1 /* 2 * w32_CancelableWait.c 3 * 4 * Description: 5 * This translation unit implements miscellaneous 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 static INLINE int 42 ptw32_cancelable_wait (HANDLE waitHandle, DWORD timeout) 43 /* 44 * ------------------------------------------------------------------- 45 * This provides an extra hook into the pthread_cancel 46 * mechanism that will allow you to wait on a Windows handle and make it a 47 * cancellation point. This function blocks until the given WIN32 handle is 48 * signaled or pthread_cancel has been called. It is implemented using 49 * WaitForMultipleObjects on 'waitHandle' and a manually reset WIN32 50 * event used to implement pthread_cancel. 51 * 52 * Given this hook it would be possible to implement more of the cancellation 53 * points. 54 * ------------------------------------------------------------------- 55 */ 56 { 57 int result; 58 pthread_t self; 59 ptw32_thread_t * sp; 60 HANDLE handles[2]; 61 DWORD nHandles = 1; 62 DWORD status; 63 64 handles[0] = waitHandle; 65 66 self = pthread_self(); 67 sp = (ptw32_thread_t *) self.p; 68 69 if (sp != NULL) 70 { 71 /* 72 * Get cancelEvent handle 73 */ 74 if (sp->cancelState == PTHREAD_CANCEL_ENABLE) 75 { 76 77 if ((handles[1] = sp->cancelEvent) != NULL) 78 { 79 nHandles++; 80 } 81 } 82 } 83 else 84 { 85 handles[1] = NULL; 86 } 87 88 status = WaitForMultipleObjects (nHandles, handles, PTW32_FALSE, timeout); 89 90 switch (status - WAIT_OBJECT_0) 91 { 92 case 0: 93 /* 94 * Got the handle. 95 * In the event that both handles are signalled, the smallest index 96 * value (us) is returned. As it has been arranged, this ensures that 97 * we don't drop a signal that we should act on (i.e. semaphore, 98 * mutex, or condition variable etc). 99 */ 100 result = 0; 101 break; 102 103 case 1: 104 /* 105 * Got cancel request. 106 * In the event that both handles are signaled, the cancel will 107 * be ignored (see case 0 comment). 108 */ 109 ResetEvent (handles[1]); 110 111 if (sp != NULL) 112 { 113 ptw32_mcs_local_node_t stateLock; 114 /* 115 * Should handle POSIX and implicit POSIX threads.. 116 * Make sure we haven't been async-canceled in the meantime. 117 */ 118 ptw32_mcs_lock_acquire (&sp->stateLock, &stateLock); 119 if (sp->state < PThreadStateCanceling) 120 { 121 sp->state = PThreadStateCanceling; 122 sp->cancelState = PTHREAD_CANCEL_DISABLE; 123 ptw32_mcs_lock_release (&stateLock); 124 ptw32_throw (PTW32_EPS_CANCEL); 125 126 /* Never reached */ 127 } 128 ptw32_mcs_lock_release (&stateLock); 129 } 130 131 /* Should never get to here. */ 132 result = EINVAL; 133 break; 134 135 default: 136 if (status == WAIT_TIMEOUT) 137 { 138 result = ETIMEDOUT; 139 } 140 else 141 { 142 result = EINVAL; 143 } 144 break; 145 } 146 147 return (result); 148 149 } /* CancelableWait */ 150 151 int 152 pthreadCancelableWait (HANDLE waitHandle) 153 { 154 return (ptw32_cancelable_wait (waitHandle, INFINITE)); 155 } 156 157 int 158 pthreadCancelableTimedWait (HANDLE waitHandle, DWORD timeout) 159 { 160 return (ptw32_cancelable_wait (waitHandle, timeout)); 161 } 162