unix/SysSemaphore.cpp
Go to the documentation of this file.
1 /*----------------------------------------------------------------------------*/
2 /* */
3 /* Copyright (c) 1995, 2004 IBM Corporation. All rights reserved. */
4 /* Copyright (c) 2005-2009 Rexx Language Association. All rights reserved. */
5 /* */
6 /* This program and the accompanying materials are made available under */
7 /* the terms of the Common Public License v1.0 which accompanies this */
8 /* distribution. A copy is also available at the following address: */
9 /* http://www.ibm.com/developerworks/oss/CPLv1.0.htm */
10 /* */
11 /* Redistribution and use in source and binary forms, with or */
12 /* without modification, are permitted provided that the following */
13 /* conditions are met: */
14 /* */
15 /* Redistributions of source code must retain the above copyright */
16 /* notice, this list of conditions and the following disclaimer. */
17 /* Redistributions in binary form must reproduce the above copyright */
18 /* notice, this list of conditions and the following disclaimer in */
19 /* the documentation and/or other materials provided with the distribution. */
20 /* */
21 /* Neither the name of Rexx Language Association nor the names */
22 /* of its contributors may be used to endorse or promote products */
23 /* derived from this software without specific prior written permission. */
24 /* */
25 /* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS */
26 /* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT */
27 /* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS */
28 /* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT */
29 /* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, */
30 /* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED */
31 /* TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, */
32 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY */
33 /* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING */
34 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS */
35 /* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
36 /* */
37 /*----------------------------------------------------------------------------*/
38 /*****************************************************************************/
39 /* REXX Unix Support */
40 /* */
41 /* Semaphore support for Unix */
42 /* */
43 /*****************************************************************************/
44 /*****************************************************************************/
45 
46 #ifdef HAVE_CONFIG_H
47  #include "config.h"
48 #endif
49 
50 #include <pthread.h>
51 #include <memory.h>
52 #include <stdio.h>
53 #ifdef AIX
54  #include <sys/sched.h>
55  #include <time.h>
56 #endif
57 
58 #if defined(OPSYS_SUN)
59  #include <sched.h>
60 #endif
61 
62 #include <errno.h>
63 
64 #include "SysSemaphore.hpp"
65 #include "SysDebug.hpp"
66 
67 
68 /* ********************************************************************** */
69 /* *** SysSemaphore *** */
70 /* ********************************************************************** */
71 
72 /**
73  * Create a semaphore with potential creation-time
74  * initialization.
75  *
76  * @param create Indicates whether the semaphore should be created now.
77  */
78 SysSemaphore::SysSemaphore(const char *variable, bool createSem)
79 {
80  semVariable = variable;
81  postedCount = 0;
82  created = false;
83 
84  if (createSem)
85  {
86  create();
87  }
88 }
89 
90 
92 {
93  int iRC = 0;
94 
95  if (!created)
96  {
97  // Clear mutex/cond prior to init
98  // this->semMutex = NULL;
99  // this->semCond = NULL;
100 
101  /* The original settings for pthread_mutexattr_settype() were:
102  AIX : PTHREAD_MUTEX_RECURSIVE
103  SUNOS: PTHREAD_MUTEX_ERRORCHECK
104  LINUX: PTHREAD_MUTEX_RECURSIVE_NP
105  */
106 
107  #if defined( HAVE_PTHREAD_MUTEXATTR_SETTYPE )
108  pthread_mutexattr_t mutexattr;
109 
110  iRC = pthread_mutexattr_init(&mutexattr);
111  if ( iRC == 0 )
112  {
113  #if defined( HAVE_PTHREAD_MUTEX_RECURSIVE_NP ) /* Linux most likely */
114  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
115  #elif defined( HAVE_PTHREAD_MUTEX_RECURSIVE )
116  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
117  #elif defined( HAVE_PTHREAD_MUTEX_ERRORCHECK )
118  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
119  #else
120  fprintf(stderr," *** ERROR: Unknown 2nd argument to pthread_mutexattr_settype()!\n");
121  #endif
122  }
123  if ( iRC == 0 )
124  {
125  iRC = pthread_mutex_init(&(this->semMutex), &mutexattr);
126  }
127  if ( iRC == 0 )
128  {
129  iRC = pthread_mutexattr_destroy(&mutexattr); /* It does not affect */
130  }
131  if ( iRC == 0 ) /* mutexes created with it */
132  {
133  iRC = pthread_cond_init(&(this->semCond), NULL);
134  }
135  #else
136  iRC = pthread_mutex_init(&(this->semMutex), NULL);
137  if ( iRC == 0 )
138  {
139  iRC = pthread_cond_init(&(this->semCond), NULL);
140  }
141  #endif
142  if ( iRC != 0 )
143  {
144  fprintf(stderr," *** ERROR: At RexxSemaphore(), pthread_mutex_init - RC = %d !\n", iRC);
145  if ( iRC == EINVAL )
146  {
147  fprintf(stderr," *** ERROR: Application was not built thread safe!\n");
148  }
149  }
150  this->postedCount = 0;
151  created = true;
152  }
153 }
154 
156 {
157  if (created)
158  {
159  pthread_cond_destroy(&(this->semCond));
160  pthread_mutex_destroy(&(this->semMutex));
161  created = false;
162  }
163 }
164 
165 
167 {
168  int rc;
169 
170  rc = pthread_mutex_lock(&(this->semMutex)); //Lock the semaphores Mutex
171  postedCount++; //Increment post count
172  rc = pthread_cond_broadcast(&(this->semCond)); //allows any threads waiting to run
173  rc = pthread_mutex_unlock(&(this->semMutex)); // Unlock access to Semaphore mutex
174 }
175 
176 void SysSemaphore::wait(const char *ds, int di)
177 {
178  int rc;
179  int schedpolicy, i_prio;
180  struct sched_param schedparam;
181 
182  pthread_getschedparam(pthread_self(), &schedpolicy, &schedparam);
183  i_prio = schedparam.sched_priority;
184  schedparam.sched_priority = 100;
185  pthread_setschedparam(pthread_self(),SCHED_OTHER, &schedparam);
186  rc = pthread_mutex_lock(&(this->semMutex)); // Lock access to semaphore
187 
188  if (this->postedCount == 0) // Has it been posted?
189  {
190 #ifdef CONCURRENCY_DEBUG
192  {
193  struct ConcurrencyInfos concurrencyInfos;
194  Utilities::GetConcurrencyInfos(concurrencyInfos);
195  dbgprintf(CONCURRENCY_TRACE "...... ... (SysSemaphore)%s.wait : before pthread_cond_wait(0x%x, 0x%x) from %s (0x%x)\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock, semVariable, &(this->semCond), &(this->semMutex), ds, di);
196  }
197 #endif
198  rc = pthread_cond_wait(&(this->semCond), &(this->semMutex)); // Nope, then wait on it.
199 #ifdef CONCURRENCY_DEBUG
201  {
202  struct ConcurrencyInfos concurrencyInfos;
203  Utilities::GetConcurrencyInfos(concurrencyInfos);
204  dbgprintf(CONCURRENCY_TRACE "...... ... (SysSemaphore)%s.wait : after pthread_cond_wait(0x%x, 0x%x) from %s (0x%x)\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock, semVariable, &(this->semCond), &(this->semMutex), ds, di);
205  }
206 #endif
207  }
208 
209  pthread_mutex_unlock(&(this->semMutex)); // Release mutex lock
210  schedparam.sched_priority = i_prio;
211  pthread_setschedparam(pthread_self(),SCHED_OTHER, &schedparam);
212 }
213 
214 bool SysSemaphore::wait(const char *ds, int di, uint32_t t) // takes a timeout in msecs
215 {
216  struct timespec timestruct;
217  time_t *Tpnt = NULL;
218 
219  int result = 0;
220  timestruct.tv_nsec = 0;
221  timestruct.tv_sec = t/1000+time(Tpnt); // convert to secs and abstime
222  pthread_mutex_lock(&(this->semMutex)); // Lock access to semaphore
223  if (!this->postedCount) // Has it been posted?
224  {
225 #ifdef CONCURRENCY_DEBUG
227  {
228  struct ConcurrencyInfos concurrencyInfos;
229  Utilities::GetConcurrencyInfos(concurrencyInfos);
230  dbgprintf(CONCURRENCY_TRACE "...... ... (SysSemaphore)%s.wait : before pthread_cond_timedwait(0x%x, 0x%x, &timestruct) from %s (0x%x)\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock, semVariable, &(this->semCond), &(this->semMutex), ds, di);
231  }
232 #endif
233  // wait with timeout
234  result = pthread_cond_timedwait(&(this->semCond),&(this->semMutex),&timestruct);
235 #ifdef CONCURRENCY_DEBUG
237  {
238  struct ConcurrencyInfos concurrencyInfos;
239  Utilities::GetConcurrencyInfos(concurrencyInfos);
240  dbgprintf(CONCURRENCY_TRACE "...... ... (SysSemaphore)%s.wait : after pthread_cond_timedwait(0x%x, 0x%x, &timestruct) from %s (0x%x)\n", concurrencyInfos.threadId, concurrencyInfos.activation, concurrencyInfos.variableDictionary, concurrencyInfos.reserveCount, concurrencyInfos.lock, semVariable, &(this->semCond), &(this->semMutex), ds, di);
241  }
242 #endif
243  }
244  pthread_mutex_unlock(&(this->semMutex)); // Release mutex lock
245  // a false return means this timed out
246  return result != ETIMEDOUT;
247 }
248 
250 {
251  pthread_mutex_lock(&(this->semMutex)); // Lock access to semaphore
252  this->postedCount = 0; // Clear value
253  pthread_mutex_unlock(&(this->semMutex)); // unlock access to semaphore
254 }
255 
256 /* ********************************************************************** */
257 /* *** SysMutex *** */
258 /* ********************************************************************** */
259 
260 /**
261  * Create a semaphore with potential creation-time
262  * initialization.
263  *
264  * @param create Indicates whether the semaphore should be created now.
265  */
266 SysMutex::SysMutex(const char *variable, bool createSem)
267 {
268  mutexVariable = variable;
269  if (createSem)
270  {
271  create();
272  }
273 }
274 
276 {
277  // don't create this multiple times
278  if (created)
279  {
280  return;
281  }
282  int iRC = 0;
283 
284 /* The original settings for pthread_mutexattr_settype() were:
285  SUNOS: PTHREAD_MUTEX_ERRORCHECK
286  LINUX: PTHREAD_MUTEX_RECURSIVE_NP
287 */
288 #if defined( HAVE_PTHREAD_MUTEXATTR_SETTYPE )
289  pthread_mutexattr_t mutexattr;
290 
291  iRC = pthread_mutexattr_init(&mutexattr);
292  if ( iRC == 0 )
293  {
294  #if defined( HAVE_PTHREAD_MUTEX_RECURSIVE_NP ) /* Linux most likely */
295  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
296  #elif defined( HAVE_PTHREAD_MUTEX_RECURSIVE )
297  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
298  #elif defined( HAVE_PTHREAD_MUTEX_ERRORCHECK )
299  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
300  #else
301  fprintf(stderr," *** ERROR: Unknown 2nd argument to pthread_mutexattr_settype()!\n");
302  #endif
303  }
304  if ( iRC == 0 )
305  {
306  iRC = pthread_mutex_init(&(this->mutexMutex), &mutexattr);
307  }
308  if ( iRC == 0 )
309  {
310  iRC = pthread_mutexattr_destroy(&mutexattr); /* It does not affect */
311  }
312 #else /* mutexes created with it */
313  iRC = pthread_mutex_init(&(this->mutexMutex), NULL);
314 #endif
315  if ( iRC != 0 )
316  {
317  fprintf(stderr," *** ERROR: At RexxMutex(), pthread_mutex_init - RC = %d !\n", iRC);
318  }
319 
320  created = true;
321 }
322 
323 
325 {
326  if (created)
327  {
328  pthread_mutex_destroy(&(this->mutexMutex));
329  created = false;
330  }
331 }
#define CONCURRENCY_TRACE
Definition: Utilities.hpp:50
pthread_mutex_t mutexMutex
SysMutex(const char *variable)
const char * mutexVariable
SysSemaphore(const char *variable)
pthread_mutex_t semMutex
const char * semVariable
void wait(const char *ds, int di)
pthread_cond_t semCond
static void GetConcurrencyInfos(struct ConcurrencyInfos &concurrencyInfos)
Definition: Utilities.cpp:61
static bool traceConcurrency()
RexxVariableDictionary * variableDictionary
Definition: Utilities.hpp:65
RexxActivation * activation
Definition: Utilities.hpp:64
unsigned short reserveCount
Definition: Utilities.hpp:66
wholenumber_t threadId
Definition: Utilities.hpp:62
void dbgprintf(const char *format,...)
unsigned int uint32_t