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