From 9628dc45e2c41980924d1de304d4ad053a9cde2a Mon Sep 17 00:00:00 2001 From: Hugo Santos Date: Wed, 9 May 2007 00:55:10 +0000 Subject: [PATCH] freebsd compat. layer: remove arbitrary limit on number of created threads available in taskqueue_start_threads. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@21077 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/libs/compat/freebsd_network/taskqueue.c | 59 ++++++++++++++------- 1 file changed, 41 insertions(+), 18 deletions(-) diff --git a/src/libs/compat/freebsd_network/taskqueue.c b/src/libs/compat/freebsd_network/taskqueue.c index 1c6583bea8..c253d46f97 100644 --- a/src/libs/compat/freebsd_network/taskqueue.c +++ b/src/libs/compat/freebsd_network/taskqueue.c @@ -13,8 +13,6 @@ #include #include -#define MAX_TASKQUEUE_THREADS 2 - struct taskqueue { char tq_name[64]; mutex tq_mutex; @@ -24,7 +22,8 @@ struct taskqueue { int tq_fast; int32 tq_spinlock; sem_id tq_sem; - thread_id tq_threads[MAX_TASKQUEUE_THREADS]; + thread_id *tq_threads; + thread_id tq_thread_storage; int tq_threadcount; }; @@ -42,17 +41,10 @@ _taskqueue_create(const char *name, int mflags, int fast, tq->tq_fast = fast; - tq->tq_sem = create_sem(0, tq->tq_name); - if (tq->tq_sem < B_OK) { - free(tq); - return tq->tq_sem; - } - if (fast) { tq->tq_spinlock = 0; } else { if (mutex_init(&tq->tq_mutex, name) < B_OK) { - delete_sem(tq->tq_sem); free(tq); return NULL; } @@ -63,6 +55,8 @@ _taskqueue_create(const char *name, int mflags, int fast, tq->tq_enqueue = enqueue; tq->tq_arg = context; + tq->tq_sem = -1; + tq->tq_threads = NULL; tq->tq_threadcount = 0; return tq; @@ -108,9 +102,15 @@ tq_handle_thread(void *data) cpu_status cpu_state; struct task *t; int pending; + sem_id sem; + + /* just a synchronization point */ + tq_lock(tq, &cpu_state); + sem = tq->tq_sem; + tq_unlock(tq, cpu_state); while (1) { - status_t status = acquire_sem(tq->tq_sem); + status_t status = acquire_sem(sem); if (status < B_OK) break; @@ -137,8 +137,24 @@ _taskqueue_start_threads(struct taskqueue **tqp, int count, int prio, if (count == 0) return -1; - if (count > MAX_TASKQUEUE_THREADS) - panic("_taskqueue_start_threads, too many threads requested"); + if (tq->tq_threads != NULL) + return -1; + + if (count == 1) { + tq->tq_threads = &tq->tq_thread_storage; + } else { + tq->tq_threads = malloc(sizeof(thread_id) * count); + if (tq->tq_threads == NULL) + return B_NO_MEMORY; + } + + tq->tq_sem = create_sem(0, tq->tq_name); + if (tq->tq_sem < B_OK) { + if (count > 1) + free(tq->tq_threads); + tq->tq_threads = NULL; + return tq->tq_sem; + } for (i = 0; i < count; i++) { tq->tq_threads[i] = spawn_kernel_thread(tq_handle_thread, tq->tq_name, @@ -147,6 +163,10 @@ _taskqueue_start_threads(struct taskqueue **tqp, int count, int prio, status_t status = tq->tq_threads[i]; for (j = 0; j < i; j++) kill_thread(tq->tq_threads[j]); + if (count > 1) + free(tq->tq_threads); + tq->tq_threads = NULL; + delete_sem(tq->tq_sem); return status; } } @@ -164,10 +184,10 @@ int taskqueue_start_threads(struct taskqueue **tqp, int count, int prio, const char *format, ...) { - /* we assume that start_threads is called in a sane place, and - * thus don't lock. This is mostly due to the fact that if the - * TQ is 'fast', locking it disables interrupts... and then we - * can't create semaphores, threads and bananas. */ + /* we assume that start_threads is called in a sane place, and thus + * don't need to be locked. This is mostly due to the fact that if + * the TQ is 'fast', locking the TQ disables interrupts... and then + * we can't create semaphores, threads and bananas. */ /* cpu_status state; */ char name[64]; @@ -201,6 +221,9 @@ taskqueue_free(struct taskqueue *tq) status_t status; wait_for_thread(tq->tq_threads[i], &status); } + + if (tq->tq_threadcount > 1) + free(tq->tq_threads); } free(tq); @@ -214,7 +237,7 @@ taskqueue_drain(struct taskqueue *tq, struct task *task) tq_lock(tq, &status); if (task->ta_pending != 0) - panic("unimplemented, taskqueue drain"); + UNIMPLEMENTED(); tq_unlock(tq, status); }