1 // SPDX-License-Identifier: LGPL-2.1-or-later
3 * Copyright (C) 2020-2021 Paul Cercueil <paul@crapouillou.net>
6 #include "blockcache.h"
8 #include "lightrec-private.h"
9 #include "memmanager.h"
15 #include <stdatomic.h>
21 struct slist_elm slist;
25 struct lightrec_state *state;
26 pthread_mutex_t mutex;
28 struct slist_elm reap_list;
34 struct reaper *lightrec_reaper_init(struct lightrec_state *state)
36 struct reaper *reaper;
39 reaper = lightrec_malloc(state, MEM_FOR_LIGHTREC, sizeof(*reaper));
41 pr_err("Cannot create reaper: Out of memory\n");
45 reaper->state = state;
46 reaper->running = false;
48 slist_init(&reaper->reap_list);
50 ret = pthread_mutex_init(&reaper->mutex, NULL);
52 pr_err("Cannot init mutex variable: %d\n", ret);
56 ret = pthread_cond_init(&reaper->cond, NULL);
58 pr_err("Cannot init cond variable: %d\n", ret);
59 goto err_destroy_mutex;
65 pthread_mutex_destroy(&reaper->mutex);
67 lightrec_free(reaper->state, MEM_FOR_LIGHTREC, sizeof(*reaper), reaper);
71 void lightrec_reaper_destroy(struct reaper *reaper)
73 lightrec_reaper_reap(reaper);
75 pthread_cond_destroy(&reaper->cond);
76 pthread_mutex_destroy(&reaper->mutex);
77 lightrec_free(reaper->state, MEM_FOR_LIGHTREC, sizeof(*reaper), reaper);
80 int lightrec_reaper_add(struct reaper *reaper, reap_func_t f, void *data)
82 struct reaper_elm *reaper_elm;
83 struct slist_elm *elm;
86 pthread_mutex_lock(&reaper->mutex);
88 for (elm = reaper->reap_list.next; elm; elm = elm->next) {
89 reaper_elm = container_of(elm, struct reaper_elm, slist);
91 if (reaper_elm->data == data)
95 reaper_elm = lightrec_malloc(reaper->state, MEM_FOR_LIGHTREC,
98 pr_err("Cannot add reaper entry: Out of memory\n");
103 reaper_elm->func = f;
104 reaper_elm->data = data;
105 slist_append(&reaper->reap_list, &reaper_elm->slist);
108 pthread_mutex_unlock(&reaper->mutex);
112 static bool lightrec_reaper_can_reap(struct reaper *reaper)
114 return !atomic_load_explicit(&reaper->sem, memory_order_relaxed);
117 void lightrec_reaper_reap(struct reaper *reaper)
119 struct reaper_elm *reaper_elm;
120 struct slist_elm *elm;
122 pthread_mutex_lock(&reaper->mutex);
124 while (lightrec_reaper_can_reap(reaper) &&
125 !!(elm = slist_first(&reaper->reap_list))) {
126 slist_remove(&reaper->reap_list, elm);
127 reaper->running = true;
128 pthread_mutex_unlock(&reaper->mutex);
130 reaper_elm = container_of(elm, struct reaper_elm, slist);
132 (*reaper_elm->func)(reaper->state, reaper_elm->data);
134 lightrec_free(reaper->state, MEM_FOR_LIGHTREC,
135 sizeof(*reaper_elm), reaper_elm);
137 pthread_mutex_lock(&reaper->mutex);
138 reaper->running = false;
139 pthread_cond_broadcast(&reaper->cond);
142 pthread_mutex_unlock(&reaper->mutex);
145 void lightrec_reaper_pause(struct reaper *reaper)
147 atomic_fetch_add_explicit(&reaper->sem, 1, memory_order_relaxed);
149 pthread_mutex_lock(&reaper->mutex);
150 while (reaper->running)
151 pthread_cond_wait(&reaper->cond, &reaper->mutex);
152 pthread_mutex_unlock(&reaper->mutex);
155 void lightrec_reaper_continue(struct reaper *reaper)
157 atomic_fetch_sub_explicit(&reaper->sem, 1, memory_order_relaxed);