xref: /dflybsd-src/lib/libthread_xu/thread/thr_kern.c (revision 6e42f7e2096165a28bab14a23c399e4b1a8bb531)
171b3fa15SDavid Xu /*
271b3fa15SDavid Xu  * Copyright (c) 2005 David Xu <davidxu@freebsd.org>
371b3fa15SDavid Xu  * All rights reserved.
471b3fa15SDavid Xu  *
571b3fa15SDavid Xu  * Redistribution and use in source and binary forms, with or without
671b3fa15SDavid Xu  * modification, are permitted provided that the following conditions
771b3fa15SDavid Xu  * are met:
871b3fa15SDavid Xu  * 1. Redistributions of source code must retain the above copyright
971b3fa15SDavid Xu  *    notice unmodified, this list of conditions, and the following
1071b3fa15SDavid Xu  *    disclaimer.
1171b3fa15SDavid Xu  * 2. Redistributions in binary form must reproduce the above copyright
1271b3fa15SDavid Xu  *    notice, this list of conditions and the following disclaimer in the
1371b3fa15SDavid Xu  *    documentation and/or other materials provided with the distribution.
1471b3fa15SDavid Xu  *
1571b3fa15SDavid Xu  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1671b3fa15SDavid Xu  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1771b3fa15SDavid Xu  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1871b3fa15SDavid Xu  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1971b3fa15SDavid Xu  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
2071b3fa15SDavid Xu  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
2171b3fa15SDavid Xu  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
2271b3fa15SDavid Xu  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2371b3fa15SDavid Xu  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
2471b3fa15SDavid Xu  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
2571b3fa15SDavid Xu  */
2671b3fa15SDavid Xu 
27*6e42f7e2Szrj #include <sys/single_threaded.h>
2871b3fa15SDavid Xu #include <sys/types.h>
2971b3fa15SDavid Xu #include <sys/signalvar.h>
30a31d0705SMatthew Dillon #include <sys/rtprio.h>
310d9899e7SSepherosa Ziehau #include <sys/lwp.h>
3271b3fa15SDavid Xu #include <pthread.h>
336be5672cSzrj 
3471b3fa15SDavid Xu #include "thr_private.h"
3571b3fa15SDavid Xu 
3671b3fa15SDavid Xu /*#define DEBUG_THREAD_KERN */
3771b3fa15SDavid Xu #ifdef DEBUG_THREAD_KERN
3871b3fa15SDavid Xu #define DBG_MSG		stdout_debug
3971b3fa15SDavid Xu #else
4071b3fa15SDavid Xu #define DBG_MSG(x...)
4171b3fa15SDavid Xu #endif
4271b3fa15SDavid Xu 
4371b3fa15SDavid Xu /*
4471b3fa15SDavid Xu  * This is called when the first thread (other than the initial
4571b3fa15SDavid Xu  * thread) is created.
46fcaa7a3aSMatthew Dillon  *
4798247283SMatthew Dillon  * NOTE: we no longer call _thrd_rtld_fini here.
4871b3fa15SDavid Xu  */
4971b3fa15SDavid Xu int
_thr_setthreaded(int threaded)5071b3fa15SDavid Xu _thr_setthreaded(int threaded)
5171b3fa15SDavid Xu {
5271b3fa15SDavid Xu 	if (((threaded == 0) ^ (__isthreaded == 0)) == 0)
5371b3fa15SDavid Xu 		return (0);
5471b3fa15SDavid Xu 	__isthreaded = threaded;
55*6e42f7e2Szrj 	if (__libc_single_threaded != 0)
56*6e42f7e2Szrj 		__libc_single_threaded = 0;	/* sticky version */
5750caca1aSMatthew Dillon 	_rtld_setthreaded(threaded);
5898247283SMatthew Dillon #if 0
5998247283SMatthew Dillon 	/* save for later. */
60fcaa7a3aSMatthew Dillon 	if (threaded != 0)
6198247283SMatthew Dillon 		/* blah */ ;
6298247283SMatthew Dillon 	else
6398247283SMatthew Dillon 		/* blah */ ;
6498247283SMatthew Dillon #endif
6571b3fa15SDavid Xu 	return (0);
6671b3fa15SDavid Xu }
6771b3fa15SDavid Xu 
6871b3fa15SDavid Xu void
_thr_signal_block(pthread_t curthread)69940be950Szrj _thr_signal_block(pthread_t curthread)
7071b3fa15SDavid Xu {
7171b3fa15SDavid Xu 	sigset_t set;
7271b3fa15SDavid Xu 
7371b3fa15SDavid Xu 	if (curthread->sigblock > 0) {
7471b3fa15SDavid Xu 		curthread->sigblock++;
7571b3fa15SDavid Xu 		return;
7671b3fa15SDavid Xu 	}
7771b3fa15SDavid Xu 	SIGFILLSET(set);
7871b3fa15SDavid Xu 	SIGDELSET(set, SIGBUS);
7971b3fa15SDavid Xu 	SIGDELSET(set, SIGILL);
8071b3fa15SDavid Xu 	SIGDELSET(set, SIGFPE);
8171b3fa15SDavid Xu 	SIGDELSET(set, SIGSEGV);
8271b3fa15SDavid Xu 	SIGDELSET(set, SIGTRAP);
8371b3fa15SDavid Xu 	__sys_sigprocmask(SIG_BLOCK, &set, &curthread->sigmask);
8471b3fa15SDavid Xu 	curthread->sigblock++;
8571b3fa15SDavid Xu }
8671b3fa15SDavid Xu 
8771b3fa15SDavid Xu void
_thr_signal_unblock(pthread_t curthread)88940be950Szrj _thr_signal_unblock(pthread_t curthread)
8971b3fa15SDavid Xu {
9071b3fa15SDavid Xu 	if (--curthread->sigblock == 0)
9171b3fa15SDavid Xu 		__sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL);
9271b3fa15SDavid Xu }
9371b3fa15SDavid Xu 
9471b3fa15SDavid Xu void
_thr_assert_lock_level(void)95d797dc5dSSascha Wildner _thr_assert_lock_level(void)
9671b3fa15SDavid Xu {
9771b3fa15SDavid Xu 	PANIC("locklevel <= 0");
9871b3fa15SDavid Xu }
9971b3fa15SDavid Xu 
10071b3fa15SDavid Xu int
_thr_send_sig(pthread_t thread,int sig)101940be950Szrj _thr_send_sig(pthread_t thread, int sig)
10271b3fa15SDavid Xu {
103fbf2ef09SSimon Schubert 	return (lwp_kill(-1, thread->tid, sig));
10471b3fa15SDavid Xu }
10571b3fa15SDavid Xu 
10671b3fa15SDavid Xu int
_thr_get_tid(void)107d797dc5dSSascha Wildner _thr_get_tid(void)
10871b3fa15SDavid Xu {
109fbf2ef09SSimon Schubert 	return (lwp_gettid());
11071b3fa15SDavid Xu }
111a31d0705SMatthew Dillon 
112a31d0705SMatthew Dillon /*
113a31d0705SMatthew Dillon  * We don't use the priority for SCHED_OTHER, but
114a31d0705SMatthew Dillon  * some programs may depend on getting an error when
115a31d0705SMatthew Dillon  * setting a priority that is out of the range returned
116a31d0705SMatthew Dillon  * by sched_get_priority_{min,max}. Not sure if this
117a31d0705SMatthew Dillon  * falls into implementation defined behavior or not.
118a31d0705SMatthew Dillon  */
119a31d0705SMatthew Dillon int
_thr_set_sched_other_prio(pthread_t pth __unused,int prio)120940be950Szrj _thr_set_sched_other_prio(pthread_t pth __unused, int prio)
121a31d0705SMatthew Dillon {
122a31d0705SMatthew Dillon 	static int max, min, init_status;
123a31d0705SMatthew Dillon 
124a31d0705SMatthew Dillon 	/*
125a31d0705SMatthew Dillon 	 * switch (init_status) {
126a31d0705SMatthew Dillon 	 * case 0: need initialization
127a31d0705SMatthew Dillon 	 * case 1: initialization successful
128a31d0705SMatthew Dillon 	 * case 2: initialization failed. can't happen, but if
129a31d0705SMatthew Dillon 	 *	   it does, accept all and hope for the best.
130a31d0705SMatthew Dillon 	 *	   It's not like we use it anyway.
131a31d0705SMatthew Dillon 	 */
132a31d0705SMatthew Dillon 	if (!init_status) {
133a31d0705SMatthew Dillon 		int tmp = errno;
134a31d0705SMatthew Dillon 
135a31d0705SMatthew Dillon 		errno = 0;
136a31d0705SMatthew Dillon 		init_status = 1;
137a31d0705SMatthew Dillon 		if (((min = sched_get_priority_min(SCHED_OTHER)) == -1) &&
138a31d0705SMatthew Dillon 								(errno != 0))
139a31d0705SMatthew Dillon 			init_status = 2;
140a31d0705SMatthew Dillon 		if (((max = sched_get_priority_max(SCHED_OTHER)) == -1) &&
141a31d0705SMatthew Dillon 								(errno != 0))
142a31d0705SMatthew Dillon 			init_status = 2;
143a31d0705SMatthew Dillon 		errno = tmp;
144a31d0705SMatthew Dillon 	}
145a31d0705SMatthew Dillon 	if ((init_status == 2) || ((prio >= min) && (prio <= max))) {
146a31d0705SMatthew Dillon 		return 0;
147a31d0705SMatthew Dillon 	}
14805bc0b36SSimon Schubert 	errno = ENOTSUP;
149a31d0705SMatthew Dillon 	return -1;
150a31d0705SMatthew Dillon }
151a31d0705SMatthew Dillon 
152a31d0705SMatthew Dillon int
_rtp_to_schedparam(const struct rtprio * rtp,int * policy,struct sched_param * param)153a31d0705SMatthew Dillon _rtp_to_schedparam(const struct rtprio *rtp, int *policy,
154a31d0705SMatthew Dillon 	struct sched_param *param)
155a31d0705SMatthew Dillon {
156a31d0705SMatthew Dillon 	switch(rtp->type) {
157a31d0705SMatthew Dillon 	case RTP_PRIO_REALTIME:
158a31d0705SMatthew Dillon 		*policy = SCHED_RR;
159a31d0705SMatthew Dillon 		param->sched_priority = RTP_PRIO_MAX - rtp->prio;
160a31d0705SMatthew Dillon 		break;
161a31d0705SMatthew Dillon 	case RTP_PRIO_FIFO:
162a31d0705SMatthew Dillon 		*policy = SCHED_FIFO;
163a31d0705SMatthew Dillon 		param->sched_priority = RTP_PRIO_MAX - rtp->prio;
164a31d0705SMatthew Dillon 		break;
165a31d0705SMatthew Dillon 	default:
166a31d0705SMatthew Dillon 		*policy = SCHED_OTHER;
167a31d0705SMatthew Dillon 		param->sched_priority = 0;
168a31d0705SMatthew Dillon 		break;
169a31d0705SMatthew Dillon 	}
170a31d0705SMatthew Dillon 	return (0);
171a31d0705SMatthew Dillon }
172a31d0705SMatthew Dillon 
173a31d0705SMatthew Dillon int
_schedparam_to_rtp(int policy,const struct sched_param * param,struct rtprio * rtp)174a31d0705SMatthew Dillon _schedparam_to_rtp(int policy, const struct sched_param *param,
175a31d0705SMatthew Dillon 	struct rtprio *rtp)
176a31d0705SMatthew Dillon {
177a31d0705SMatthew Dillon 	switch(policy) {
178a31d0705SMatthew Dillon 	case SCHED_RR:
179a31d0705SMatthew Dillon 		rtp->type = RTP_PRIO_REALTIME;
180a31d0705SMatthew Dillon 		rtp->prio = RTP_PRIO_MAX - param->sched_priority;
181a31d0705SMatthew Dillon 		break;
182a31d0705SMatthew Dillon 	case SCHED_FIFO:
183a31d0705SMatthew Dillon 		rtp->type = RTP_PRIO_FIFO;
184a31d0705SMatthew Dillon 		rtp->prio = RTP_PRIO_MAX - param->sched_priority;
185a31d0705SMatthew Dillon 		break;
186a31d0705SMatthew Dillon 	case SCHED_OTHER:
187a31d0705SMatthew Dillon 	default:
188a31d0705SMatthew Dillon 		rtp->type = RTP_PRIO_NORMAL;
189a31d0705SMatthew Dillon 		rtp->prio = 0;
190a31d0705SMatthew Dillon 		break;
191a31d0705SMatthew Dillon 	}
192a31d0705SMatthew Dillon 	return (0);
193a31d0705SMatthew Dillon }
194a31d0705SMatthew Dillon 
195a31d0705SMatthew Dillon int
_thr_getscheduler(lwpid_t lwpid,int * policy,struct sched_param * param)196a31d0705SMatthew Dillon _thr_getscheduler(lwpid_t lwpid, int *policy, struct sched_param *param)
197a31d0705SMatthew Dillon {
198940be950Szrj 	pthread_t curthread = tls_get_curthread();
199a31d0705SMatthew Dillon 	struct rtprio rtp;
200a31d0705SMatthew Dillon 	int ret;
201a31d0705SMatthew Dillon 
202a31d0705SMatthew Dillon 	if (lwpid == curthread->tid)
203a31d0705SMatthew Dillon 		lwpid = -1;
204a31d0705SMatthew Dillon 	ret = lwp_rtprio(RTP_LOOKUP, 0, lwpid, &rtp);
205a31d0705SMatthew Dillon 	if (ret == -1)
206a31d0705SMatthew Dillon 		return (ret);
207a31d0705SMatthew Dillon 	_rtp_to_schedparam(&rtp, policy, param);
208a31d0705SMatthew Dillon 	return (0);
209a31d0705SMatthew Dillon }
210a31d0705SMatthew Dillon 
211a31d0705SMatthew Dillon int
_thr_setscheduler(lwpid_t lwpid,int policy,const struct sched_param * param)212a31d0705SMatthew Dillon _thr_setscheduler(lwpid_t lwpid, int policy, const struct sched_param *param)
213a31d0705SMatthew Dillon {
214940be950Szrj 	pthread_t curthread = tls_get_curthread();
215a31d0705SMatthew Dillon 	struct rtprio rtp;
216a31d0705SMatthew Dillon 
217a31d0705SMatthew Dillon 	if (lwpid == curthread->tid)
218a31d0705SMatthew Dillon 		lwpid = -1;
219a31d0705SMatthew Dillon 	_schedparam_to_rtp(policy, param, &rtp);
220a31d0705SMatthew Dillon 	return (lwp_rtprio(RTP_SET, 0, lwpid, &rtp));
221a31d0705SMatthew Dillon }
222