erofs-utils: lib: get rid of pthread_cancel() for workqueue
authorGao Xiang <hsiangkao@linux.alibaba.com>
Wed, 11 Dec 2024 02:50:09 +0000 (10:50 +0800)
committerGao Xiang <hsiangkao@linux.alibaba.com>
Wed, 11 Dec 2024 08:02:56 +0000 (16:02 +0800)
Since bionic (Android's libc) does not have pthread_cancel(),
call erofs_destroy_workqueue() when initialization fails.

Reviewed-by: Yifan Zhao <zhaoyifan@sjtu.edu.cn>
Cc: Kelvin Zhang <zhangkelvin@google.com>
Signed-off-by: Gao Xiang <hsiangkao@linux.alibaba.com>
Link: https://lore.kernel.org/r/20241211025009.3393476-1-hsiangkao@linux.alibaba.com
lib/compress.c
lib/workqueue.c

index c67984384165e695978047aec726fc15ffc87486..65edd007ca721e54683fee331c2e0f4e708885e0 100644 (file)
@@ -1790,7 +1790,9 @@ int z_erofs_compress_init(struct erofs_sb_info *sbi, struct erofs_buffer_head *s
                                            cfg.c_mt_workers << 2,
                                            z_erofs_mt_wq_tls_alloc,
                                            z_erofs_mt_wq_tls_free);
-               z_erofs_mt_enabled = !ret;
+               if (ret)
+                       return ret;
+               z_erofs_mt_enabled = true;
        }
        pthread_mutex_init(&g_ictx.mutex, NULL);
        pthread_cond_init(&g_ictx.cond, NULL);
index 47cec9be7f327a8e1d85d4dcaa8e48e05551daf5..18ee0f9f239feebf30a4332afac1c52f5a10214b 100644 (file)
@@ -15,9 +15,9 @@ static void *worker_thread(void *arg)
        while (true) {
                pthread_mutex_lock(&wq->lock);
 
-               while (wq->job_count == 0 && !wq->shutdown)
+               while (!wq->job_count && !wq->shutdown)
                        pthread_cond_wait(&wq->cond_empty, &wq->lock);
-               if (wq->job_count == 0 && wq->shutdown) {
+               if (!wq->job_count && wq->shutdown) {
                        pthread_mutex_unlock(&wq->lock);
                        break;
                }
@@ -40,6 +40,30 @@ static void *worker_thread(void *arg)
        return NULL;
 }
 
+int erofs_destroy_workqueue(struct erofs_workqueue *wq)
+{
+       if (!wq)
+               return -EINVAL;
+
+       pthread_mutex_lock(&wq->lock);
+       wq->shutdown = true;
+       pthread_cond_broadcast(&wq->cond_empty);
+       pthread_mutex_unlock(&wq->lock);
+
+       while (wq->nworker) {
+               int ret = -pthread_join(wq->workers[wq->nworker - 1], NULL);
+
+               if (ret)
+                       return ret;
+               --wq->nworker;
+       }
+       free(wq->workers);
+       pthread_mutex_destroy(&wq->lock);
+       pthread_cond_destroy(&wq->cond_empty);
+       pthread_cond_destroy(&wq->cond_full);
+       return 0;
+}
+
 int erofs_alloc_workqueue(struct erofs_workqueue *wq, unsigned int nworker,
                          unsigned int max_jobs, erofs_wq_func_t on_start,
                          erofs_wq_func_t on_exit)
@@ -51,7 +75,6 @@ int erofs_alloc_workqueue(struct erofs_workqueue *wq, unsigned int nworker,
                return -EINVAL;
 
        wq->head = wq->tail = NULL;
-       wq->nworker = nworker;
        wq->max_jobs = max_jobs;
        wq->job_count = 0;
        wq->shutdown = false;
@@ -66,15 +89,14 @@ int erofs_alloc_workqueue(struct erofs_workqueue *wq, unsigned int nworker,
                return -ENOMEM;
 
        for (i = 0; i < nworker; i++) {
-               ret = pthread_create(&wq->workers[i], NULL, worker_thread, wq);
-               if (ret) {
-                       while (i)
-                               pthread_cancel(wq->workers[--i]);
-                       free(wq->workers);
-                       return ret;
-               }
+               ret = -pthread_create(&wq->workers[i], NULL, worker_thread, wq);
+               if (ret)
+                       break;
        }
-       return 0;
+       wq->nworker = i;
+       if (ret)
+               erofs_destroy_workqueue(wq);
+       return ret;
 }
 
 int erofs_queue_work(struct erofs_workqueue *wq, struct erofs_work *work)
@@ -99,25 +121,3 @@ int erofs_queue_work(struct erofs_workqueue *wq, struct erofs_work *work)
        pthread_mutex_unlock(&wq->lock);
        return 0;
 }
-
-int erofs_destroy_workqueue(struct erofs_workqueue *wq)
-{
-       unsigned int i;
-
-       if (!wq)
-               return -EINVAL;
-
-       pthread_mutex_lock(&wq->lock);
-       wq->shutdown = true;
-       pthread_cond_broadcast(&wq->cond_empty);
-       pthread_mutex_unlock(&wq->lock);
-
-       for (i = 0; i < wq->nworker; i++)
-               pthread_join(wq->workers[i], NULL);
-
-       free(wq->workers);
-       pthread_mutex_destroy(&wq->lock);
-       pthread_cond_destroy(&wq->cond_empty);
-       pthread_cond_destroy(&wq->cond_full);
-       return 0;
-}