1 /*--------------------------------------------------------------- 2 * Copyright (c) 1999,2000,2001,2002,2003 3 * The Board of Trustees of the University of Illinois 4 * All Rights Reserved. 5 *--------------------------------------------------------------- 6 * Permission is hereby granted, free of charge, to any person 7 * obtaining a copy of this software (Iperf) and associated 8 * documentation files (the "Software"), to deal in the Software 9 * without restriction, including without limitation the 10 * rights to use, copy, modify, merge, publish, distribute, 11 * sublicense, and/or sell copies of the Software, and to permit 12 * persons to whom the Software is furnished to do 13 * so, subject to the following conditions: 14 * 15 * 16 * Redistributions of source code must retain the above 17 * copyright notice, this list of conditions and 18 * the following disclaimers. 19 * 20 * 21 * Redistributions in binary form must reproduce the above 22 * copyright notice, this list of conditions and the following 23 * disclaimers in the documentation and/or other materials 24 * provided with the distribution. 25 * 26 * 27 * Neither the names of the University of Illinois, NCSA, 28 * nor the names of its contributors may be used to endorse 29 * or promote products derived from this Software without 30 * specific prior written permission. 31 * 32 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 33 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 34 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 35 * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTIBUTORS OR COPYRIGHT 36 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 37 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 38 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE 39 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 40 * ________________________________________________________________ 41 * National Laboratory for Applied Network Research 42 * National Center for Supercomputing Applications 43 * University of Illinois at Urbana-Champaign 44 * http://www.ncsa.uiuc.edu 45 * ________________________________________________________________ 46 * 47 * Condition.h 48 * by Mark Gates <mgates@nlanr.net> 49 * ------------------------------------------------------------------- 50 * An abstract class for waiting on a condition variable. If 51 * threads are not available, this does nothing. 52 * ------------------------------------------------------------------- */ 53 54 #ifndef CONDITION_H 55 #define CONDITION_H 56 57 #include "headers.h" 58 #include "Mutex.h" 59 #include "util.h" 60 61 #if defined( HAVE_POSIX_THREAD ) 62 struct Condition { 63 pthread_cond_t mCondition; 64 pthread_mutex_t mMutex; 65 }; 66 #elif defined( HAVE_WIN32_THREAD ) 67 struct Condition { 68 HANDLE mCondition; 69 HANDLE mMutex; 70 }; 71 #else 72 struct Condition { 73 int mCondition; 74 int mMutex; 75 }; 76 #endif 77 78 struct AwaitMutex { 79 struct Condition await; 80 int ready; 81 }; 82 83 struct BarrierMutex { 84 struct Condition await; 85 struct timeval release_time; 86 int count; 87 int timeout; 88 }; 89 90 struct ReferenceMutex { 91 Mutex lock; 92 int count; 93 int maxcount; 94 }; 95 96 #define Condition_Lock( Cond ) Mutex_Lock( &Cond.mMutex ) 97 98 #define Condition_Unlock( Cond ) Mutex_Unlock( &Cond.mMutex ) 99 100 // initialize condition 101 #if defined( HAVE_POSIX_THREAD ) 102 #define Condition_Initialize( Cond ) do { \ 103 Mutex_Initialize( &(Cond)->mMutex ); \ 104 pthread_cond_init( &(Cond)->mCondition, NULL ); \ 105 } while ( 0 ) 106 #elif defined( HAVE_WIN32_THREAD ) 107 // set all conditions to be broadcast 108 // unfortunately in Win32 you have to know at creation 109 // whether the signal is broadcast or not. 110 #define Condition_Initialize( Cond ) do { \ 111 Mutex_Initialize( &(Cond)->mMutex ); \ 112 (Cond)->mCondition = CreateEvent( NULL, 1, 0, NULL ); \ 113 } while ( 0 ) 114 #else 115 #define Condition_Initialize( Cond ) 116 #endif 117 118 // destroy condition 119 #if defined( HAVE_POSIX_THREAD ) 120 #define Condition_Destroy( Cond ) do { \ 121 pthread_cond_destroy( &(Cond)->mCondition ); \ 122 Mutex_Destroy( &(Cond)->mMutex ); \ 123 } while ( 0 ) 124 #elif defined( HAVE_WIN32_THREAD ) 125 #define Condition_Destroy( Cond ) do { \ 126 CloseHandle( (Cond)->mCondition ); \ 127 Mutex_Destroy( &(Cond)->mMutex ); \ 128 } while ( 0 ) 129 #else 130 #define Condition_Destroy( Cond ) 131 #endif 132 133 #define Condition_Destroy_Reference(Ref) do { \ 134 Mutex_Destroy(&(Ref)->lock); \ 135 } while ( 0 ) 136 137 #if defined (HAVE_CLOCK_GETTIME) 138 #define SETABSTIME(ts, seconds) do { \ 139 clock_gettime(CLOCK_REALTIME, &ts); \ 140 ts.tv_sec += seconds; \ 141 } while (0) 142 #else 143 #define SETABSTIME(ts, seconds) do { \ 144 struct timeval t1; \ 145 gettimeofday(&t1, NULL); 146 ts.tv_sec = t1.tv_sec + inSeconds; \ 147 ts.tv_nsec = t1.tv_sec * 1000; \ 148 } while (0) 149 #endif 150 151 // sleep this thread, waiting for condition signal 152 #if defined( HAVE_POSIX_THREAD ) 153 #define Condition_Wait( Cond ) pthread_cond_wait( &(Cond)->mCondition, &(Cond)->mMutex ) 154 #elif defined( HAVE_WIN32_THREAD ) 155 // atomically release mutex and wait on condition, 156 // then re-acquire the mutex 157 #define Condition_Wait( Cond ) do { \ 158 SignalObjectAndWait( (Cond)->mMutex, (Cond)->mCondition, INFINITE, 0 ); \ 159 Mutex_Lock( &(Cond)->mMutex ); \ 160 } while ( 0 ) 161 #else 162 #define Condition_Wait( Cond ) 163 #endif 164 165 // sleep this thread, waiting for condition signal, 166 // but bound sleep time by the relative time inSeconds. 167 #if defined( HAVE_POSIX_THREAD ) 168 #define Condition_TimedWait( Cond, inSeconds ) do { \ 169 struct timespec absTimeout; \ 170 SETABSTIME(absTimeout, inSeconds); \ 171 pthread_cond_timedwait( &(Cond)->mCondition, &(Cond)->mMutex, &absTimeout ); \ 172 } while ( 0 ) 173 #define Condition_TimedLock( Cond, inSeconds ) do { \ 174 struct timespec absTimeout; \ 175 SETABSTIME(absTimeout, inSeconds); \ 176 pthread_mutex_timedlock(&Cond.mMutex, &absTimeout); \ 177 } while ( 0 ) 178 #elif defined( HAVE_WIN32_THREAD ) 179 // atomically release mutex and wait on condition, 180 // then re-acquire the mutex 181 #define Condition_TimedWait( Cond, inSeconds ) do { \ 182 SignalObjectAndWait( (Cond)->mMutex, (Cond)->mCondition, inSeconds*1000, false ); \ 183 Mutex_Lock( &(Cond)->mMutex ); \ 184 } while ( 0 ) 185 #else 186 #define Condition_TimedWait( Cond, inSeconds ) 187 #endif 188 189 // send a condition signal to wake one thread waiting on condition 190 // in Win32, this actually wakes up all threads, same as Broadcast 191 // use PulseEvent to auto-reset the signal after waking all threads 192 #if defined( HAVE_POSIX_THREAD ) 193 #define Condition_Signal( Cond ) pthread_cond_signal( &(Cond)->mCondition ) 194 #elif defined( HAVE_WIN32_THREAD ) 195 #define Condition_Signal( Cond ) PulseEvent( (Cond)->mCondition ) 196 #else 197 #define Condition_Signal( Cond ) 198 #endif 199 200 // send a condition signal to wake all threads waiting on condition 201 #if defined( HAVE_POSIX_THREAD ) 202 #define Condition_Broadcast( Cond ) pthread_cond_broadcast( &(Cond)->mCondition ) 203 #elif defined( HAVE_WIN32_THREAD ) 204 #define Condition_Broadcast( Cond ) PulseEvent( (Cond)->mCondition ) 205 #else 206 #define Condition_Broadcast( Cond ) 207 #endif 208 209 #endif // CONDITION_H 210