1 /* 2 * pthreads_delay_np.c 3 * 4 * Description: 5 * This translation unit implements non-portable thread functions. 6 * 7 * -------------------------------------------------------------------------- 8 * 9 * Pthreads-win32 - POSIX Threads Library for Win32 10 * Copyright(C) 1998 John E. Bossom 11 * Copyright(C) 1999,2005 Pthreads-win32 contributors 12 * 13 * Contact Email: rpj (at) callisto.canberra.edu.au 14 * 15 * The current list of contributors is contained 16 * in the file CONTRIBUTORS included with the source 17 * code distribution. The list can also be seen at the 18 * following World Wide Web location: 19 * http://sources.redhat.com/pthreads-win32/contributors.html 20 * 21 * This library is free software; you can redistribute it and/or 22 * modify it under the terms of the GNU Lesser General Public 23 * License as published by the Free Software Foundation; either 24 * version 2 of the License, or (at your option) any later version. 25 * 26 * This library is distributed in the hope that it will be useful, 27 * but WITHOUT ANY WARRANTY; without even the implied warranty of 28 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 29 * Lesser General Public License for more details. 30 * 31 * You should have received a copy of the GNU Lesser General Public 32 * License along with this library in the file COPYING.LIB; 33 * if not, write to the Free Software Foundation, Inc., 34 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA 35 */ 36 37 #include "pthread.h" 38 #include "implement.h" 39 40 /* 41 * pthread_delay_np 42 * 43 * DESCRIPTION 44 * 45 * This routine causes a thread to delay execution for a specific period of time. 46 * This period ends at the current time plus the specified interval. The routine 47 * will not return before the end of the period is reached, but may return an 48 * arbitrary amount of time after the period has gone by. This can be due to 49 * system load, thread priorities, and system timer granularity. 50 * 51 * Specifying an interval of zero (0) seconds and zero (0) nanoseconds is 52 * allowed and can be used to force the thread to give up the processor or to 53 * deliver a pending cancelation request. 54 * 55 * The timespec structure contains the following two fields: 56 * 57 * tv_sec is an integer number of seconds. 58 * tv_nsec is an integer number of nanoseconds. 59 * 60 * Return Values 61 * 62 * If an error condition occurs, this routine returns an integer value indicating 63 * the type of error. Possible return values are as follows: 64 * 65 * 0 66 * Successful completion. 67 * [EINVAL] 68 * The value specified by interval is invalid. 69 * 70 * Example 71 * 72 * The following code segment would wait for 5 and 1/2 seconds 73 * 74 * struct timespec tsWait; 75 * int intRC; 76 * 77 * tsWait.tv_sec = 5; 78 * tsWait.tv_nsec = 500000000L; 79 * intRC = pthread_delay_np(&tsWait); 80 */ 81 int 82 pthread_delay_np (struct timespec *interval) 83 { 84 DWORD wait_time; 85 DWORD secs_in_millisecs; 86 DWORD millisecs; 87 DWORD status; 88 pthread_t self; 89 ptw32_thread_t * sp; 90 91 if (interval == NULL) 92 { 93 return EINVAL; 94 } 95 96 if (interval->tv_sec == 0L && interval->tv_nsec == 0L) 97 { 98 pthread_testcancel (); 99 Sleep (0); 100 pthread_testcancel (); 101 return (0); 102 } 103 104 /* convert secs to millisecs */ 105 secs_in_millisecs = (DWORD)interval->tv_sec * 1000L; 106 107 /* convert nanosecs to millisecs (rounding up) */ 108 millisecs = (interval->tv_nsec + 999999L) / 1000000L; 109 110 #if defined(__WATCOMC__) 111 #pragma disable_message (124) 112 #endif 113 114 /* 115 * Most compilers will issue a warning 'comparison always 0' 116 * because the variable type is unsigned, but we need to keep this 117 * for some reason I can't recall now. 118 */ 119 if (0 > (wait_time = secs_in_millisecs + millisecs)) 120 { 121 return EINVAL; 122 } 123 124 #if defined(__WATCOMC__) 125 #pragma enable_message (124) 126 #endif 127 128 if (NULL == (self = pthread_self ()).p) 129 { 130 return ENOMEM; 131 } 132 133 sp = (ptw32_thread_t *) self.p; 134 135 if (sp->cancelState == PTHREAD_CANCEL_ENABLE) 136 { 137 /* 138 * Async cancelation won't catch us until wait_time is up. 139 * Deferred cancelation will cancel us immediately. 140 */ 141 if (WAIT_OBJECT_0 == 142 (status = WaitForSingleObject (sp->cancelEvent, wait_time))) 143 { 144 ptw32_mcs_local_node_t stateLock; 145 /* 146 * Canceling! 147 */ 148 ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); 149 if (sp->state < PThreadStateCanceling) 150 { 151 sp->state = PThreadStateCanceling; 152 sp->cancelState = PTHREAD_CANCEL_DISABLE; 153 ptw32_mcs_lock_release (&stateLock); 154 155 ptw32_throw (PTW32_EPS_CANCEL); 156 } 157 158 ptw32_mcs_lock_release (&stateLock); 159 return ESRCH; 160 } 161 else if (status != WAIT_TIMEOUT) 162 { 163 return EINVAL; 164 } 165 } 166 else 167 { 168 Sleep (wait_time); 169 } 170 171 return (0); 172 } 173