X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=deps%2Flightrec%2Freaper.c;h=777b9970454a628cbc2ff9c542ac7d6edca4f902;hb=0096868ecb1c7403b76847010d4fb6a1a827110b;hp=377685c1ed10e2c53de627e50cc36eee9fd62efb;hpb=a34093eb63d1645fd2de9b412efe2587df9fdb3f;p=pcsx_rearmed.git diff --git a/deps/lightrec/reaper.c b/deps/lightrec/reaper.c index 377685c1..777b9970 100644 --- a/deps/lightrec/reaper.c +++ b/deps/lightrec/reaper.c @@ -1,15 +1,6 @@ +// SPDX-License-Identifier: LGPL-2.1-or-later /* - * Copyright (C) 2020 Paul Cercueil - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. + * Copyright (C) 2020-2021 Paul Cercueil */ #include "blockcache.h" @@ -21,6 +12,7 @@ #include #include +#include #include struct reaper_elm { @@ -32,7 +24,11 @@ struct reaper_elm { struct reaper { struct lightrec_state *state; pthread_mutex_t mutex; + pthread_cond_t cond; struct slist_elm reap_list; + + bool running; + atomic_uint sem; }; struct reaper *lightrec_reaper_init(struct lightrec_state *state) @@ -47,21 +43,36 @@ struct reaper *lightrec_reaper_init(struct lightrec_state *state) } reaper->state = state; + reaper->running = false; + reaper->sem = 0; slist_init(&reaper->reap_list); ret = pthread_mutex_init(&reaper->mutex, NULL); if (ret) { pr_err("Cannot init mutex variable: %d\n", ret); - lightrec_free(reaper->state, MEM_FOR_LIGHTREC, - sizeof(*reaper), reaper); - return NULL; + goto err_free_reaper; + } + + ret = pthread_cond_init(&reaper->cond, NULL); + if (ret) { + pr_err("Cannot init cond variable: %d\n", ret); + goto err_destroy_mutex; } return reaper; + +err_destroy_mutex: + pthread_mutex_destroy(&reaper->mutex); +err_free_reaper: + lightrec_free(reaper->state, MEM_FOR_LIGHTREC, sizeof(*reaper), reaper); + return NULL; } void lightrec_reaper_destroy(struct reaper *reaper) { + lightrec_reaper_reap(reaper); + + pthread_cond_destroy(&reaper->cond); pthread_mutex_destroy(&reaper->mutex); lightrec_free(reaper->state, MEM_FOR_LIGHTREC, sizeof(*reaper), reaper); } @@ -98,6 +109,11 @@ out_unlock: return ret; } +static bool lightrec_reaper_can_reap(struct reaper *reaper) +{ + return !atomic_load_explicit(&reaper->sem, memory_order_relaxed); +} + void lightrec_reaper_reap(struct reaper *reaper) { struct reaper_elm *reaper_elm; @@ -105,19 +121,38 @@ void lightrec_reaper_reap(struct reaper *reaper) pthread_mutex_lock(&reaper->mutex); - while (!!(elm = slist_first(&reaper->reap_list))) { + while (lightrec_reaper_can_reap(reaper) && + !!(elm = slist_first(&reaper->reap_list))) { slist_remove(&reaper->reap_list, elm); + reaper->running = true; pthread_mutex_unlock(&reaper->mutex); reaper_elm = container_of(elm, struct reaper_elm, slist); - (*reaper_elm->func)(reaper_elm->data); + (*reaper_elm->func)(reaper->state, reaper_elm->data); lightrec_free(reaper->state, MEM_FOR_LIGHTREC, sizeof(*reaper_elm), reaper_elm); pthread_mutex_lock(&reaper->mutex); + reaper->running = false; + pthread_cond_broadcast(&reaper->cond); } pthread_mutex_unlock(&reaper->mutex); } + +void lightrec_reaper_pause(struct reaper *reaper) +{ + atomic_fetch_add_explicit(&reaper->sem, 1, memory_order_relaxed); + + pthread_mutex_lock(&reaper->mutex); + while (reaper->running) + pthread_cond_wait(&reaper->cond, &reaper->mutex); + pthread_mutex_unlock(&reaper->mutex); +} + +void lightrec_reaper_continue(struct reaper *reaper) +{ + atomic_fetch_sub_explicit(&reaper->sem, 1, memory_order_relaxed); +}