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
31 #include <sys/types.h>
32 #include <sys/sysctl.h>
34 #include "thr_private.h"
36 LT10_COMPAT_PRIVATE(_pthread_getconcurrency);
37 LT10_COMPAT_DEFAULT(pthread_getconcurrency);
38 LT10_COMPAT_PRIVATE(_pthread_setconcurrency);
39 LT10_COMPAT_DEFAULT(pthread_setconcurrency);
41 /*#define DEBUG_CONCURRENCY */
42 #ifdef DEBUG_CONCURRENCY
43 #define DBG_MSG stdout_debug
50 __weak_reference(_pthread_getconcurrency, pthread_getconcurrency);
51 __weak_reference(_pthread_setconcurrency, pthread_setconcurrency);
54 _pthread_getconcurrency(void)
60 _pthread_setconcurrency(int new_level)
66 else if (new_level == level)
68 else if (new_level == 0) {
71 } else if ((_kse_isthreaded() == 0) && (_kse_setthreaded(1) != 0)) {
72 DBG_MSG("Can't enable threading.\n");
75 ret = _thr_setconcurrency(new_level);
83 _thr_setconcurrency(int new_level)
85 struct pthread *curthread;
86 struct kse *newkse, *kse;
93 * Turn on threaded mode, if failed, it is unnecessary to
96 if (_kse_isthreaded() == 0 && _kse_setthreaded(1))
100 curthread = _get_curthread();
101 /* Race condition, but so what. */
102 kse_count = _kse_initial->k_kseg->kg_ksecount;
103 if (new_level > kse_count) {
104 for (i = kse_count; i < new_level; i++) {
105 newkse = _kse_alloc(curthread, 0);
106 if (newkse == NULL) {
107 DBG_MSG("Can't alloc new KSE.\n");
111 newkse->k_kseg = _kse_initial->k_kseg;
112 newkse->k_schedq = _kse_initial->k_schedq;
113 newkse->k_curthread = NULL;
114 crit = _kse_critical_enter();
115 KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg);
116 TAILQ_INSERT_TAIL(&newkse->k_kseg->kg_kseq,
118 newkse->k_kseg->kg_ksecount++;
119 newkse->k_flags |= KF_STARTED;
120 KSE_SCHED_UNLOCK(curthread->kse, newkse->k_kseg);
121 if (kse_create(&newkse->k_kcb->kcb_kmbx, 0) != 0) {
122 KSE_SCHED_LOCK(curthread->kse, newkse->k_kseg);
123 TAILQ_REMOVE(&newkse->k_kseg->kg_kseq,
125 newkse->k_kseg->kg_ksecount--;
126 KSE_SCHED_UNLOCK(curthread->kse,
128 _kse_critical_leave(crit);
129 _kse_free(curthread, newkse);
130 DBG_MSG("kse_create syscall failed.\n");
134 _kse_critical_leave(crit);
137 } else if (new_level < kse_count) {
139 crit = _kse_critical_enter();
140 KSE_SCHED_LOCK(curthread->kse, _kse_initial->k_kseg);
141 /* Count the number of active KSEs */
142 TAILQ_FOREACH(kse, &_kse_initial->k_kseg->kg_kseq, k_kgqe) {
143 if ((kse->k_flags & KF_TERMINATED) == 0)
146 /* Reduce the number of active KSEs appropriately. */
147 kse = TAILQ_FIRST(&_kse_initial->k_kseg->kg_kseq);
148 while ((kse != NULL) && (kse_count > new_level)) {
149 if ((kse != _kse_initial) &&
150 ((kse->k_flags & KF_TERMINATED) == 0)) {
151 kse->k_flags |= KF_TERMINATED;
153 /* Wakup the KSE in case it is idle. */
154 kse_wakeup(&kse->k_kcb->kcb_kmbx);
156 kse = TAILQ_NEXT(kse, k_kgqe);
158 KSE_SCHED_UNLOCK(curthread->kse, _kse_initial->k_kseg);
159 _kse_critical_leave(crit);
165 _thr_setmaxconcurrency(void)
172 ret = sysctlbyname("kern.threads.virtual_cpu", &vcpu, &len, NULL, 0);
173 if (ret == 0 && vcpu > 0)
174 ret = _thr_setconcurrency(vcpu);