1 /* 2 * Copyright (c) 2003 Jeffrey Roberson <jeff@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 * $FreeBSD$ 27 */ 28 29 #include <sys/cdefs.h> 30 #include <sys/types.h> 31 #include <sys/signalvar.h> 32 #include <sys/time.h> 33 #include <sys/timespec.h> 34 #include <pthread.h> 35 #include <signal.h> 36 #include <errno.h> 37 38 #include "thr_private.h" 39 40 /* XXX Why can't I get this from time.h? :-( */ 41 #define timespecsub(vvp, uvp) \ 42 do { \ 43 (vvp)->tv_sec -= (uvp)->tv_sec; \ 44 (vvp)->tv_nsec -= (uvp)->tv_nsec; \ 45 if ((vvp)->tv_nsec < 0) { \ 46 (vvp)->tv_sec--; \ 47 (vvp)->tv_nsec += 1000000000; \ 48 } \ 49 } while (0) 50 51 static sigset_t restore; 52 53 void 54 GIANT_LOCK(pthread_t pthread) 55 { 56 sigset_t set; 57 sigset_t sav; 58 int error; 59 60 /* 61 * Block all signals. 62 */ 63 SIGFILLSET(set); 64 65 /* 66 * We can not use the global 'restore' set until after we have 67 * acquired the giant lock. 68 */ 69 #if 0 70 error = __sys_sigprocmask(SIG_SETMASK, &set, &sav); 71 if (error) { 72 _thread_printf(0, "GIANT_LOCK: sig err %d\n", errno); 73 abort(); 74 } 75 #endif 76 77 error = umtx_lock(&_giant_mutex, pthread->thr_id); 78 if (error) { 79 _thread_printf(0, "GIANT_LOCK: %d\n", errno); 80 abort(); 81 } 82 83 restore = sav; 84 } 85 86 void 87 GIANT_UNLOCK(pthread_t pthread) 88 { 89 sigset_t set; 90 int error; 91 92 /* 93 * restore is protected by giant. We could restore our signal state 94 * incorrectly if someone else set restore between unlocking giant 95 * and restoring the signal mask. To avoid this we cache a copy prior 96 * to the unlock. 97 */ 98 set = restore; 99 100 error = umtx_unlock(&_giant_mutex, pthread->thr_id); 101 if (error) { 102 _thread_printf(0, "GIANT_UNLOCK: %d\n", errno); 103 abort(); 104 } 105 106 #if 0 107 /* 108 * Restore signals. 109 */ 110 error = __sys_sigprocmask(SIG_SETMASK, &set, NULL); 111 if (error) { 112 _thread_printf(0, "GIANT_UNLOCK: sig err %d\n", errno); 113 abort(); 114 } 115 #endif 116 } 117 118 int 119 _thread_suspend(pthread_t pthread, struct timespec *abstime) 120 { 121 struct timespec remaining; 122 struct timespec *ts; 123 siginfo_t info; 124 sigset_t set; 125 int error; 126 127 /* 128 * Catch SIGTHR. 129 */ 130 SIGFILLSET(set); 131 SIGDELSET(set, SIGTHR); 132 133 /* 134 * Compute the remainder of the run time. 135 */ 136 if (abstime) { 137 struct timespec now; 138 struct timeval tv; 139 140 GET_CURRENT_TOD(tv); 141 TIMEVAL_TO_TIMESPEC(&tv, &now); 142 143 remaining = *abstime; 144 timespecsub(&remaining, &now); 145 ts = &remaining; 146 } else 147 ts = NULL; 148 149 error = sigtimedwait(&set, &info, ts); 150 if (error == -1) 151 error = errno; 152 153 return (error); 154 } 155