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
191  if (Utilities::traceConcurrency()) dbgprintf(CONCURRENCY_TRACE "...... ... ", Utilities::currentThreadId(), NULL, NULL, 0, ' ');
192  dbgprintf("(SysSemaphore)%s.wait : before pthread_cond_wait(0x%x, 0x%x) from %s (0x%x)\n", semVariable, &(this->semCond), &(this->semMutex), ds, di);
193 #endif
194  rc = pthread_cond_wait(&(this->semCond), &(this->semMutex)); // Nope, then wait on it.
195 #ifdef CONCURRENCY_DEBUG
196  if (Utilities::traceConcurrency()) dbgprintf(CONCURRENCY_TRACE "...... ... ", Utilities::currentThreadId(), NULL, NULL, 0, ' ');
197  dbgprintf("(SysSemaphore)%s.wait : after pthread_cond_wait(0x%x, 0x%x) from %s (0x%x)\n", semVariable, &(this->semCond), &(this->semMutex), ds, di);
198 #endif
199  }
200 
201  pthread_mutex_unlock(&(this->semMutex)); // Release mutex lock
202  schedparam.sched_priority = i_prio;
203  pthread_setschedparam(pthread_self(),SCHED_OTHER, &schedparam);
204 }
205 
206 bool SysSemaphore::wait(const char *ds, int di, uint32_t t) // takes a timeout in msecs
207 {
208  struct timespec timestruct;
209  time_t *Tpnt = NULL;
210 
211  int result = 0;
212  timestruct.tv_nsec = 0;
213  timestruct.tv_sec = t/1000+time(Tpnt); // convert to secs and abstime
214  pthread_mutex_lock(&(this->semMutex)); // Lock access to semaphore
215  if (!this->postedCount) // Has it been posted?
216  {
217 #ifdef CONCURRENCY_DEBUG
218  if (Utilities::traceConcurrency()) dbgprintf(CONCURRENCY_TRACE "...... ... ", Utilities::currentThreadId(), NULL, NULL, 0, ' ');
219  dbgprintf("(SysSemaphore)%s.wait : before pthread_cond_timedwait(0x%x, 0x%x, &timestruct) from %s (0x%x)\n", semVariable, &(this->semCond), &(this->semMutex), ds, di);
220 #endif
221  // wait with timeout
222  result = pthread_cond_timedwait(&(this->semCond),&(this->semMutex),&timestruct);
223 #ifdef CONCURRENCY_DEBUG
224  if (Utilities::traceConcurrency()) dbgprintf(CONCURRENCY_TRACE "...... ... ", Utilities::currentThreadId(), NULL, NULL, 0, ' ');
225  dbgprintf("(SysSemaphore)%s.wait : after pthread_cond_timedwait(0x%x, 0x%x, &timestruct) from %s (0x%x)\n", semVariable, &(this->semCond), &(this->semMutex), ds, di);
226 #endif
227  }
228  pthread_mutex_unlock(&(this->semMutex)); // Release mutex lock
229  // a false return means this timed out
230  return result != ETIMEDOUT;
231 }
232 
234 {
235  pthread_mutex_lock(&(this->semMutex)); // Lock access to semaphore
236  this->postedCount = 0; // Clear value
237  pthread_mutex_unlock(&(this->semMutex)); // unlock access to semaphore
238 }
239 
240 /* ********************************************************************** */
241 /* *** SysMutex *** */
242 /* ********************************************************************** */
243 
244 /**
245  * Create a semaphore with potential creation-time
246  * initialization.
247  *
248  * @param create Indicates whether the semaphore should be created now.
249  */
250 SysMutex::SysMutex(const char *variable, bool createSem)
251 {
252  mutexVariable = variable;
253  if (createSem)
254  {
255  create();
256  }
257 }
258 
260 {
261  // don't create this multiple times
262  if (created)
263  {
264  return;
265  }
266  int iRC = 0;
267 
268 /* The original settings for pthread_mutexattr_settype() were:
269  SUNOS: PTHREAD_MUTEX_ERRORCHECK
270  LINUX: PTHREAD_MUTEX_RECURSIVE_NP
271 */
272 #if defined( HAVE_PTHREAD_MUTEXATTR_SETTYPE )
273  pthread_mutexattr_t mutexattr;
274 
275  iRC = pthread_mutexattr_init(&mutexattr);
276  if ( iRC == 0 )
277  {
278  #if defined( HAVE_PTHREAD_MUTEX_RECURSIVE_NP ) /* Linux most likely */
279  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE_NP);
280  #elif defined( HAVE_PTHREAD_MUTEX_RECURSIVE )
281  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE);
282  #elif defined( HAVE_PTHREAD_MUTEX_ERRORCHECK )
283  iRC = pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_ERRORCHECK);
284  #else
285  fprintf(stderr," *** ERROR: Unknown 2nd argument to pthread_mutexattr_settype()!\n");
286  #endif
287  }
288  if ( iRC == 0 )
289  {
290  iRC = pthread_mutex_init(&(this->mutexMutex), &mutexattr);
291  }
292  if ( iRC == 0 )
293  {
294  iRC = pthread_mutexattr_destroy(&mutexattr); /* It does not affect */
295  }
296 #else /* mutexes created with it */
297  iRC = pthread_mutex_init(&(this->mutexMutex), NULL);
298 #endif
299  if ( iRC != 0 )
300  {
301  fprintf(stderr," *** ERROR: At RexxMutex(), pthread_mutex_init - RC = %d !\n", iRC);
302  }
303 
304  created = true;
305 }
306 
307 
309 {
310  if (created)
311  {
312  pthread_mutex_destroy(&(this->mutexMutex));
313  created = false;
314  }
315 }
#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 wholenumber_t currentThreadId()
static bool traceConcurrency()
void dbgprintf(const char *format,...)
unsigned int uint32_t