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