Update lightrec 20220910 (#686)
[pcsx_rearmed.git] / deps / lightrec / reaper.c
index 2e32cae..777b997 100644 (file)
@@ -24,8 +24,10 @@ 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;
 };
 
@@ -41,22 +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);
 }
@@ -108,6 +124,7 @@ void lightrec_reaper_reap(struct reaper *reaper)
        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);
@@ -118,6 +135,8 @@ void lightrec_reaper_reap(struct reaper *reaper)
                              sizeof(*reaper_elm), reaper_elm);
 
                pthread_mutex_lock(&reaper->mutex);
+               reaper->running = false;
+               pthread_cond_broadcast(&reaper->cond);
        }
 
        pthread_mutex_unlock(&reaper->mutex);
@@ -126,6 +145,11 @@ void lightrec_reaper_reap(struct reaper *reaper)
 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)