2 * Copyright (c) 2003 Daniel M. Eischen <deischen@freebsd.org>
3 * Copyright (c) 2003 Sergey Osokin <osa@freebsd.org.ru>.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Neither the name of the author nor the names of any co-contributors
12 * may be used to endorse or promote products derived from this software
13 * without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include "namespace.h"
33 #include <sys/types.h>
34 #include <sys/sysctl.h>
35 #include "un-namespace.h"
37 #include "thr_private.h"
39 /*#define DEBUG_CONCURRENCY */
40 #ifdef DEBUG_CONCURRENCY
41 #define DBG_MSG stdout_debug
48 __weak_reference(_pthread_getconcurrency, pthread_getconcurrency);
49 __weak_reference(_pthread_setconcurrency, pthread_setconcurrency);
52 _pthread_getconcurrency(void)
58 _pthread_setconcurrency(int new_level)
64 else if (new_level == level)
66 else if (new_level == 0) {
69 } else if ((_kse_isthreaded() == 0) && (_kse_setthreaded(1) != 0)) {
70 DBG_MSG("Can't enable threading.\n");
73 ret = _thr_setconcurrency(new_level);
81 _thr_setconcurrency(int new_level)
83 struct pthread *curthread;
84 struct kse *newkse, *kse;
91 * Turn on threaded mode, if failed, it is unnecessary to
94 if (_kse_isthreaded() == 0 && _kse_setthreaded(1))
98 curthread = _get_curthread();
99 /* Race condition, but so what. */
100 kse_count = _kse_initial->k_kseg->kg_ksecount;
101 if (new_level > kse_count) {
102 for (i = kse_count; i < new_level; i++) {
103 newkse = _kse_alloc(curthread, 0);
104 if (newkse == NULL) {
105 DBG_MSG("Can't alloc new KSE.\n");
109 newkse->k_kseg = _kse_initial->k_kseg;
110 newkse->k_schedq = _kse_initial->k_schedq;
111 newkse->k_curthread = NULL;
112 crit = _kse_critical_enter();
113 KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg);
114 TAILQ_INSERT_TAIL(&newkse->k_kseg->kg_kseq,
116 newkse->k_kseg->kg_ksecount++;
117 newkse->k_flags |= KF_STARTED;
118 KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg);
119 if (kse_create(&newkse->k_kcb->kcb_kmbx, 0) != 0) {
120 KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg);
121 TAILQ_REMOVE(&newkse->k_kseg->kg_kseq,
123 newkse->k_kseg->kg_ksecount--;
124 KSE_SCHED_UNLOCK(curthread->kse,
126 _kse_critical_leave(crit);
127 _kse_free(curthread, newkse);
128 DBG_MSG("kse_create syscall failed.\n");
132 _kse_critical_leave(crit);
135 } else if (new_level < kse_count) {
137 crit = _kse_critical_enter();
138 KSE_SCHED_LOCK(curthread->kse, _kse_initial->k_kseg);
139 /* Count the number of active KSEs */
140 TAILQ_FOREACH(kse, &_kse_initial->k_kseg->kg_kseq, k_kgqe) {
141 if ((kse->k_flags & KF_TERMINATED) == 0)
144 /* Reduce the number of active KSEs appropriately. */
145 kse = TAILQ_FIRST(&_kse_initial->k_kseg->kg_kseq);
146 while ((kse != NULL) && (kse_count > new_level)) {
147 if ((kse != _kse_initial) &&
148 ((kse->k_flags & KF_TERMINATED) == 0)) {
149 kse->k_flags |= KF_TERMINATED;
151 /* Wakup the KSE in case it is idle. */
152 kse_wakeup(&kse->k_kcb->kcb_kmbx);
154 kse = TAILQ_NEXT(kse, k_kgqe);
156 KSE_SCHED_UNLOCK(curthread->kse, _kse_initial->k_kseg);
157 _kse_critical_leave(crit);
163 _thr_setmaxconcurrency(void)
170 ret = sysctlbyname("kern.threads.virtual_cpu", &vcpu, &len, NULL, 0);
171 if (ret == 0 && vcpu > 0)
172 ret = _thr_setconcurrency(vcpu);