1 /* 2 * Copyright (c) 2005 David Xu <davidxu@freebsd.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice unmodified, this list of conditions, and the following 10 * disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 * 26 * $DragonFly: src/lib/libthread_xu/thread/thr_kern.c,v 1.4 2008/01/05 13:38:08 corecode Exp $ 27 */ 28 29 #include <sys/cdefs.h> 30 #include <sys/types.h> 31 #include <sys/signalvar.h> 32 #include <sys/rtprio.h> 33 #include <pthread.h> 34 #include "thr_private.h" 35 36 /*#define DEBUG_THREAD_KERN */ 37 #ifdef DEBUG_THREAD_KERN 38 #define DBG_MSG stdout_debug 39 #else 40 #define DBG_MSG(x...) 41 #endif 42 43 /* 44 * This is called when the first thread (other than the initial 45 * thread) is created. 46 */ 47 int 48 _thr_setthreaded(int threaded) 49 { 50 if (((threaded == 0) ^ (__isthreaded == 0)) == 0) 51 return (0); 52 53 __isthreaded = threaded; 54 #if 0 55 if (threaded != 0) { 56 _thr_rtld_init(); 57 } else { 58 _thr_rtld_fini(); 59 } 60 #endif 61 return (0); 62 } 63 64 void 65 _thr_signal_block(struct pthread *curthread) 66 { 67 sigset_t set; 68 69 if (curthread->sigblock > 0) { 70 curthread->sigblock++; 71 return; 72 } 73 SIGFILLSET(set); 74 SIGDELSET(set, SIGBUS); 75 SIGDELSET(set, SIGILL); 76 SIGDELSET(set, SIGFPE); 77 SIGDELSET(set, SIGSEGV); 78 SIGDELSET(set, SIGTRAP); 79 __sys_sigprocmask(SIG_BLOCK, &set, &curthread->sigmask); 80 curthread->sigblock++; 81 } 82 83 void 84 _thr_signal_unblock(struct pthread *curthread) 85 { 86 if (--curthread->sigblock == 0) 87 __sys_sigprocmask(SIG_SETMASK, &curthread->sigmask, NULL); 88 } 89 90 void 91 _thr_assert_lock_level() 92 { 93 PANIC("locklevel <= 0"); 94 } 95 96 int 97 _thr_send_sig(struct pthread *thread, int sig) 98 { 99 return (lwp_kill(-1, thread->tid, sig)); 100 } 101 102 int 103 _thr_get_tid() 104 { 105 return (lwp_gettid()); 106 } 107 108 /* 109 * We don't use the priority for SCHED_OTHER, but 110 * some programs may depend on getting an error when 111 * setting a priority that is out of the range returned 112 * by sched_get_priority_{min,max}. Not sure if this 113 * falls into implementation defined behavior or not. 114 */ 115 int 116 _thr_set_sched_other_prio(struct pthread *pth, int prio) 117 { 118 static int max, min, init_status; 119 120 /* 121 * switch (init_status) { 122 * case 0: need initialization 123 * case 1: initialization successful 124 * case 2: initialization failed. can't happen, but if 125 * it does, accept all and hope for the best. 126 * It's not like we use it anyway. 127 */ 128 if (!init_status) { 129 int tmp = errno; 130 131 errno = 0; 132 init_status = 1; 133 if (((min = sched_get_priority_min(SCHED_OTHER)) == -1) && 134 (errno != 0)) 135 init_status = 2; 136 if (((max = sched_get_priority_max(SCHED_OTHER)) == -1) && 137 (errno != 0)) 138 init_status = 2; 139 errno = tmp; 140 } 141 if ((init_status == 2) || ((prio >= min) && (prio <= max))) { 142 return 0; 143 } 144 errno = ENOTSUP; 145 return -1; 146 } 147 148 int 149 _rtp_to_schedparam(const struct rtprio *rtp, int *policy, 150 struct sched_param *param) 151 { 152 switch(rtp->type) { 153 case RTP_PRIO_REALTIME: 154 *policy = SCHED_RR; 155 param->sched_priority = RTP_PRIO_MAX - rtp->prio; 156 break; 157 case RTP_PRIO_FIFO: 158 *policy = SCHED_FIFO; 159 param->sched_priority = RTP_PRIO_MAX - rtp->prio; 160 break; 161 default: 162 *policy = SCHED_OTHER; 163 param->sched_priority = 0; 164 break; 165 } 166 return (0); 167 } 168 169 int 170 _schedparam_to_rtp(int policy, const struct sched_param *param, 171 struct rtprio *rtp) 172 { 173 switch(policy) { 174 case SCHED_RR: 175 rtp->type = RTP_PRIO_REALTIME; 176 rtp->prio = RTP_PRIO_MAX - param->sched_priority; 177 break; 178 case SCHED_FIFO: 179 rtp->type = RTP_PRIO_FIFO; 180 rtp->prio = RTP_PRIO_MAX - param->sched_priority; 181 break; 182 case SCHED_OTHER: 183 default: 184 rtp->type = RTP_PRIO_NORMAL; 185 rtp->prio = 0; 186 break; 187 } 188 return (0); 189 } 190 191 int 192 _thr_getscheduler(lwpid_t lwpid, int *policy, struct sched_param *param) 193 { 194 struct pthread *curthread = tls_get_curthread(); 195 struct rtprio rtp; 196 int ret; 197 198 if (lwpid == curthread->tid) 199 lwpid = -1; 200 ret = lwp_rtprio(RTP_LOOKUP, 0, lwpid, &rtp); 201 if (ret == -1) 202 return (ret); 203 _rtp_to_schedparam(&rtp, policy, param); 204 return (0); 205 } 206 207 int 208 _thr_setscheduler(lwpid_t lwpid, int policy, const struct sched_param *param) 209 { 210 struct pthread *curthread = tls_get_curthread(); 211 struct rtprio rtp; 212 213 if (lwpid == curthread->tid) 214 lwpid = -1; 215 _schedparam_to_rtp(policy, param, &rtp); 216 return (lwp_rtprio(RTP_SET, 0, lwpid, &rtp)); 217 } 218