From 6deabb439b7870759f16db0c9a3968e3755bf61a Mon Sep 17 00:00:00 2001 From: deischen Date: Mon, 28 Apr 2003 23:56:12 +0000 Subject: o Don't add a scope system thread's KSE to the list of available KSEs when it's thread exits; allow the GC handler to do that. o Make spinlock/spinlock critical regions. The following were submitted by davidxu o Alow thr_switch() to take a null mailbox argument. o Better protect cancellation checks. o Don't set KSE specific data when creating new KSEs; rely on the first upcall of the KSE to set it. o Add the ability to set the maximum concurrency level and do this automatically. We should have a way to enable/disable this with some sort of tunable because some applications may not want this to be the default. o Hold the scheduling lock across thread switch calls. o If scheduling of a thread fails, make sure to remove it from the list of active threads. o Better protect accesses to a joining threads when the target thread is exited and detached. o Remove some macro definitions that are now provided by . o Don't leave the library in threaded mode if creation of the initial KSE fails. o Wakeup idle KSEs when there are threads ready to run. o Maintain the number of threads active in the priority queue. --- lib/libpthread/thread/thr_concurrency.c | 108 +++++++++++++++++++------------- 1 file changed, 63 insertions(+), 45 deletions(-) (limited to 'lib/libpthread/thread/thr_concurrency.c') diff --git a/lib/libpthread/thread/thr_concurrency.c b/lib/libpthread/thread/thr_concurrency.c index a4b055f..db84121 100644 --- a/lib/libpthread/thread/thr_concurrency.c +++ b/lib/libpthread/thread/thr_concurrency.c @@ -28,6 +28,8 @@ */ #include #include +#include +#include #include "thr_private.h" @@ -52,14 +54,8 @@ _pthread_getconcurrency(void) int _pthread_setconcurrency(int new_level) { - struct pthread *curthread; - struct kse *newkse; - kse_critical_t crit; - int kse_count; - int i; int ret; - if (new_level < 0) ret = EINVAL; else if (new_level == level) @@ -71,50 +67,72 @@ _pthread_setconcurrency(int new_level) DBG_MSG("Can't enable threading.\n"); ret = EAGAIN; } else { - ret = 0; - curthread = _get_curthread(); - /* Race condition, but so what. */ - kse_count = _kse_initial->k_kseg->kg_ksecount; - for (i = kse_count; i < new_level; i++) { - newkse = _kse_alloc(curthread); - if (newkse == NULL) { - DBG_MSG("Can't alloc new KSE.\n"); - ret = EAGAIN; - break; - } - newkse->k_kseg = _kse_initial->k_kseg; - newkse->k_schedq = _kse_initial->k_schedq; - newkse->k_curthread = NULL; - crit = _kse_critical_enter(); + ret = _thr_setconcurrency(new_level); + if (ret == 0) + level = new_level; + } + return (ret); +} + +int +_thr_setconcurrency(int new_level) +{ + struct pthread *curthread; + struct kse *newkse; + kse_critical_t crit; + int kse_count; + int i; + int ret; + + ret = 0; + curthread = _get_curthread(); + /* Race condition, but so what. */ + kse_count = _kse_initial->k_kseg->kg_ksecount; + for (i = kse_count; i < new_level; i++) { + newkse = _kse_alloc(curthread); + if (newkse == NULL) { + DBG_MSG("Can't alloc new KSE.\n"); + ret = EAGAIN; + break; + } + newkse->k_kseg = _kse_initial->k_kseg; + newkse->k_schedq = _kse_initial->k_schedq; + newkse->k_curthread = NULL; + crit = _kse_critical_enter(); + KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg); + TAILQ_INSERT_TAIL(&newkse->k_kseg->kg_kseq, + newkse, k_kgqe); + newkse->k_kseg->kg_ksecount++; + KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg); + if (kse_create(&newkse->k_mbx, 0) != 0) { KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg); - TAILQ_INSERT_TAIL(&newkse->k_kseg->kg_kseq, + TAILQ_REMOVE(&newkse->k_kseg->kg_kseq, newkse, k_kgqe); - newkse->k_kseg->kg_ksecount++; + newkse->k_kseg->kg_ksecount--; KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg); - if (_ksd_setprivate(&_kse_initial->k_ksd) != 0) { - /* This should never happen. */ - PANIC("pthread_setconcurrency: Unable to " - "set KSE specific data"); - } - newkse->k_flags |= KF_INITIALIZED; - if (kse_create(&newkse->k_mbx, 0) != 0) { - _ksd_setprivate(&curthread->kse->k_ksd); - KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg); - TAILQ_REMOVE(&newkse->k_kseg->kg_kseq, - newkse, k_kgqe); - newkse->k_kseg->kg_ksecount--; - KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg); - _kse_critical_leave(crit); - _kse_free(curthread, newkse); - DBG_MSG("kse_create syscall failed.\n"); - ret = EAGAIN; - break; - } - _ksd_setprivate(&curthread->kse->k_ksd); + _kse_critical_leave(crit); + _kse_free(curthread, newkse); + DBG_MSG("kse_create syscall failed.\n"); + ret = EAGAIN; + break; + } else { _kse_critical_leave(crit); } - if (ret == 0) - level = new_level; } return (ret); } + +int +_thr_setmaxconcurrency(void) +{ + int vcpu; + int len; + int ret; + + len = sizeof(vcpu); + ret = sysctlbyname("kern.threads.virtual_cpu", &vcpu, &len, NULL, NULL); + if (ret == 0 && vcpu > 0) + ret = _thr_setconcurrency(vcpu); + return (ret); +} + -- cgit v1.1