Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / OS_NS_Thread.inl
blobe20c7077f8863a4d1202daea509e4ea85fcf43bd
1 // -*- C++ -*-
2 #include "ace/OS_NS_macros.h"
3 // for timespec_t, perhaps move it to os_time.h
4 #include "ace/Time_Value.h"
5 #include "ace/OS_NS_sys_mman.h"
6 #include "ace/OS_NS_sys_time.h"
7 #include "ace/OS_NS_string.h"
8 #include "ace/OS_NS_unistd.h"
9 #include "ace/OS_NS_stdio.h"
10 #include "ace/OS_NS_errno.h"
12 #if defined (ACE_USES_FIFO_SEM)
13 #  include "ace/OS_NS_sys_stat.h"
14 #  include "ace/OS_NS_sys_select.h"
15 #  include "ace/OS_NS_fcntl.h"
16 #  include "ace/Handle_Set.h"
17 # endif /* ACE_USES_FIFO_SEM */
19 #if defined (ACE_HAS_ALLOC_HOOKS)
20 # include "ace/Malloc_Base.h"
21 #endif /* ACE_HAS_ALLOC_HOOKS */
23 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
25 /*****************************************************************************/
27 #if defined (ACE_LACKS_COND_T) && defined (ACE_HAS_THREADS)
28 ACE_INLINE long
29 ACE_cond_t::waiters () const
31   return this->waiters_;
33 #endif /* ACE_LACKS_COND_T && ACE_HAS_THREADS */
35 /*****************************************************************************/
37 #if defined (ACE_HAS_TSS_EMULATION)
39 #  if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
40 ACE_INLINE
41 void **&
42 ACE_TSS_Emulation::tss_base ()
44 #    if defined (ACE_HAS_VXTHREADS)
45 #      if (!defined (_WRS_CONFIG_SMP) && !defined (INCLUDE_AMP_CPU))
46   if (taskVarGet(0, reinterpret_cast<int*>(&ace_tss_keys)) == ERROR)
47     taskVarAdd(0, reinterpret_cast<int*>(&ace_tss_keys));
48 #      endif
49   return reinterpret_cast <void **&> (ace_tss_keys);
50 #    else
51   // Uh oh.
52   ACE_NOTSUP_RETURN (0);
53 #    endif /* ACE_HAS_VXTHREADS */
55 #  endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
57 ACE_INLINE
58 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
59 ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key)
61   return tss_destructor_ [key];
64 ACE_INLINE
65 void
66 ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key,
67                                    ACE_TSS_DESTRUCTOR destructor)
69   tss_destructor_ [key] = destructor;
72 ACE_INLINE
73 void *&
74 ACE_TSS_Emulation::ts_object (const ACE_thread_key_t key)
76 #    if defined (ACE_HAS_VXTHREADS)
77     /* If someone wants tss_base make sure they get one.  This
78        gets used if someone spawns a VxWorks task directly, not
79        through ACE.  The allocated array will never be deleted! */
80     if (ace_tss_keys == 0)
81       {
82         ace_tss_keys = new void *[ACE_TSS_THREAD_KEYS_MAX];
84         // Zero the entire TSS array.  Do it manually instead of using
85         // memset, for optimum speed.  Though, memset may be faster :-)
86         void **tss_base_p = reinterpret_cast<void **> (ace_tss_keys);
87         for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
88           {
89             *tss_base_p = 0;
90           }
91       }
92 #    endif /* ACE_HAS_VXTHREADS */
94   return tss_base ()[key];
97 #endif /* ACE_HAS_TSS_EMULATION */
99 /*****************************************************************************/
101 ACE_INLINE int
102 ACE_OS::thr_equal (ACE_thread_t t1, ACE_thread_t t2)
104 #if defined (ACE_HAS_PTHREADS)
105 # if defined (pthread_equal)
106   // If it's a macro we can't say "pthread_equal"...
107   return pthread_equal (t1, t2);
108 # else
109   return pthread_equal (t1, t2);
110 # endif /* pthread_equal */
111 #else /* For both STHREADS and WTHREADS... */
112   // Hum, Do we need to treat WTHREAD differently?
113   // levine 13 oct 98 % I don't think so, ACE_thread_t is a DWORD.
114   return t1 == t2;
115 #endif /* ACE_HAS_PTHREADS */
118 ACE_INLINE int
119 ACE_OS::condattr_destroy (ACE_condattr_t &attributes)
121 #if defined (ACE_HAS_THREADS) && !defined (ACE_LACKS_CONDATTR)
122 #   if defined (ACE_HAS_PTHREADS)
123   pthread_condattr_destroy (&attributes);
124 #   else
125   attributes.type = 0;
126 #   endif /* ACE_HAS_PTHREADS */
127   return 0;
128 # else
129   ACE_UNUSED_ARG (attributes);
130   return 0;
131 # endif /* ACE_HAS_THREADS  */
134 ACE_INLINE int
135 ACE_OS::condattr_init (ACE_condattr_t &attributes, int type)
137   ACE_UNUSED_ARG (type);
138 # if defined (ACE_HAS_THREADS)
139 #   if defined (ACE_HAS_PTHREADS)
140   int result = -1;
142 #     if !defined (ACE_LACKS_CONDATTR)
143 #       if defined (ACE_PTHREAD_CONDATTR_T_INITIALIZE)
144   /* Tests show that VxWorks 6.x pthread lib does not only
145     * require zeroing of mutex/condition objects to function correctly
146     * but also of the attribute objects.
147     */
148   ACE_OS::memset (&attributes, 0, sizeof (attributes));
149 #       endif
150   if (
151       ACE_ADAPT_RETVAL (pthread_condattr_init (&attributes), result) == 0
152 #       if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)
153       && ACE_ADAPT_RETVAL (pthread_condattr_setpshared (&attributes, type),
154                            result) == 0
155 #       endif /* _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_CONDATTR_PSHARED */
156       )
157 #     else
158   if (type == USYNC_THREAD)
159 #     endif /* !ACE_LACKS_CONDATTR */
160      result = 0;
161   else
162     {
163       ACE_UNUSED_ARG (attributes);
164       result = -1;       // ACE_ADAPT_RETVAL used it for intermediate status
165     }
167   return result;
168 #   else
169   attributes.type = type;
170   return 0;
171 #   endif /* ACE_HAS_PTHREADS */
173 # else
174   ACE_UNUSED_ARG (attributes);
175   ACE_UNUSED_ARG (type);
176   ACE_NOTSUP_RETURN (-1);
177 # endif /* ACE_HAS_THREADS */
180 ACE_INLINE int
181 ACE_OS::condattr_synctype (ACE_condattr_t &attributes, int& type)
183 # if defined (ACE_HAS_THREADS)
184 #   if defined (ACE_HAS_PTHREADS)
185 #   if !defined (ACE_LACKS_CONDATTR) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)
186   int result = -1;
188   if (
189       ACE_ADAPT_RETVAL (pthread_condattr_getpshared (&attributes, &type),
190                            result) == 0
191      )
192     {
193       result = 0;
194     }
195 #   else
196   ACE_UNUSED_ARG (attributes);
197   int result = 0;
198   type = USYNC_THREAD;
199 #   endif /* !ACE_LACKS_CONDATTR && _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_CONDATTR_PSHARED */
201   return result;
202 #   else
203   type = attributes.type;
204   return 0;
205 #   endif /* ACE_HAS_PTHREADS */
207 # else
208   ACE_UNUSED_ARG (attributes);
209   ACE_UNUSED_ARG (type);
210   ACE_NOTSUP_RETURN (-1);
211 # endif /* ACE_HAS_THREADS */
214 ACE_INLINE int
215 ACE_OS::condattr_setclock (ACE_condattr_t &attributes, clockid_t clock_id)
217 #if defined (ACE_HAS_CONDATTR_SETCLOCK) && !defined (ACE_LACKS_CONDATTR_SETCLOCK)
218   int result = -1;
219   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_condattr_setclock (&attributes, clock_id),
220                                        result),
221                      int);
222   return result;
223 #else
224   ACE_UNUSED_ARG (clock_id);
225   ACE_UNUSED_ARG (attributes);
226   ACE_NOTSUP_RETURN (-1);
227 #endif
230 #if !defined (ACE_LACKS_COND_T)
231 // NOTE: The ACE_OS::cond_* functions for Unix platforms are defined
232 // here because the ACE_OS::sema_* functions below need them.
233 // However, ACE_WIN32 and VXWORKS define the ACE_OS::cond_* functions
234 // using the ACE_OS::sema_* functions.  So, they are defined in OS_NS_Tread.cpp.
236 ACE_INLINE int
237 ACE_OS::cond_broadcast (ACE_cond_t *cv)
239   ACE_OS_TRACE ("ACE_OS::cond_broadcast");
240 # if defined (ACE_HAS_THREADS)
241 #   if defined (ACE_HAS_PTHREADS)
242   int result;
243   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_broadcast (cv),
244                                        result),
245                      int);
246 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
247   ::WakeAllConditionVariable  (cv);
248   return 0;
249 #   endif /* ACE_HAS_PTHREADS */
250 # else
251   ACE_UNUSED_ARG (cv);
252   ACE_NOTSUP_RETURN (-1);
253 # endif /* ACE_HAS_THREADS */
256 ACE_INLINE int
257 ACE_OS::cond_destroy (ACE_cond_t *cv)
259   ACE_OS_TRACE ("ACE_OS::cond_destroy");
260 # if defined (ACE_HAS_THREADS)
261 #   if defined (ACE_HAS_PTHREADS)
262   int result;
263   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_destroy (cv), result), int);
264 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
265   // Windows doesn't have a destroy
266   return 0;
267 #   endif /* ACE_HAS_PTHREADS */
268 # else
269   ACE_UNUSED_ARG (cv);
270   ACE_NOTSUP_RETURN (-1);
271 # endif /* ACE_HAS_THREADS */
274 ACE_INLINE int
275 ACE_OS::cond_init (ACE_cond_t *cv,
276                    ACE_condattr_t &attributes,
277                    const char *name,
278                    void *arg)
280   // ACE_OS_TRACE ("ACE_OS::cond_init");
281   ACE_UNUSED_ARG (name);
282   ACE_UNUSED_ARG (arg);
283 # if defined (ACE_HAS_THREADS)
284 #   if defined (ACE_HAS_PTHREADS)
285   int result = -1;
287 #     if defined (ACE_PTHREAD_COND_T_INITIALIZE)
288   /* VxWorks 6.x API reference states:
289    *   If the memory for the condition variable object has been allocated
290    *   dynamically, it is a good policy to always zero out the
291    *   block of memory so as to avoid spurious EBUSY return code
292    *   when calling this routine.
293    */
294   ACE_OS::memset (cv, 0, sizeof (*cv));
295 #     endif
297   if (ACE_ADAPT_RETVAL (pthread_cond_init (cv, &attributes), result) == 0)
298      result = 0;
299   else
300      result = -1;       // ACE_ADAPT_RETVAL used it for intermediate status
302   return result;
303 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
304     ::InitializeConditionVariable (cv);
305     return 0;
306 #   endif /* ACE_HAS_PTHREADS */
307 # else
308   ACE_UNUSED_ARG (cv);
309   ACE_UNUSED_ARG (attributes);
310   ACE_UNUSED_ARG (name);
311   ACE_UNUSED_ARG (arg);
312   ACE_NOTSUP_RETURN (-1);
313 # endif /* ACE_HAS_THREADS */
316 #if defined (ACE_HAS_WCHAR)
317 ACE_INLINE int
318 ACE_OS::cond_init (ACE_cond_t *cv,
319                    ACE_condattr_t &attributes,
320                    const wchar_t *name,
321                    void *arg)
323   return ACE_OS::cond_init (cv, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg);
325 #endif /* ACE_HAS_WCHAR */
327 #if defined (ACE_HAS_WCHAR)
328 ACE_INLINE int
329 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
331   return ACE_OS::cond_init (cv, type, ACE_Wide_To_Ascii (name).char_rep (), arg);
333 #endif /* ACE_HAS_WCHAR */
335 ACE_INLINE int
336 ACE_OS::cond_signal (ACE_cond_t *cv)
338   ACE_OS_TRACE ("ACE_OS::cond_signal");
339 # if defined (ACE_HAS_THREADS)
340 #   if defined (ACE_HAS_PTHREADS)
341   int result;
342   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_signal (cv), result),
343                      int);
344 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
345   ::WakeConditionVariable (cv);
346   return 0;
347 #   endif /* ACE_HAS_PTHREADS */
348 # else
349   ACE_UNUSED_ARG (cv);
350   ACE_NOTSUP_RETURN (-1);
351 # endif /* ACE_HAS_THREADS */
354 ACE_INLINE int
355 ACE_OS::cond_wait (ACE_cond_t *cv,
356                    ACE_mutex_t *external_mutex)
358   ACE_OS_TRACE ("ACE_OS::cond_wait");
359 # if defined (ACE_HAS_THREADS)
360 #   if defined (ACE_HAS_PTHREADS)
361   int result;
362   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_wait (cv, external_mutex), result),
363                      int);
364 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
365   int result;
366   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, &external_mutex->thr_mutex_, INFINITE), result),
367                      int);
368 #   endif /* ACE_HAS_PTHREADS */
369 # else
370   ACE_UNUSED_ARG (cv);
371   ACE_UNUSED_ARG (external_mutex);
372   ACE_NOTSUP_RETURN (-1);
373 # endif /* ACE_HAS_THREADS */
376 ACE_INLINE int
377 ACE_OS::cond_timedwait (ACE_cond_t *cv,
378                         ACE_mutex_t *external_mutex,
379                         ACE_Time_Value *timeout)
381   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
382 # if defined (ACE_HAS_THREADS)
383   int result = 0;
384   timespec_t ts;
386   if (timeout != 0)
387     ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
389 #   if defined (ACE_HAS_PTHREADS)
391   ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
392                                 ? pthread_cond_wait (cv, external_mutex)
393                                 : pthread_cond_timedwait (cv, external_mutex,
394                                                             (ACE_TIMESPEC_PTR) &ts),
395                                 result),
396               int, result);
397   // We need to adjust this to make the POSIX return
398   // values consistent.  EAGAIN is from Pthreads DRAFT4
399   if (result == -1 &&
400       (errno == ETIMEDOUT || errno == EAGAIN))
401     errno = ETIME;
403 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
404   int msec_timeout = 0;
405   if (timeout != 0)
406     {
407       ACE_Time_Value relative_time = timeout->to_relative_time ();
408       // Watchout for situations where a context switch has caused the
409       // current time to be > the timeout.
410       if (relative_time > ACE_Time_Value::zero)
411         msec_timeout = relative_time.msec ();
412     }
414   ACE_OSCALL (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, &external_mutex->thr_mutex_, msec_timeout),
415                                 result),
416               int, result);
418   return result;
419 #   endif /* ACE_HAS_PTHREADS */
420   if (timeout != 0)
421     timeout->set (ts); // Update the time value before returning.
423   return result;
424 # else
425   ACE_UNUSED_ARG (cv);
426   ACE_UNUSED_ARG (external_mutex);
427   ACE_UNUSED_ARG (timeout);
428   ACE_NOTSUP_RETURN (-1);
429 # endif /* ACE_HAS_THREADS */
431 #endif /* !ACE_LACKS_COND_T */
433 ACE_INLINE int
434 ACE_OS::mutex_lock (ACE_mutex_t *m,
435                     const ACE_Time_Value *timeout)
437   return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout);
440 ACE_INLINE int
441 ACE_OS::event_wait (ACE_event_t *event)
443   return ACE_OS::event_timedwait (event, 0);
446 ACE_INLINE int
447 ACE_OS::event_init (ACE_event_t *event,
448                     int manual_reset,
449                     int initial_state,
450                     int type,
451                     const char *name,
452                     void *arg,
453                     LPSECURITY_ATTRIBUTES sa)
455   ACE_condattr_t *pattr = 0;
456   return ACE_OS::event_init (event, type, pattr, manual_reset, initial_state, name, arg, sa);
459 #if defined (ACE_HAS_WCHAR)
460 ACE_INLINE int
461 ACE_OS::event_init (ACE_event_t *event,
462                     int manual_reset,
463                     int initial_state,
464                     int type,
465                     const wchar_t *name,
466                     void *arg,
467                     LPSECURITY_ATTRIBUTES sa)
469 #if defined (ACE_WIN32)
470   ACE_UNUSED_ARG (type);
471   ACE_UNUSED_ARG (arg);
472   SECURITY_ATTRIBUTES sa_buffer;
473   SECURITY_DESCRIPTOR sd_buffer;
474   *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
475       (sa, &sa_buffer, &sd_buffer),
476   manual_reset,
477   initial_state,
478   name);
479   if (*event == 0)
480     ACE_FAIL_RETURN (-1);
482   // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
483   ACE_OS::set_errno_to_last_error ();
484   return 0;
485 #else  /* ACE_WIN32 */
486   return ACE_OS::event_init (event,
487                              manual_reset,
488                              initial_state,
489                              type,
490                              ACE_Wide_To_Ascii (name).char_rep (),
491                              arg,
492                              sa);
493 #endif /* ACE_WIN32 */
496 ACE_INLINE int
497 ACE_OS::event_init (ACE_event_t *event,
498                     int type,
499                     ACE_condattr_t *attributes,
500                     int manual_reset,
501                     int initial_state,
502                     const wchar_t *name,
503                     void *arg,
504                     LPSECURITY_ATTRIBUTES sa)
506 #if defined (ACE_WIN32)
507   ACE_UNUSED_ARG (type);
508   ACE_UNUSED_ARG (attributes);
509   ACE_UNUSED_ARG (arg);
510   SECURITY_ATTRIBUTES sa_buffer;
511   SECURITY_DESCRIPTOR sd_buffer;
512   *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
513       (sa, &sa_buffer, &sd_buffer),
514   manual_reset,
515   initial_state,
516   name);
517   if (*event == 0)
518     ACE_FAIL_RETURN (-1);
520   // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
521   ACE_OS::set_errno_to_last_error ();
522   return 0;
523 #else  /* ACE_WIN32 */
524   return ACE_OS::event_init (event,
525                              type,
526                              attributes,
527                              manual_reset,
528                              initial_state,
529                              ACE_Wide_To_Ascii (name).char_rep (),
530                              arg,
531                              sa);
532 #endif /* ACE_WIN32 */
534 #endif /* ACE_HAS_WCHAR */
536 ACE_INLINE long
537 ACE_OS::priority_control (ACE_idtype_t /*idtype*/, ACE_id_t /*identifier*/, int /*cmd*/, void * /*arg*/)
539   ACE_OS_TRACE ("ACE_OS::priority_control");
540   ACE_NOTSUP_RETURN (-1);
543 // This method is used to prepare the recursive mutex for releasing
544 // when waiting on a condition variable. If the platform doesn't have
545 // native recursive mutex and condition variable support, then ACE needs
546 // to save the recursion state around the wait and also ensure that the
547 // wait and lock release are atomic. recursive_mutex_cond_relock()
548 // is the inverse of this method.
549 ACE_INLINE int
550 ACE_OS::recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m,
551                                      ACE_recursive_mutex_state &state)
553 #if defined (ACE_HAS_THREADS)
554   ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_unlock");
555 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
556   // Windows need special handling since it has recursive mutexes, but
557   // does not integrate them into a condition variable.
558 #    if defined (ACE_WIN32)
559   // For Windows, the OS takes care of the mutex and its recursion. We just
560   // need to release the lock one fewer times than this thread has acquired
561   // it. Remember how many times, and reacquire it that many more times when
562   // the condition is signaled.
564   // We're using undocumented fields in the CRITICAL_SECTION structure
565   // and they've been known to change across Windows variants and versions./
566   // So be careful if you need to change these - there may be other
567   // Windows variants that depend on existing values and limits.
569   state.relock_count_ = 0;
570   while (m->LockCount > 0 && m->RecursionCount > 1)
571     {
572       // This may fail if the current thread doesn't own the mutex. If it
573       // does fail, it'll be on the first try, so don't worry about resetting
574       // the state.
575       if (ACE_OS::recursive_mutex_unlock (m) == -1)
576         return -1;
577       ++state.relock_count_;
578     }
579 #    else /* not ACE_WIN32 */
580     // prevent warnings for unused variables
581     ACE_UNUSED_ARG (state);
582     ACE_UNUSED_ARG (m);
583 #    endif /* ACE_WIN32 */
584   return 0;
585 #  else /* ACE_HAS_RECURSIVE_MUTEXES */
586   // For platforms without recursive mutexes, we obtain the nesting mutex
587   // to gain control over the mutex internals. Then set the internals to say
588   // the mutex is available. If there are waiters, signal the condition
589   // to notify them (this is mostly like the recursive_mutex_unlock() method).
590   // Then, return with the nesting mutex still held. The condition wait
591   // will release it atomically, allowing mutex waiters to continue.
592   // Note that this arrangement relies on the fact that on return from
593   // the condition wait, this thread will again own the nesting mutex
594   // and can either set the mutex internals directly or get in line for
595   // the mutex... this part is handled in recursive_mutex_cond_relock().
596   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
597     return -1;
599 #    if !defined (ACE_NDEBUG)
600   if (m->nesting_level_ == 0
601       || ACE_OS::thr_equal (ACE_OS::thr_self (), m->owner_id_) == 0)
602     {
603       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
604       errno = EINVAL;
605       return -1;
606     }
607 #    endif /* ACE_NDEBUG */
609   // To make error recovery a bit easier, signal the condition now. Any
610   // waiter won't regain control until the mutex is released, which won't
611   // be until the caller returns and does the wait on the condition.
612   if (ACE_OS::cond_signal (&m->lock_available_) == -1)
613     {
614       // Save/restore errno.
615       ACE_Errno_Guard error (errno);
616       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
617       return -1;
618     }
620   // Ok, the nesting_mutex_ lock is still held, the condition has been
621   // signaled... reset the nesting info and return _WITH_ the lock
622   // held. The lock will be released when the condition waits, in the
623   // caller.
624   state.nesting_level_ = m->nesting_level_;
625   state.owner_id_ = m->owner_id_;
626   m->nesting_level_ = 0;
627   m->owner_id_ = ACE_OS::NULL_thread;
628   return 0;
629 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
630 #else
631   ACE_UNUSED_ARG (m);
632   ACE_UNUSED_ARG (state);
633   ACE_NOTSUP_RETURN (-1);
634 #endif /* ACE_HAS_THREADS */
638 // This method is called after waiting on a condition variable when a
639 // recursive mutex must be reacquired. If the platform doesn't natively
640 // integrate recursive mutexes and condition variables, it's taken care
641 // of here (inverse of ACE_OS::recursive_mutex_cond_unlock).
642 ACE_INLINE void
643 ACE_OS::recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m,
644                                      ACE_recursive_mutex_state &state)
646 #if defined (ACE_HAS_THREADS)
647   ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_relock");
648 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
649   // Windows need special handling since it has recursive mutexes, but
650   // does not integrate them into a condition variable.
651   // On entry, the OS has already reacquired the lock for us. Just
652   // reacquire it the proper number of times so the recursion is the same as
653   // before waiting on the condition.
654 #    if defined (ACE_WIN32)
655   while (state.relock_count_ > 0)
656     {
657       ACE_OS::recursive_mutex_lock (m);
658       --state.relock_count_;
659     }
660   return;
661 #    else /* not ACE_WIN32 */
662     // prevent warnings for unused variables
663     ACE_UNUSED_ARG (state);
664     ACE_UNUSED_ARG (m);
666 #    endif /* ACE_WIN32 */
667 #  else
668   // Without recursive mutex support, it's somewhat trickier. On entry,
669   // the current thread holds the nesting_mutex_, but another thread may
670   // still be holding the ACE_recursive_mutex_t. If so, mimic the code
671   // in ACE_OS::recursive_mutex_lock that waits to acquire the mutex.
672   // After acquiring it, restore the nesting counts and release the
673   // nesting mutex. This will restore the conditions to what they were
674   // before calling ACE_OS::recursive_mutex_cond_unlock().
675   while (m->nesting_level_ > 0)
676     ACE_OS::cond_wait (&m->lock_available_, &m->nesting_mutex_);
678   // At this point, we still have nesting_mutex_ and the mutex is free.
679   m->nesting_level_ = state.nesting_level_;
680   m->owner_id_ = state.owner_id_;
681   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
682   return;
683 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
684 #else
685   ACE_UNUSED_ARG (m);
686   ACE_UNUSED_ARG (state);
687   return;
688 #endif /* ACE_HAS_THREADS */
691 ACE_INLINE int
692 ACE_OS::recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m)
694 #if defined (ACE_HAS_THREADS)
695 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
696   return ACE_OS::thread_mutex_destroy (m);
697 #else
698   if (ACE_OS::cond_destroy (&m->lock_available_) == -1
699       || ACE_OS::thread_mutex_destroy (&m->nesting_mutex_) == -1)
700     return -1;
701   return 0;
702 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
703 #else
704   ACE_UNUSED_ARG (m);
705   ACE_NOTSUP_RETURN (-1);
706 #endif /* ACE_HAS_THREADS */
709 ACE_INLINE int
710 ACE_OS::recursive_mutex_init (ACE_recursive_thread_mutex_t *m,
711                               const ACE_TCHAR *name,
712                               ACE_mutexattr_t *arg,
713                               LPSECURITY_ATTRIBUTES sa)
715   ACE_UNUSED_ARG (sa);
716 #if defined (ACE_HAS_THREADS)
717 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
718 #    if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
719   return ACE_OS::thread_mutex_init (m, PTHREAD_MUTEX_RECURSIVE, name, arg);
720 #    else
721   return ACE_OS::thread_mutex_init (m, 0, name, arg);
722 #    endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
723 #  else
724   if (ACE_OS::thread_mutex_init (&m->nesting_mutex_, 0, name, arg) == -1)
725     return -1;
726   else if (ACE_OS::cond_init (&m->lock_available_,
727                               (short) USYNC_THREAD,
728                               name,
729                               0) == -1)
730     return -1;
731   else
732     {
733       m->nesting_level_ = 0;
734       m->owner_id_ = ACE_OS::NULL_thread;
735       return 0;
736     }
737 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
738 #else
739   ACE_UNUSED_ARG (m);
740   ACE_UNUSED_ARG (name);
741   ACE_UNUSED_ARG (arg);
742   ACE_NOTSUP_RETURN (-1);
743 #endif /* ACE_HAS_THREADS */
746 ACE_INLINE int
747 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m)
749 #if defined (ACE_HAS_THREADS)
750 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
751   return ACE_OS::thread_mutex_lock (m);
752 #else
753   ACE_thread_t const t_id = ACE_OS::thr_self ();
754   int result = 0;
756   // Acquire the guard.
757   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
758     result = -1;
759   else
760   {
761     // If there's no contention, just grab the lock immediately
762     // (since this is the common case we'll optimize for it).
763     if (m->nesting_level_ == 0)
764       m->owner_id_ = t_id;
765       // If we already own the lock, then increment the nesting level
766       // and return.
767     else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
768     {
769           // Wait until the nesting level has dropped to zero, at
770           // which point we can acquire the lock.
771       while (m->nesting_level_ > 0)
772         ACE_OS::cond_wait (&m->lock_available_,
773                             &m->nesting_mutex_);
775           // At this point the nesting_mutex_ is held...
776       m->owner_id_ = t_id;
777     }
779     // At this point, we can safely increment the nesting_level_ no
780     // matter how we got here!
781     ++m->nesting_level_;
782   }
784   {
785     // Save/restore errno.
786     ACE_Errno_Guard error (errno);
787     ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
788   }
789   return result;
790 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
791 #else
792   ACE_UNUSED_ARG (m);
793   ACE_NOTSUP_RETURN (-1);
794 #endif /* ACE_HAS_THREADS */
797 ACE_INLINE int
798 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
799                               const ACE_Time_Value &timeout)
801 #if defined (ACE_HAS_THREADS)
802 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
803   return ACE_OS::thread_mutex_lock (m, timeout);
804 #else
805   ACE_thread_t t_id = ACE_OS::thr_self ();
806   int result = 0;
808   // Try to acquire the guard.
809   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_, timeout) == -1)
810     result = -1;
811   else
812     {
813       // If there's no contention, just grab the lock immediately
814       // (since this is the common case we'll optimize for it).
815       if (m->nesting_level_ == 0)
816         m->owner_id_ = t_id;
817       // If we already own the lock, then increment the nesting level
818       // and return.
819       else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
820         {
821           // Wait until the nesting level has dropped to zero, at
822           // which point we can acquire the lock.
823           while (m->nesting_level_ > 0)
824             {
825               result = ACE_OS::cond_timedwait (&m->lock_available_,
826                                                &m->nesting_mutex_,
827                                                const_cast <ACE_Time_Value *> (&timeout));
829               // The mutex is reacquired even in the case of a timeout
830               // release the mutex to prevent a deadlock
831               if (result == -1)
832                 {
833                   // Save/restore errno.
834                   ACE_Errno_Guard error (errno);
835                   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
837                   return result;
838                 }
839             }
841           // At this point the nesting_mutex_ is held...
842           m->owner_id_ = t_id;
843         }
845       // At this point, we can safely increment the nesting_level_ no
846       // matter how we got here!
847       m->nesting_level_++;
849       // Save/restore errno.
850       ACE_Errno_Guard error (errno);
851       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
852     }
853   return result;
854 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
855 #else
856   ACE_UNUSED_ARG (m);
857   ACE_UNUSED_ARG (timeout);
858   ACE_NOTSUP_RETURN (-1);
859 #endif /* ACE_HAS_THREADS */
862 ACE_INLINE int
863 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
864                               const ACE_Time_Value *timeout)
866   return timeout == 0
867     ? ACE_OS::recursive_mutex_lock (m)
868     : ACE_OS::recursive_mutex_lock (m, *timeout);
871 ACE_INLINE int
872 ACE_OS::recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m)
874 #if defined (ACE_HAS_THREADS)
875 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
876   return ACE_OS::thread_mutex_trylock (m);
877 #else
878   ACE_thread_t t_id = ACE_OS::thr_self ();
879   int result = 0;
881   // Acquire the guard.
882   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
883     result = -1;
884   else
885   {
886       // If there's no contention, just grab the lock immediately.
887     if (m->nesting_level_ == 0)
888     {
889       m->owner_id_ = t_id;
890       m->nesting_level_ = 1;
891     }
892       // If we already own the lock, then increment the nesting level
893       // and proceed.
894     else if (ACE_OS::thr_equal (t_id, m->owner_id_))
895       m->nesting_level_++;
896     else
897     {
898       errno = EBUSY;
899       result = -1;
900     }
901   }
903   {
904     // Save/restore errno.
905     ACE_Errno_Guard error (errno);
906     ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
907   }
908   return result;
909 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
910 #else
911   ACE_UNUSED_ARG (m);
912   ACE_NOTSUP_RETURN (-1);
913 #endif /* ACE_HAS_THREADS */
916 ACE_INLINE int
917 ACE_OS::recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m)
919 #if defined (ACE_HAS_THREADS)
920 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
921   return ACE_OS::thread_mutex_unlock (m);
922 #  else
923   ACE_OS_TRACE ("ACE_OS::recursive_mutex_unlock");
924 #    if !defined (ACE_NDEBUG)
925   ACE_thread_t t_id = ACE_OS::thr_self ();
926 #    endif /* ACE_NDEBUG */
927   int result = 0;
929   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
930     result = -1;
931   else
932   {
933 #    if !defined (ACE_NDEBUG)
934       if (m->nesting_level_ == 0
935           || ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
937   errno = EINVAL;
938   result = -1;
940       else
941 #    endif /* ACE_NDEBUG */
943   m->nesting_level_--;
944   if (m->nesting_level_ == 0)
945   {
946               // This may not be strictly necessary, but it does put
947               // the mutex into a known state...
948     m->owner_id_ = ACE_OS::NULL_thread;
950               // Inform a waiter that the lock is free.
951     if (ACE_OS::cond_signal (&m->lock_available_) == -1)
952       result = -1;
953   }
955   }
958     // Save/restore errno.
959   ACE_Errno_Guard error (errno);
960   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
962   return result;
963 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
964 #else
965   ACE_UNUSED_ARG (m);
966   ACE_NOTSUP_RETURN (-1);
967 #endif /* ACE_HAS_THREADS */
970 ACE_INLINE int
971 ACE_OS::rw_rdlock (ACE_rwlock_t *rw)
973   ACE_OS_TRACE ("ACE_OS::rw_rdlock");
974 #if defined (ACE_HAS_THREADS)
975 # if !defined (ACE_LACKS_RWLOCK_T)
976 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
977   int result;
978   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_rdlock (rw),
979                                        result),
980                      int);
981 #  else /* ACE_HAS_PTHREADS_UNIX98_EXT */
982   int result;
983   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_rdlock (rw), result), int);
984 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
985 # else /* NT, POSIX, and VxWorks don't support this natively. */
986 #   if defined (ACE_HAS_PTHREADS)
987   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
988 #   endif /* ACE_HAS_PTHREADS */
989   int result = 0;
990   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
991     result = -1; // -1 means didn't get the mutex.
992   else
993     {
994       // Give preference to writers who are waiting.
995       while (rw->ref_count_ < 0 || rw->num_waiting_writers_ > 0)
996         {
997           rw->num_waiting_readers_++;
998           if (ACE_OS::cond_wait (&rw->waiting_readers_, &rw->lock_) == -1)
999             {
1000               result = -2; // -2 means that we need to release the mutex.
1001               break;
1002             }
1003           rw->num_waiting_readers_--;
1004         }
1005     }
1006   if (result == 0)
1007     rw->ref_count_++;
1008   if (result != -1)
1009     ACE_OS::mutex_unlock (&rw->lock_);
1010 #   if defined (ACE_HAS_PTHREADS)
1011   ACE_PTHREAD_CLEANUP_POP (0);
1012 #   endif /* defined (ACE_HAS_PTHREADS) */
1013   return 0;
1014 # endif /* ! ACE_LACKS_RWLOCK_T */
1015 #else
1016   ACE_UNUSED_ARG (rw);
1017   ACE_NOTSUP_RETURN (-1);
1018 #endif /* ACE_HAS_THREADS */
1021 ACE_INLINE int
1022 ACE_OS::rw_tryrdlock (ACE_rwlock_t *rw)
1024   ACE_OS_TRACE ("ACE_OS::rw_tryrdlock");
1025 #if defined (ACE_HAS_THREADS)
1026 # if !defined (ACE_LACKS_RWLOCK_T)
1027 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1028   int result;
1029   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_tryrdlock (rw),
1030                                        result),
1031                      int);
1032 #  else /* ACE_HAS_PTHREADS_UNIX98_EXT */
1033   int result;
1034   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_tryrdlock (rw), result), int);
1035 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1036 # else /* NT, POSIX, and VxWorks don't support this natively. */
1037   int result = -1;
1039   if (ACE_OS::mutex_lock (&rw->lock_) != -1)
1040     {
1041       ACE_Errno_Guard error (errno);
1043       if (rw->ref_count_ == -1 || rw->num_waiting_writers_ > 0)
1044         {
1045           error = EBUSY;
1046           result = -1;
1047         }
1048       else
1049         {
1050           rw->ref_count_++;
1051           result = 0;
1052         }
1054       ACE_OS::mutex_unlock (&rw->lock_);
1055     }
1056   return result;
1057 # endif /* ! ACE_LACKS_RWLOCK_T */
1058 #else
1059   ACE_UNUSED_ARG (rw);
1060   ACE_NOTSUP_RETURN (-1);
1061 #endif /* ACE_HAS_THREADS */
1064 ACE_INLINE int
1065 ACE_OS::rw_trywrlock (ACE_rwlock_t *rw)
1067   ACE_OS_TRACE ("ACE_OS::rw_trywrlock");
1068 #if defined (ACE_HAS_THREADS)
1069 # if !defined (ACE_LACKS_RWLOCK_T)
1070 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1071   int result;
1072   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
1073                                        result),
1074                      int);
1075 #  else /* ACE_HAS_PTHREADS_UNIX98_EXT */
1076   int result;
1077   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_trywrlock (rw), result), int);
1078 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1079 # else /* NT, POSIX, and VxWorks don't support this natively. */
1080   int result = -1;
1082   if (ACE_OS::mutex_lock (&rw->lock_) != -1)
1083     {
1084       ACE_Errno_Guard error (errno);
1086       if (rw->ref_count_ != 0)
1087         {
1088           error = EBUSY;
1089           result = -1;
1090         }
1091       else
1092         {
1093           rw->ref_count_ = -1;
1094           result = 0;
1095         }
1097       ACE_OS::mutex_unlock (&rw->lock_);
1098     }
1099   return result;
1100 # endif /* ! ACE_LACKS_RWLOCK_T */
1101 #else
1102   ACE_UNUSED_ARG (rw);
1103   ACE_NOTSUP_RETURN (-1);
1104 #endif /* ACE_HAS_THREADS */
1107 // Note that the caller of this method *must* already possess this
1108 // lock as a read lock.
1109 // return {-1 and no errno set means: error,
1110 //         -1 and errno==EBUSY set means: could not upgrade,
1111 //         0 means: upgraded successfully}
1113 ACE_INLINE int
1114 ACE_OS::rw_trywrlock_upgrade (ACE_rwlock_t *rw)
1116   ACE_OS_TRACE ("ACE_OS::rw_trywrlock_upgrade");
1117 #if defined (ACE_HAS_THREADS)
1118 # if defined (ACE_HAS_PTHREADS_UNIX98_EXT) && !defined (ACE_LACKS_RWLOCK_T)
1119   int result;
1120   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
1121                                        result),
1122                      int);
1123 # elif !defined (ACE_LACKS_RWLOCK_T)
1124   // Some native rwlocks
1125   ACE_UNUSED_ARG (rw);
1126   ACE_NOTSUP_RETURN (-1);
1127 # else /* NT, POSIX, and VxWorks don't support this natively. */
1128   // The ACE rwlock emulation does support upgrade . . .
1129   int result = 0;
1131 #   if defined (ACE_HAS_PTHREADS)
1132   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
1133 #   endif /* defined (ACE_HAS_PTHREADS) */
1135   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1136     return -1;
1137     // -1 means didn't get the mutex, error
1138   else if (rw->important_writer_)
1139     // an other reader upgrades already
1140     {
1141       result = -1;
1142       errno = EBUSY;
1143     }
1144   else
1145     {
1146       while (rw->ref_count_ > 1) // wait until only I am left
1147         {
1148           rw->num_waiting_writers_++; // prohibit any more readers
1149           rw->important_writer_ = true;
1151           if (ACE_OS::cond_wait (&rw->waiting_important_writer_, &rw->lock_) == -1)
1152             {
1153               result = -1;
1154               // we know that we have the lock again, we have this guarantee,
1155               // but something went wrong
1156             }
1157           rw->important_writer_ = false;
1158           rw->num_waiting_writers_--;
1159         }
1160       if (result == 0)
1161         {
1162           // nothing bad happend
1163           rw->ref_count_ = -1;
1164           // now I am a writer
1165           // everything is O.K.
1166         }
1167     }
1169   ACE_OS::mutex_unlock (&rw->lock_);
1171 #   if defined (ACE_HAS_PTHREADS)
1172   ACE_PTHREAD_CLEANUP_POP (0);
1173 #   endif /* defined (ACE_HAS_PTHREADS) */
1175   return result;
1177 # endif /* ! ACE_LACKS_RWLOCK_T */
1178 #else
1179   ACE_UNUSED_ARG (rw);
1180   ACE_NOTSUP_RETURN (-1);
1181 #endif /* ACE_HAS_THREADS */
1184 ACE_INLINE int
1185 ACE_OS::rw_unlock (ACE_rwlock_t *rw)
1187   ACE_OS_TRACE ("ACE_OS::rw_unlock");
1188 #if defined (ACE_HAS_THREADS)
1189 # if !defined (ACE_LACKS_RWLOCK_T)
1190 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1191   int result;
1192   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_unlock (rw),
1193                                        result),
1194                      int);
1195 #  else /* ACE_HAS_PTHREADS_UNIX98_EXT */
1196   int result;
1197   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_unlock (rw), result), int);
1198 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1199 # else /* NT, POSIX, and VxWorks don't support this natively. */
1200   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1201     return -1;
1203   if (rw->ref_count_ > 0) // Releasing a reader.
1204     rw->ref_count_--;
1205   else if (rw->ref_count_ == -1) // Releasing a writer.
1206     rw->ref_count_ = 0;
1207   else
1208     {
1209       (void) ACE_OS::mutex_unlock (&rw->lock_);
1210       return -1; // @@ ACE_ASSERT (!"count should not be 0!\n");
1211     }
1213   int result = 0;
1214   ACE_Errno_Guard error (errno);
1216   if (rw->important_writer_ && rw->ref_count_ == 1)
1217     // only the reader requesting to upgrade its lock is left over.
1218     {
1219       result = ACE_OS::cond_signal (&rw->waiting_important_writer_);
1220       error = errno;
1221     }
1222   else if (rw->num_waiting_writers_ > 0 && rw->ref_count_ == 0)
1223     // give preference to writers over readers...
1224     {
1225       result = ACE_OS::cond_signal (&rw->waiting_writers_);
1226       error =  errno;
1227     }
1228   else if (rw->num_waiting_readers_ > 0 && rw->num_waiting_writers_ == 0)
1229     {
1230       result = ACE_OS::cond_broadcast (&rw->waiting_readers_);
1231       error = errno;
1232     }
1234   (void) ACE_OS::mutex_unlock (&rw->lock_);
1235   return result;
1236 # endif /* ! ace_lacks_rwlock_t */
1237 #else
1238   ACE_UNUSED_ARG (rw);
1239   ACE_NOTSUP_RETURN (-1);
1240 #endif /* ace_has_threads */
1243 ACE_INLINE int
1244 ACE_OS::rw_wrlock (ACE_rwlock_t *rw)
1246   ACE_OS_TRACE ("ACE_OS::rw_wrlock");
1247 #if defined (ACE_HAS_THREADS)
1248 # if !defined (ACE_LACKS_RWLOCK_T)
1249 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1250   int result;
1251   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_wrlock (rw),
1252                                        result),
1253                      int);
1254 #  else /* ACE_HAS_PTHREADS_UNIX98_EXT */
1255   int result;
1256   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_wrlock (rw), result), int);
1257 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1258 # else /* NT, POSIX, and VxWorks don't support this natively. */
1259 #   if defined (ACE_HAS_PTHREADS)
1260   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
1261 #   endif /* defined (ACE_HAS_PTHREADS) */
1262   int result = 0;
1264   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1265     result = -1; // -1 means didn't get the mutex.
1266   else
1267     {
1268       while (rw->ref_count_ != 0)
1269         {
1270           rw->num_waiting_writers_++;
1272           if (ACE_OS::cond_wait (&rw->waiting_writers_, &rw->lock_) == -1)
1273             {
1274               result = -2; // -2 means we need to release the mutex.
1275               break;
1276             }
1278           rw->num_waiting_writers_--;
1279         }
1280     }
1281   if (result == 0)
1282     rw->ref_count_ = -1;
1283   if (result != -1)
1284     ACE_OS::mutex_unlock (&rw->lock_);
1285 #   if defined (ACE_HAS_PTHREADS)
1286   ACE_PTHREAD_CLEANUP_POP (0);
1287 #   endif /* defined (ACE_HAS_PTHREADS) */
1288   return 0;
1289 # endif /* ! ACE_LACKS_RWLOCK_T */
1290 #else
1291   ACE_UNUSED_ARG (rw);
1292   ACE_NOTSUP_RETURN (-1);
1293 #endif /* ACE_HAS_THREADS */
1296 ACE_INLINE int
1297 ACE_OS::rwlock_destroy (ACE_rwlock_t *rw)
1299   ACE_OS_TRACE ("ACE_OS::rwlock_destroy");
1300 #if defined (ACE_HAS_THREADS)
1301 # if !defined (ACE_LACKS_RWLOCK_T)
1302 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1303   int result;
1304   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_destroy (rw),
1305                                        result),
1306                      int);
1307 #  else /* ACE_HAS_PTHREADS_UNIX98_EXT */
1308   int result;
1309   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_destroy (rw), result), int);
1310 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1311 # else /* NT, POSIX, and VxWorks don't support this natively. */
1312   ACE_OS::mutex_destroy (&rw->lock_);
1313   ACE_OS::cond_destroy (&rw->waiting_readers_);
1314   ACE_OS::cond_destroy (&rw->waiting_important_writer_);
1315   return ACE_OS::cond_destroy (&rw->waiting_writers_);
1316 # endif /* !defined (ACE_LACKS_RWLOCK_T) */
1317 #else
1318   ACE_UNUSED_ARG (rw);
1319   ACE_NOTSUP_RETURN (-1);
1320 #endif /* ACE_HAS_THREADS */
1323 #if defined (ACE_HAS_THREADS) && !defined (ACE_LACKS_RWLOCK_T)
1324 ACE_INLINE int
1325 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
1326                      int type,
1327                      const ACE_TCHAR *name,
1328                      void *arg)
1330   // ACE_OS_TRACE ("ACE_OS::rwlock_init");
1331 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1332   ACE_UNUSED_ARG (name);
1333   ACE_UNUSED_ARG (arg);
1335   int status;
1336   pthread_rwlockattr_t attr;
1337   pthread_rwlockattr_init (&attr);
1338 #    if !defined (ACE_LACKS_RWLOCKATTR_PSHARED)
1339   pthread_rwlockattr_setpshared (&attr, (type == USYNC_THREAD ?
1340                                          PTHREAD_PROCESS_PRIVATE :
1341                                          PTHREAD_PROCESS_SHARED));
1342 #    else
1343   ACE_UNUSED_ARG (type);
1344 #    endif /* !ACE_LACKS_RWLOCKATTR_PSHARED */
1345   status = ACE_ADAPT_RETVAL (pthread_rwlock_init (rw, &attr), status);
1346   pthread_rwlockattr_destroy (&attr);
1348   return status;
1350 #  else
1351   type = type;
1352   name = name;
1353   int result;
1354   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_init (rw, type, arg), result), int);
1355 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1357 #endif /* ACE_HAS_THREADS && !defined (ACE_LACKS_RWLOCK_T) */
1359 ACE_INLINE int
1360 ACE_OS::sema_destroy (ACE_sema_t *s)
1362   ACE_OS_TRACE ("ACE_OS::sema_destroy");
1363 #if defined (ACE_HAS_POSIX_SEM)
1364   int result = 0;
1365 # if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
1366   ACE_OS::mutex_destroy (&s->lock_);
1367   ACE_OS::cond_destroy (&s->count_nonzero_);
1368 # endif /* !ACE_HAS_POSIX_SEM_TIMEOUT && !ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
1369 # if defined (ACE_LACKS_NAMED_POSIX_SEM)
1370   if (s->name_)
1371     {
1372       // Only destroy the semaphore if we're the ones who
1373       // initialized it.
1374 #  if !defined (ACE_LACKS_SEM_DESTROY)
1375       ACE_OSCALL (::sem_destroy (s->sema_),int, result);
1376 #  endif /* ACE_LACKS_SEM_DESTROY */
1377       ACE_OS::shm_unlink (s->name_);
1378       delete s->name_;
1379       return result;
1380     }
1381 # else
1382   if (s->name_)
1383     {
1384       if (!s->avoid_unlink_)
1385         ACE_OS::sema_unlink (s->name_);
1386 #if defined (ACE_HAS_ALLOC_HOOKS)
1387       ACE_Allocator::instance()->free ((void *) s->name_);
1388 #else
1389       ACE_OS::free ((void *) s->name_);
1390 #endif /* ACE_HAS_ALLOC_HOOKS */
1391       return ::sem_close (s->sema_);
1392     }
1393 # endif /*  ACE_LACKS_NAMED_POSIX_SEM */
1394   else
1395     {
1396 # if !defined (ACE_LACKS_UNNAMED_SEMAPHORE) && !defined (ACE_LACKS_SEM_DESTROY)
1397       ACE_OSCALL (::sem_destroy (s->sema_), int, result);
1398 # endif /* !ACE_LACKS_UNNAMED_SEMAPHORE  && !ACE_LACKS_SEM_DESTROY */
1399 # if defined (ACE_LACKS_NAMED_POSIX_SEM)
1400       if (s->new_sema_)
1401 # endif /* ACE_LACKS_NAMED_POSIX_SEM */
1402 #if defined (ACE_HAS_ALLOC_HOOKS)
1403         ACE_Allocator::instance()->free(s->sema_);
1404 #else
1405         delete s->sema_;
1406 #endif /* ACE_HAS_ALLOC_HOOKS */
1407       s->sema_ = 0;
1408       return result;
1409     }
1410 #elif defined (ACE_USES_FIFO_SEM)
1411   int r0 = 0;
1412   if (s->name_)
1413     {
1414       r0 = ACE_OS::unlink (s->name_);
1415 #if defined (ACE_HAS_ALLOC_HOOKS)
1416       ACE_Allocator::instance()->free ((void *) s->name_);
1417 #else
1418       ACE_OS::free ((void *) s->name_);
1419 #endif /* ACE_HAS_ALLOC_HOOKS */
1420       s->name_ = 0;
1421     }
1422   int r1 = ACE_OS::close (s->fd_[0]);      /* ignore error */
1423   int r2 = ACE_OS::close (s->fd_[1]);      /* ignore error */
1424   return r0 != 0 || r1 != 0 || r2 != 0 ? -1 : 0;
1425 #elif defined (ACE_HAS_THREADS)
1426 # if defined (ACE_HAS_PTHREADS)
1427   int r1 = ACE_OS::mutex_destroy (&s->lock_);
1428   int r2 = ACE_OS::cond_destroy (&s->count_nonzero_);
1429   return r1 != 0 || r2 != 0 ? -1 : 0;
1430 # elif defined (ACE_HAS_WTHREADS)
1431   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*s), ace_result_), int, -1);
1432 # elif defined (ACE_VXWORKS)
1433   int result;
1434   ACE_OSCALL (::semDelete (s->sema_), int, result);
1435   s->sema_ = 0;
1436   return result;
1437 # endif /* ACE_HAS_PTHREADS */
1438 #else
1439   ACE_UNUSED_ARG (s);
1440   ACE_NOTSUP_RETURN (-1);
1441 #endif /* ACE_HAS_POSIX_SEM */
1444 // NOTE: The previous four function definitions must appear before
1445 // ACE_OS::sema_init ().
1446 ACE_INLINE int
1447 ACE_OS::sema_init (ACE_sema_t *s,
1448                    u_int count,
1449                    int type,
1450                    const char *name,
1451                    void *arg,
1452                    int max,
1453                    LPSECURITY_ATTRIBUTES sa)
1455   ACE_condattr_t *pattr = 0;
1456   return ACE_OS::sema_init (s, count, type, pattr, name, arg, max, sa);
1459 ACE_INLINE int
1460 ACE_OS::sema_init (ACE_sema_t *s,
1461                    u_int count,
1462                    int type,
1463                    ACE_condattr_t *attributes,
1464                    const char *name,
1465                    void *arg,
1466                    int max,
1467                    LPSECURITY_ATTRIBUTES sa)
1469   ACE_OS_TRACE ("ACE_OS::sema_init");
1470 #if defined (ACE_HAS_POSIX_SEM)
1471   ACE_UNUSED_ARG (max);
1472   ACE_UNUSED_ARG (sa);
1474   s->name_ = 0;
1475   s->avoid_unlink_ = false;
1476 #  if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
1477   ACE_UNUSED_ARG (arg);
1478   ACE_UNUSED_ARG (attributes);
1479 #  else
1480   int result = -1;
1482   if (ACE_OS::mutex_init (&s->lock_, type, name,
1483                           (ACE_mutexattr_t *) arg) == 0
1484       && (attributes == 0 ?
1485           ACE_OS::cond_init (&s->count_nonzero_, (short)type, name, arg) :
1486             ACE_OS::cond_init (&s->count_nonzero_, *attributes, name, arg)) == 0
1487       && ACE_OS::mutex_lock (&s->lock_) == 0)
1488     {
1489       if (ACE_OS::mutex_unlock (&s->lock_) == 0)
1490         result = 0;
1491     }
1493   if (result == -1)
1494     {
1495       ACE_OS::mutex_destroy (&s->lock_);
1496       ACE_OS::cond_destroy (&s->count_nonzero_);
1497       return result;
1498     }
1499 #  endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
1501 #  if defined (ACE_LACKS_NAMED_POSIX_SEM)
1502   s->new_sema_ = false;
1503   if (type == USYNC_PROCESS)
1504     {
1505       // Let's see if it already exists.
1506       ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
1507                                         O_RDWR | O_CREAT | O_EXCL,
1508                                         ACE_DEFAULT_FILE_PERMS);
1509       if (fd == ACE_INVALID_HANDLE)
1510         {
1511           if (errno == EEXIST)
1512             fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
1513                                    O_RDWR | O_CREAT,
1514                                    ACE_DEFAULT_FILE_PERMS);
1515           else
1516             return -1;
1517         }
1518       else
1519         {
1520           // We own this shared memory object!  Let's set its
1521           // size.
1522           if (ACE_OS::ftruncate (fd,
1523                                  sizeof (ACE_sema_t)) == -1)
1524             return -1;
1525           s->name_ = ACE_OS::strdup (name);
1526           if (s->name_ == 0)
1527             return -1;
1528         }
1529       if (fd == -1)
1530         return -1;
1532       s->sema_ = (sem_t *)
1533         ACE_OS::mmap (0,
1534                       sizeof (ACE_sema_t),
1535                       PROT_RDWR,
1536                       MAP_SHARED,
1537                       fd,
1538                       0);
1539       ACE_OS::close (fd);
1540       if (s->sema_ == (sem_t *) MAP_FAILED)
1541         return -1;
1542       if (s->name_
1543           // @@ According UNIX Network Programming V2 by Stevens,
1544           //    sem_init() is currently not required to return zero on
1545           //    success, but it *does* return -1 upon failure.  For
1546           //    this reason, check for failure by comparing to -1,
1547           //    instead of checking for success by comparing to zero.
1548           //        -Ossama
1549           // Only initialize it if we're the one who created it.
1550           && ::sem_init (s->sema_, type == USYNC_PROCESS, count) == -1)
1551         return -1;
1552       return 0;
1553     }
1554 #  else
1555   if (name)
1556     {
1557       ACE_ALLOCATOR_RETURN (s->name_,
1558                             ACE_OS::strdup (name),
1559                             -1);
1560       s->sema_ = ::sem_open (s->name_,
1561                              O_CREAT,
1562                              ACE_DEFAULT_FILE_PERMS,
1563                              count);
1564       if (s->sema_ == (sem_t *) SEM_FAILED)
1565         return -1;
1566       else
1567         return 0;
1568     }
1569 #  endif /* ACE_LACKS_NAMED_POSIX_SEM */
1570   else
1571     {
1572 #  if defined (ACE_LACKS_UNNAMED_SEMAPHORE)
1573       ACE_NOTSUP_RETURN (-1);
1574 #  else
1575 #if defined (ACE_HAS_ALLOC_HOOKS)
1576       ACE_ALLOCATOR_RETURN (s->sema_,
1577                             static_cast<sem_t*>(ACE_Allocator::instance()->malloc(sizeof(sem_t))),
1578                             -1);
1579 #else
1580       ACE_NEW_RETURN (s->sema_,
1581                       sem_t,
1582                       -1);
1583 #endif /* ACE_HAS_ALLOC_HOOKS */
1585 #   if defined (ACE_LACKS_NAMED_POSIX_SEM)
1586       s->new_sema_ = true;
1587 #   endif /* ACE_LACKS_NAMED_POSIX_SEM */
1588       ACE_OS::memset(s->sema_, 0, sizeof(*s->sema_));
1589       return ::sem_init (s->sema_, type != USYNC_THREAD, count);
1590 #  endif /* ACE_LACKS_UNNAMED_SEMAPHORE */
1591     }
1593 #elif defined (ACE_USES_FIFO_SEM)
1594   ACE_UNUSED_ARG (arg);
1595   ACE_UNUSED_ARG (max);
1596   ACE_UNUSED_ARG (sa);
1597   int             flags = 0;
1598   mode_t          mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
1600   if (type == USYNC_THREAD)
1601     {
1602       // Create systemwide unique name for semaphore
1603       char   uname[ACE_UNIQUE_NAME_LEN];
1604       ACE_OS::unique_name ((const void *) s,
1605                             uname,
1606                             ACE_UNIQUE_NAME_LEN);
1607       name = &uname[0];
1608     }
1610   s->name_ = 0;
1611   s->fd_[0] = s->fd_[1] = ACE_INVALID_HANDLE;
1612   bool creator = false;
1614   if (ACE_OS::mkfifo (ACE_TEXT_CHAR_TO_TCHAR (name), mode) < 0)
1615     {
1616       if (errno != EEXIST)    /* already exists OK else ERR */
1617         return -1;
1618       // check if this is a real FIFO, not just some other existing file
1619       ACE_stat fs;
1620       if (ACE_OS::stat (name, &fs))
1621         return -1;
1622       if (!S_ISFIFO (fs.st_mode))
1623         {
1624           // existing file is not a FIFO
1625           errno = EEXIST;
1626           return -1;
1627         }
1628     }
1629     else
1630       creator = true; // remember we created it for initialization at end
1632   // for processshared semaphores remember who we are to be able to remove
1633   // the FIFO when we're done with it
1634   if (type == USYNC_PROCESS)
1635     {
1636       s->name_ = ACE_OS::strdup (name);
1637       if (s->name_ == 0)
1638         {
1639           if (creator)
1640             ACE_OS::unlink (name);
1641           return -1;
1642         }
1643     }
1645   if ((s->fd_[0] = ACE_OS::open (name, O_RDONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE
1646       || (s->fd_[1] = ACE_OS::open (name, O_WRONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE)
1647     return -1;
1649   /* turn off nonblocking for fd_[0] */
1650   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
1651     return -1;
1653   flags &= ~O_NONBLOCK;
1654   if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
1655     return -1;
1657   //if (s->name_ && count)
1658   if (creator && count)
1659     {
1660       char    c = 1;
1661       for (u_int i=0; i<count ;++i)
1662         if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) != 1)
1663           return -1;
1664     }
1666   // In the case of process scope semaphores we can already unlink the FIFO now that
1667   // we completely set it up (the opened handles will keep it active until we close
1668   // thos down). This way we're protected against unexpected crashes as far as removal
1669   // is concerned.
1670   // Unfortunately this does not work for processshared FIFOs since as soon as we
1671   // have unlinked the semaphore no other process will be able to open it anymore.
1672   if (type == USYNC_THREAD)
1673     {
1674       ACE_OS::unlink (name);
1675     }
1677   return 0;
1678 #elif defined (ACE_HAS_THREADS)
1679 #  if defined (ACE_HAS_PTHREADS)
1680   ACE_UNUSED_ARG (max);
1681   ACE_UNUSED_ARG (sa);
1682   int result = -1;
1684   if (ACE_OS::mutex_init (&s->lock_, type, name,
1685                           (ACE_mutexattr_t *) arg) == 0
1686       && (attributes == 0 ?
1687           ACE_OS::cond_init (&s->count_nonzero_, (short)type, name, arg) :
1688             ACE_OS::cond_init (&s->count_nonzero_, *attributes, name, arg)) == 0
1689       && ACE_OS::mutex_lock (&s->lock_) == 0)
1690     {
1691       s->count_ = count;
1692       s->waiters_ = 0;
1694       if (ACE_OS::mutex_unlock (&s->lock_) == 0)
1695         result = 0;
1696     }
1698   if (result == -1)
1699     {
1700       ACE_OS::mutex_destroy (&s->lock_);
1701       ACE_OS::cond_destroy (&s->count_nonzero_);
1702     }
1703   return result;
1704 #  elif defined (ACE_HAS_WTHREADS)
1705   ACE_UNUSED_ARG (attributes);
1706   ACE_UNUSED_ARG (type);
1707   ACE_UNUSED_ARG (arg);
1708   // Create the semaphore with its value initialized to <count> and
1709   // its maximum value initialized to <max>.
1710   SECURITY_ATTRIBUTES sa_buffer;
1711   SECURITY_DESCRIPTOR sd_buffer;
1712   *s = ACE_TEXT_CreateSemaphore
1713     (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
1714      count,
1715      max,
1716      ACE_TEXT_CHAR_TO_TCHAR (name));
1718   if (*s == 0)
1719     ACE_FAIL_RETURN (-1);
1720   /* NOTREACHED */
1721   else
1722     {
1723       // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1724       ACE_OS::set_errno_to_last_error ();
1725       return 0;
1726     }
1727 #  elif defined (ACE_VXWORKS)
1728   ACE_UNUSED_ARG (attributes);
1729   ACE_UNUSED_ARG (name);
1730   ACE_UNUSED_ARG (arg);
1731   ACE_UNUSED_ARG (max);
1732   ACE_UNUSED_ARG (sa);
1733   s->name_ = 0;
1734   s->sema_ = ::semCCreate (type, count);
1735   return s->sema_ ? 0 : -1;
1736 #  endif /* ACE_HAS_PTHREADS */
1737 #else
1738   ACE_UNUSED_ARG (s);
1739   ACE_UNUSED_ARG (count);
1740   ACE_UNUSED_ARG (type);
1741   ACE_UNUSED_ARG (attributes);
1742   ACE_UNUSED_ARG (name);
1743   ACE_UNUSED_ARG (arg);
1744   ACE_UNUSED_ARG (max);
1745   ACE_UNUSED_ARG (sa);
1746   ACE_NOTSUP_RETURN (-1);
1747 #endif /* ACE_HAS_POSIX_SEM */
1750 #if defined (ACE_HAS_WCHAR)
1751 ACE_INLINE int
1752 ACE_OS::sema_init (ACE_sema_t *s,
1753                    u_int count,
1754                    int type,
1755                    const wchar_t *name,
1756                    void *arg,
1757                    int max,
1758                    LPSECURITY_ATTRIBUTES sa)
1760   ACE_condattr_t *pattr = 0;
1761   return ACE_OS::sema_init (s, count, type, pattr, name, arg, max, sa);
1764 ACE_INLINE int
1765 ACE_OS::sema_init (ACE_sema_t *s,
1766                    u_int count,
1767                    int type,
1768                    ACE_condattr_t *attributes,
1769                    const wchar_t *name,
1770                    void *arg,
1771                    int max,
1772                    LPSECURITY_ATTRIBUTES sa)
1774 # if defined (ACE_HAS_WTHREADS)
1775   ACE_UNUSED_ARG (attributes);
1776   ACE_UNUSED_ARG (type);
1777   ACE_UNUSED_ARG (arg);
1778   // Create the semaphore with its value initialized to <count> and
1779   // its maximum value initialized to <max>.
1780   SECURITY_ATTRIBUTES sa_buffer;
1781   SECURITY_DESCRIPTOR sd_buffer;
1782   *s = ::CreateSemaphoreW
1783     (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
1784      count,
1785      max,
1786      name);
1788   if (*s == 0)
1789     ACE_FAIL_RETURN (-1);
1790   /* NOTREACHED */
1791   else
1792     {
1793       // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1794       ACE_OS::set_errno_to_last_error ();
1795       return 0;
1796     }
1797 # else /* ACE_HAS_WTHREADS */
1798   // Just call the normal char version.
1799   return ACE_OS::sema_init (s, count, type, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg, max, sa);
1800 # endif /* ACE_HAS_WTHREADS */
1802 #endif /* ACE_HAS_WCHAR */
1804 ACE_INLINE void
1805 ACE_OS::sema_avoid_unlink (ACE_sema_t *s, bool avoid_unlink)
1807 #if defined (ACE_HAS_POSIX_SEM)
1808   s->avoid_unlink_ = avoid_unlink;
1809 #else
1810   ACE_UNUSED_ARG (s);
1811   ACE_UNUSED_ARG (avoid_unlink);
1812 #endif
1815 ACE_INLINE int
1816 ACE_OS::sema_unlink (const char *name)
1818 #if defined (ACE_HAS_POSIX_SEM) && !defined (ACE_LACKS_SEM_UNLINK)
1819   return ::sem_unlink (name);
1820 #else
1821   ACE_UNUSED_ARG (name);
1822   ACE_NOTSUP_RETURN (-1);
1823 #endif
1826 ACE_INLINE int
1827 ACE_OS::sema_post (ACE_sema_t *s)
1829   ACE_OS_TRACE ("ACE_OS::sema_post");
1830 # if defined (ACE_HAS_POSIX_SEM)
1831 #   if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
1832   return ::sem_post (s->sema_);
1833 #   else
1834   int result = -1;
1836   if (ACE_OS::mutex_lock (&s->lock_) == 0)
1837     {
1838       if (::sem_post (s->sema_) == 0)
1839         result = ACE_OS::cond_signal (&s->count_nonzero_);
1841       ACE_OS::mutex_unlock (&s->lock_);
1842     }
1843   return result;
1844 #   endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
1845 # elif defined (ACE_USES_FIFO_SEM)
1846   char    c = 1;
1847   if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) == sizeof (char))
1848     return 0;
1849   return -1;
1850 # elif defined (ACE_HAS_THREADS)
1851 #   if defined (ACE_HAS_PTHREADS)
1852   int result = -1;
1854   if (ACE_OS::mutex_lock (&s->lock_) == 0)
1855     {
1856       // Always allow a waiter to continue if there is one.
1857       if (s->waiters_ > 0)
1858         result = ACE_OS::cond_signal (&s->count_nonzero_);
1859       else
1860         result = 0;
1862       s->count_++;
1863       ACE_OS::mutex_unlock (&s->lock_);
1864     }
1865   return result;
1866 #   elif defined (ACE_HAS_WTHREADS)
1867   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, 1, 0),
1868                                           ace_result_),
1869                         int, -1);
1870 #   elif defined (ACE_VXWORKS)
1871   return ::semGive (s->sema_);
1872 #   endif /* ACE_HAS_PTHREADS */
1873 # else
1874   ACE_UNUSED_ARG (s);
1875   ACE_NOTSUP_RETURN (-1);
1876 # endif /* ACE_HAS_POSIX_SEM */
1879 ACE_INLINE int
1880 ACE_OS::sema_post (ACE_sema_t *s, u_int release_count)
1882 #if defined (ACE_WIN32)
1883   // Win32 supports this natively.
1884   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, release_count, 0),
1885                                           ace_result_), int, -1);
1886 #else
1887   // On POSIX platforms we need to emulate this ourselves.
1888   // @@ We can optimize on this implementation.  However,
1889   // the semaphore primitive on Win32 doesn't allow one
1890   // to increase a semaphore to more than the count it was
1891   // first initialized.  Posix doesn't seem to have
1892   // this restriction.  Should we impose the restriction in
1893   // our semaphore simulation?
1894   for (size_t i = 0; i < release_count; i++)
1895     if (ACE_OS::sema_post (s) == -1)
1896       return -1;
1898   return 0;
1899 #endif /* ACE_WIN32 */
1902 ACE_INLINE int
1903 ACE_OS::sema_trywait (ACE_sema_t *s)
1905   ACE_OS_TRACE ("ACE_OS::sema_trywait");
1906 # if defined (ACE_HAS_POSIX_SEM)
1907   // POSIX semaphores set errno to EAGAIN if trywait fails
1908   return ::sem_trywait (s->sema_);
1909 # elif defined (ACE_USES_FIFO_SEM)
1910   char  c;
1911   int     rc, flags;
1913   /* turn on nonblocking for s->fd_[0] */
1914   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
1915     return -1;
1916   flags |= O_NONBLOCK;
1917   if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
1918     return -1;
1920   // read sets errno to EAGAIN if no input
1921   rc = ACE_OS::read (s->fd_[0], &c, sizeof (char));
1923   /* turn off nonblocking for fd_[0] */
1924   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) >= 0)
1925   {
1926     flags &= ~O_NONBLOCK;
1927     ACE_OS::fcntl (s->fd_[0], F_SETFL, flags);
1928   }
1930   return rc == 1 ? 0 : (-1);
1931 # elif defined (ACE_HAS_THREADS)
1932 #   if defined (ACE_HAS_PTHREADS)
1933   int result = -1;
1935   if (ACE_OS::mutex_lock (&s->lock_) == 0)
1936     {
1937       if (s->count_ > 0)
1938         {
1939           --s->count_;
1940           result = 0;
1941         }
1942       else
1943         errno = EBUSY;
1945       ACE_OS::mutex_unlock (&s->lock_);
1946     }
1947   return result;
1948 #   elif defined (ACE_HAS_WTHREADS)
1949   DWORD result = ::WaitForSingleObject (*s, 0);
1951   if (result == WAIT_OBJECT_0)
1952     return 0;
1953   else
1954     {
1955       if (result == WAIT_TIMEOUT)
1956         errno = EBUSY;
1957       else
1958         ACE_OS::set_errno_to_last_error ();
1959       // This is a hack, we need to find an appropriate mapping...
1960       return -1;
1961     }
1962 #   elif defined (ACE_VXWORKS)
1963   if (::semTake (s->sema_, NO_WAIT) == ERROR)
1964     if (errno == S_objLib_OBJ_UNAVAILABLE)
1965       {
1966         // couldn't get the semaphore
1967         errno = EBUSY;
1968         return -1;
1969       }
1970     else
1971       // error
1972       return -1;
1973   else
1974     // got the semaphore
1975     return 0;
1976 #   endif /* ACE_HAS_PTHREADS */
1977 # else
1978   ACE_UNUSED_ARG (s);
1979   ACE_NOTSUP_RETURN (-1);
1980 # endif /* ACE_HAS_POSIX_SEM */
1983 ACE_INLINE int
1984 ACE_OS::sema_wait (ACE_sema_t *s)
1986   ACE_OS_TRACE ("ACE_OS::sema_wait");
1987 # if defined (ACE_HAS_POSIX_SEM)
1988   return ::sem_wait (s->sema_);
1989 # elif defined (ACE_USES_FIFO_SEM)
1990   char c;
1991   if (ACE_OS::read (s->fd_[0], &c, sizeof (char)) == 1)
1992     return 0;
1993   return -1;
1994 # elif defined (ACE_HAS_THREADS)
1995 #   if defined (ACE_HAS_PTHREADS)
1996   int result = 0;
1998   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
2000   if (ACE_OS::mutex_lock (&s->lock_) != 0)
2001     result = -1;
2002   else
2003     {
2004       // Keep track of the number of waiters so that we can signal
2005       // them properly in <ACE_OS::sema_post>.
2006       s->waiters_++;
2008       // Wait until the semaphore count is > 0.
2009       while (s->count_ == 0)
2010         if (ACE_OS::cond_wait (&s->count_nonzero_,
2011                                &s->lock_) == -1)
2012           {
2013             result = -2; // -2 means that we need to release the mutex.
2014             break;
2015           }
2017       --s->waiters_;
2018     }
2020   if (result == 0)
2021     --s->count_;
2023   if (result != -1)
2024     ACE_OS::mutex_unlock (&s->lock_);
2025   ACE_PTHREAD_CLEANUP_POP (0);
2026   return result < 0 ? -1 : result;
2028 #   elif defined (ACE_HAS_WTHREADS)
2029   switch (::WaitForSingleObject (*s, INFINITE))
2030     {
2031     case WAIT_OBJECT_0:
2032       return 0;
2033     default:
2034       // This is a hack, we need to find an appropriate mapping...
2035       ACE_OS::set_errno_to_last_error ();
2036       return -1;
2037     }
2038   /* NOTREACHED */
2039 #   elif defined (ACE_VXWORKS)
2040   return ::semTake (s->sema_, WAIT_FOREVER);
2041 #   endif /* ACE_HAS_PTHREADS */
2042 # else
2043   ACE_UNUSED_ARG (s);
2044   ACE_NOTSUP_RETURN (-1);
2045 # endif /* ACE_HAS_POSIX_SEM */
2048 ACE_INLINE int
2049 ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv)
2051   ACE_OS_TRACE ("ACE_OS::sema_wait");
2052 # if defined (ACE_HAS_POSIX_SEM)
2053 #   if defined (ACE_HAS_POSIX_SEM_TIMEOUT)
2054   int rc;
2055   timespec_t ts;
2056   ts = tv; // Calls ACE_Time_Value::operator timespec_t().
2057   ACE_OSCALL (::sem_timedwait (s->sema_, &ts), int, rc);
2058   if (rc == -1 && errno == ETIMEDOUT)
2059     errno = ETIME;  /* POSIX returns ETIMEDOUT but we need ETIME */
2060   return rc;
2061 #   elif !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
2062   int result = 0;
2063   bool expired = false;
2064   ACE_Errno_Guard error (errno);
2066   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
2068   if (ACE_OS::mutex_lock (&s->lock_) != 0)
2069     result = -2;
2070   else
2071     {
2072       bool finished = true;
2073       do
2074       {
2075         result = ACE_OS::sema_trywait (s);
2076         if (result == -1 && errno == EAGAIN)
2077           expired = (tv.to_relative_time () <= ACE_Time_Value::zero);
2078         else
2079           expired = false;
2081         finished = result != -1 || expired ||
2082                    (result == -1 && errno != EAGAIN);
2083         if (!finished)
2084           {
2085             if (ACE_OS::cond_timedwait (&s->count_nonzero_,
2086                                         &s->lock_,
2087                                         &tv) == -1)
2088               {
2089                 error = errno;
2090                 result = -1;
2091                 break;
2092               }
2093           }
2094       } while (!finished);
2096       if (expired)
2097         error = ETIME;
2098     }
2100   if (result != -2)
2101     ACE_OS::mutex_unlock (&s->lock_);
2102   ACE_PTHREAD_CLEANUP_POP (0);
2103   return result < 0 ? -1 : result;
2104 #   else /* No native sem_timedwait(), and emulation disabled */
2105   ACE_UNUSED_ARG (s);
2106   ACE_UNUSED_ARG (tv);
2107   ACE_NOTSUP_RETURN (-1);
2108 #   endif /* ACE_HAS_POSIX_SEM_TIMEOUT */
2109 # elif defined (ACE_USES_FIFO_SEM)
2110   int rc;
2111   ACE_Time_Value timeout = tv.to_relative_time ();
2113   while (timeout > ACE_Time_Value::zero)
2114     {
2115       ACE_Handle_Set  fds_;
2117       fds_.set_bit (s->fd_[0]);
2118       if ((rc = ACE_OS::select (ACE_Handle_Set::MAXSIZE, fds_, 0, 0, timeout)) != 1)
2119         {
2120           if (rc == 0 || errno != EAGAIN)
2121           {
2122             if (rc == 0)
2123               errno = ETIME;
2124             return -1;
2125           }
2126         }
2128       // try to read the signal *but* do *not* block
2129       if (rc == 1 && ACE_OS::sema_trywait (s) == 0)
2130         return 0;
2132       // we were woken for input but someone beat us to it
2133       // so we wait again if there is still time
2134       timeout = tv.to_relative_time ();
2135     }
2137   // make sure errno is set right
2138   errno = ETIME;
2140   return -1;
2141 # elif defined (ACE_HAS_THREADS)
2142 #   if defined (ACE_HAS_PTHREADS)
2143   int result = 0;
2144   ACE_Errno_Guard error (errno);
2146   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
2148   if (ACE_OS::mutex_lock (&s->lock_) != 0)
2149     result = -1;
2150   else
2151     {
2152       // Keep track of the number of waiters so that we can signal
2153       // them properly in <ACE_OS::sema_post>.
2154       s->waiters_++;
2156       // Wait until the semaphore count is > 0 or until we time out.
2157       while (s->count_ == 0)
2158         if (ACE_OS::cond_timedwait (&s->count_nonzero_,
2159                                     &s->lock_,
2160                                     &tv) == -1)
2161           {
2162             error = errno;
2163             result = -2; // -2 means that we need to release the mutex.
2164             break;
2165           }
2167       --s->waiters_;
2168     }
2170   if (result == 0)
2171     {
2172       --s->count_;
2173     }
2175   if (result != -1)
2176     ACE_OS::mutex_unlock (&s->lock_);
2177   ACE_PTHREAD_CLEANUP_POP (0);
2178   return result < 0 ? -1 : result;
2179 #   elif defined (ACE_HAS_WTHREADS)
2180   int msec_timeout;
2182   if (tv == ACE_Time_Value::zero)
2183     msec_timeout = 0; // Do a "poll."
2184   else
2185     {
2186       // Note that we must convert between absolute time (which is
2187       // passed as a parameter) and relative time (which is what
2188       // <WaitForSingleObjects> expects).
2189       ACE_Time_Value relative_time = tv.to_relative_time ();
2191       // Watchout for situations where a context switch has caused the
2192       // current time to be > the timeout.
2193       if (relative_time < ACE_Time_Value::zero)
2194         msec_timeout = 0;
2195       else
2196         msec_timeout = relative_time.msec ();
2197     }
2199   switch (::WaitForSingleObject (*s, msec_timeout))
2200     {
2201     case WAIT_OBJECT_0:
2202       tv = tv.now ();     // Update time to when acquired
2203       return 0;
2204     case WAIT_TIMEOUT:
2205       errno = ETIME;
2206       return -1;
2207     default:
2208       // This is a hack, we need to find an appropriate mapping...
2209       ACE_OS::set_errno_to_last_error ();
2210       return -1;
2211     }
2212   /* NOTREACHED */
2213 #   elif defined (ACE_VXWORKS)
2214   // Note that we must convert between absolute time (which is
2215   // passed as a parameter) and relative time (which is what
2216   // the system call expects).
2217   ACE_Time_Value relative_time = tv.to_relative_time ();
2219   _Vx_freq_t const ticks_per_sec = ::sysClkRateGet ();
2221   int ticks = relative_time.sec () * ticks_per_sec +
2222               relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
2223   if (::semTake (s->sema_, ticks) == ERROR)
2224     {
2225       if (errno == S_objLib_OBJ_TIMEOUT)
2226         // Convert the VxWorks errno to one that's common for to ACE
2227         // platforms.
2228         errno = ETIME;
2229       else if (errno == S_objLib_OBJ_UNAVAILABLE)
2230         errno = EBUSY;
2231       return -1;
2232     }
2233   else
2234     {
2235       tv = tv.now ();  // Update to time acquired
2236       return 0;
2237     }
2238 #   endif /* ACE_HAS_PTHREADS */
2239 # else
2240   ACE_UNUSED_ARG (s);
2241   ACE_UNUSED_ARG (tv);
2242   ACE_NOTSUP_RETURN (-1);
2243 # endif /* ACE_HAS_POSIX_SEM */
2246 ACE_INLINE int
2247 ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value *tv)
2249   return tv == 0 ? ACE_OS::sema_wait (s) : ACE_OS::sema_wait (s, *tv);
2252 ACE_INLINE int
2253 ACE_OS::semctl (int int_id, int semnum, int cmd, semun value)
2255   ACE_OS_TRACE ("ACE_OS::semctl");
2256 #if defined (ACE_HAS_SYSV_IPC)
2257   return ::semctl (int_id, semnum, cmd, value);
2258 #else
2259   ACE_UNUSED_ARG (int_id);
2260   ACE_UNUSED_ARG (semnum);
2261   ACE_UNUSED_ARG (cmd);
2262   ACE_UNUSED_ARG (value);
2264   ACE_NOTSUP_RETURN (-1);
2265 #endif /* ACE_HAS_SYSV_IPC */
2268 ACE_INLINE int
2269 ACE_OS::semget (key_t key, int nsems, int flags)
2271   ACE_OS_TRACE ("ACE_OS::semget");
2272 #if defined (ACE_HAS_SYSV_IPC)
2273   return ::semget (key, nsems, flags);
2274 #else
2275   ACE_UNUSED_ARG (key);
2276   ACE_UNUSED_ARG (nsems);
2277   ACE_UNUSED_ARG (flags);
2279   ACE_NOTSUP_RETURN (-1);
2280 #endif /* ACE_HAS_SYSV_IPC */
2283 ACE_INLINE int
2284 ACE_OS::semop (int int_id, struct sembuf *sops, size_t nsops)
2286   ACE_OS_TRACE ("ACE_OS::semop");
2287 #if defined (ACE_HAS_SYSV_IPC)
2288   return ::semop (int_id, sops, nsops);
2289 #else
2290   ACE_UNUSED_ARG (int_id);
2291   ACE_UNUSED_ARG (sops);
2292   ACE_UNUSED_ARG (nsops);
2294   ACE_NOTSUP_RETURN (-1);
2295 #endif /* ACE_HAS_SYSV_IPC */
2298 ACE_INLINE int
2299 ACE_OS::sigtimedwait (const sigset_t *sset,
2300                       siginfo_t *info,
2301                       const ACE_Time_Value *timeout)
2303   ACE_OS_TRACE ("ACE_OS::sigtimedwait");
2304 #if defined (ACE_HAS_SIGTIMEDWAIT)
2305   timespec_t ts;
2306   timespec_t *tsp = 0;
2308   if (timeout != 0)
2309     {
2310       ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
2311       tsp = &ts;
2312     }
2314   return ::sigtimedwait (sset, info, tsp);
2315 #else
2316     ACE_UNUSED_ARG (sset);
2317     ACE_UNUSED_ARG (info);
2318     ACE_UNUSED_ARG (timeout);
2319     ACE_NOTSUP_RETURN (-1);
2320 #endif /* ACE_HAS_SIGTIMEDWAIT */
2323 ACE_INLINE int
2324 ACE_OS::sigwait (sigset_t *sset, int *sig)
2326   ACE_OS_TRACE ("ACE_OS::sigwait");
2327   int local_sig;
2328   if (sig == 0)
2329     sig = &local_sig;
2330 #if defined (ACE_HAS_THREADS)
2331 # if (defined (__FreeBSD__) && (__FreeBSD__ < 3))
2332     ACE_UNUSED_ARG (sset);
2333     ACE_NOTSUP_RETURN (-1);
2334 # elif defined (ACE_HAS_PTHREADS)
2335 #   if defined (CYGWIN32)
2336       // Cygwin has sigwait definition, but it is not implemented
2337       ACE_UNUSED_ARG (sset);
2338       ACE_NOTSUP_RETURN (-1);
2339 #   else   /* this is std */
2340       errno = ::sigwait (sset, sig);
2341       return errno == 0  ?  *sig  :  -1;
2342 #   endif /* CYGWIN32 */
2343 # elif defined (ACE_HAS_WTHREADS)
2344     ACE_UNUSED_ARG (sset);
2345     ACE_NOTSUP_RETURN (-1);
2346 # elif defined (ACE_VXWORKS)
2347     // Second arg is a struct siginfo *, which we don't need (the
2348     // selected signal number is returned).  Third arg is timeout:  0
2349     // means forever.
2350     *sig = ::sigtimedwait (sset, 0, 0);
2351     return *sig;
2352 # endif /* __FreeBSD__ */
2353 #else
2354     ACE_UNUSED_ARG (sset);
2355     ACE_UNUSED_ARG (sig);
2356     ACE_NOTSUP_RETURN (-1);
2357 #endif /* ACE_HAS_THREADS */
2360 ACE_INLINE int
2361 ACE_OS::sigwaitinfo (const sigset_t *sset,
2362                      siginfo_t *info)
2364   ACE_OS_TRACE ("ACE_OS::sigwaitinfo");
2365   // If this platform has sigtimedwait, it should have sigwaitinfo as well.
2366   // If this isn't true somewhere, let me know and I'll fix this.
2367   // -Steve Huston <shuston@riverace.com>.
2368 #if defined (ACE_HAS_SIGTIMEDWAIT)
2369   return ::sigwaitinfo (sset, info);
2370 #else
2371   ACE_UNUSED_ARG (sset);
2372   ACE_UNUSED_ARG (info);
2373   ACE_NOTSUP_RETURN (-1);
2374 #endif /* ACE_HAS_SIGTIMEDWAIT */
2377 ACE_INLINE int
2378 ACE_OS::thr_cancel (ACE_thread_t thr_id)
2380   ACE_OS_TRACE ("ACE_OS::thr_cancel");
2381 #if defined (ACE_HAS_THREADS)
2382 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
2383   int result;
2384   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cancel (thr_id),
2385                                         result),
2386                       int);
2387 # elif defined (ACE_HAS_VXTHREADS)
2388   return ::taskDelete (thr_id);
2389 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
2390   ACE_UNUSED_ARG (thr_id);
2391   ACE_NOTSUP_RETURN (-1);
2392 # endif /* ACE_HAS_PTHREADS */
2393 #else
2394   ACE_UNUSED_ARG (thr_id);
2395   ACE_NOTSUP_RETURN (-1);
2396 #endif /* ACE_HAS_THREADS */
2399 ACE_INLINE int
2400 ACE_OS::thr_cmp (ACE_hthread_t t1, ACE_hthread_t t2)
2402 #if defined (ACE_HAS_PTHREADS)
2403 # if defined (pthread_equal)
2404   // If it's a macro we can't say "pthread_equal"...
2405   return pthread_equal (t1, t2);
2406 # else
2407   return pthread_equal (t1, t2);
2408 # endif /* pthread_equal */
2409 #else /* For STHREADS, WTHREADS, and VXWORKS ... */
2410   // Hum, Do we need to treat WTHREAD differently?
2411   // levine 13 oct 98 % Probably, ACE_hthread_t is a HANDLE.
2412   return t1 == t2;
2413 #endif /* ACE_HAS_PTHREADS */
2416 ACE_INLINE int
2417 ACE_OS::thr_continue (ACE_hthread_t target_thread)
2419   ACE_OS_TRACE ("ACE_OS::thr_continue");
2420 #if defined (ACE_HAS_THREADS)
2421 # if defined (ACE_HAS_PTHREADS)
2422 #  if defined (ACE_HAS_PTHREAD_CONTINUE)
2423   int result;
2424   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue (target_thread),
2425                                        result),
2426                      int);
2427 #  elif defined (ACE_HAS_PTHREAD_CONTINUE_NP)
2428   int result;
2429   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue_np (target_thread),
2430                                        result),
2431                      int);
2432 #  elif defined (ACE_HAS_PTHREAD_RESUME_NP)
2433   int result;
2434   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_resume_np (target_thread),
2435                                        result),
2436                      int);
2437 #  else
2438   ACE_UNUSED_ARG (target_thread);
2439   ACE_NOTSUP_RETURN (-1);
2440 #  endif /* ACE_HAS_PTHREAD_CONTINUE */
2441 # elif defined (ACE_HAS_WTHREADS)
2442   DWORD result = ::ResumeThread (target_thread);
2443   if (result == ACE_SYSCALL_FAILED)
2444     ACE_FAIL_RETURN (-1);
2445   else
2446     return 0;
2447 # elif defined (ACE_HAS_VXTHREADS)
2448   return ::taskResume (target_thread);
2449 # endif /* ACE_HAS_PTHREADS */
2450 #else
2451   ACE_UNUSED_ARG (target_thread);
2452   ACE_NOTSUP_RETURN (-1);
2453 #endif /* ACE_HAS_THREADS */
2456 ACE_INLINE int
2457 ACE_OS::thr_getconcurrency ()
2459   ACE_OS_TRACE ("ACE_OS::thr_getconcurrency");
2460 #if defined (ACE_HAS_THREADS)
2461 # if defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_GETCONCURRENCY)
2462   return pthread_getconcurrency ();
2463 # else
2464   ACE_NOTSUP_RETURN (-1);
2465 # endif /* ACE_HAS_PTHREADS */
2466 #else
2467   ACE_NOTSUP_RETURN (-1);
2468 #endif /* ACE_HAS_THREADS */
2471 ACE_INLINE int
2472 ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority, int &policy)
2474   ACE_OS_TRACE ("ACE_OS::thr_getprio");
2475   ACE_UNUSED_ARG (policy);
2476 #if defined (ACE_HAS_THREADS)
2477 # if (defined (ACE_HAS_PTHREADS) && \
2478      (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
2480   struct sched_param param;
2481   int result;
2483   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
2484                                 result), int,
2485               result);
2486   priority = param.sched_priority;
2487   return result;
2488 # elif defined (ACE_HAS_WTHREADS)
2489   ACE_Errno_Guard error (errno);
2490   priority = ::GetThreadPriority (ht_id);
2491   DWORD const priority_class = ::GetPriorityClass (::GetCurrentProcess ());
2492   if (priority_class == 0 && (error = ::GetLastError ()) != NO_ERROR)
2493     ACE_FAIL_RETURN (-1);
2495   policy = (priority_class == REALTIME_PRIORITY_CLASS) ? ACE_SCHED_FIFO : ACE_SCHED_OTHER;
2496   return 0;
2497 # elif defined (ACE_HAS_VXTHREADS)
2498   return ::taskPriorityGet (ht_id, &priority);
2499 # else
2500   ACE_UNUSED_ARG (ht_id);
2501   ACE_UNUSED_ARG (priority);
2502   ACE_NOTSUP_RETURN (-1);
2503 # endif /* ACE_HAS_PTHREADS */
2504 #else
2505   ACE_UNUSED_ARG (ht_id);
2506   ACE_UNUSED_ARG (priority);
2507   ACE_NOTSUP_RETURN (-1);
2508 #endif /* ACE_HAS_THREADS */
2511 ACE_INLINE int
2512 ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority)
2514   ACE_OS_TRACE ("ACE_OS::thr_getprio");
2515   int policy = 0;
2516   return ACE_OS::thr_getprio (ht_id, priority, policy);
2519 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
2520 ACE_INLINE int
2521 ACE_OS::thr_getspecific_native (ACE_OS_thread_key_t key, void **data)
2523 //  ACE_OS_TRACE ("ACE_OS::thr_getspecific_native");
2524 # if defined (ACE_HAS_PTHREADS)
2525     *data = pthread_getspecific (key);
2526     return 0;
2527 # elif defined (ACE_HAS_WTHREADS)
2528   *data = ::TlsGetValue (key);
2529   if (*data == 0 && ::GetLastError () != NO_ERROR)
2530     {
2531       ACE_OS::set_errno_to_last_error ();
2532       return -1;
2533     }
2534   else
2535     return 0;
2536 # else /* ACE_HAS_PTHREADS etc.*/
2537   ACE_UNUSED_ARG (key);
2538   ACE_UNUSED_ARG (data);
2539   ACE_NOTSUP_RETURN (-1);
2540 # endif /* ACE_HAS_PTHREADS etc.*/
2542 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
2544 ACE_INLINE int
2545 ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data)
2547 //   ACE_OS_TRACE ("ACE_OS::thr_getspecific");
2548 #if defined (ACE_HAS_THREADS)
2549 # if defined (ACE_HAS_TSS_EMULATION)
2550     if (ACE_TSS_Emulation::is_key (key) == 0)
2551       {
2552         errno = EINVAL;
2553         data = 0;
2554         return -1;
2555       }
2556     else
2557       {
2558         *data = ACE_TSS_Emulation::ts_object (key);
2559         return 0;
2560       }
2561 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
2562   return ACE_OS::thr_getspecific_native (key, data);
2563 #else
2564   ACE_UNUSED_ARG (key);
2565   ACE_UNUSED_ARG (data);
2566   ACE_NOTSUP_RETURN (-1);
2567 # endif /* ACE_HAS_TSS_EMULATION */
2568 #else
2569   ACE_UNUSED_ARG (key);
2570   ACE_UNUSED_ARG (data);
2571   ACE_NOTSUP_RETURN (-1);
2572 #endif /* ACE_HAS_THREADS */
2575 #if !defined (ACE_HAS_VXTHREADS)
2576 ACE_INLINE int
2577 ACE_OS::thr_join (ACE_hthread_t thr_handle,
2578                   ACE_THR_FUNC_RETURN *status)
2580   ACE_OS_TRACE ("ACE_OS::thr_join");
2581 #if defined (ACE_HAS_THREADS)
2582 # if defined (ACE_HAS_PTHREADS)
2583 #  if defined (ACE_LACKS_PTHREAD_JOIN)
2584   ACE_UNUSED_ARG (thr_handle);
2585   ACE_UNUSED_ARG (status);
2586   ACE_NOTSUP_RETURN (-1);
2587 #  else
2588   int result;
2589   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (thr_handle, status), result),
2590                      int);
2591 #  endif /* ACE_LACKS_PTHREAD_JOIN */
2592 # elif defined (ACE_HAS_WTHREADS)
2593   // Waiting on the calling thread will deadlock, so try to avoid that. The
2594   // direct access to the needed info (GetThreadId) was added at Vista.
2595   // Win Server 2003 is 5.2; Vista is 6.0
2596 #   if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0502)
2597   const ACE_TEXT_OSVERSIONINFO &info = ACE_OS::get_win32_versioninfo ();
2598   if (info.dwMajorVersion >= 6 ||
2599       (info.dwMajorVersion == 5 && info.dwMinorVersion == 2))
2600     {
2601       if (::GetThreadId (thr_handle) == ::GetCurrentThreadId ())
2602         {
2603           errno = ERROR_POSSIBLE_DEADLOCK;
2604           return -1;
2605         }
2606     }
2607 #   endif /* _WIN32_WINNT */
2609   ACE_THR_FUNC_RETURN local_status = 0;
2611   // Make sure that status is non-NULL.
2612   if (status == 0)
2613     status = &local_status;
2615   if (::WaitForSingleObject (thr_handle, INFINITE) == WAIT_OBJECT_0
2616       && ::GetExitCodeThread (thr_handle, status) != FALSE)
2617     {
2618       ::CloseHandle (thr_handle);
2619       return 0;
2620     }
2621   ACE_FAIL_RETURN (-1);
2622   /* NOTREACHED */
2623 # else
2624   ACE_UNUSED_ARG (thr_handle);
2625   ACE_UNUSED_ARG (status);
2626   ACE_NOTSUP_RETURN (-1);
2627 # endif /* ACE_HAS_PTHREADS */
2628 #else
2629   ACE_UNUSED_ARG (thr_handle);
2630   ACE_UNUSED_ARG (status);
2631   ACE_NOTSUP_RETURN (-1);
2632 #endif /* ACE_HAS_THREADS */
2635 ACE_INLINE int
2636 ACE_OS::thr_join (ACE_thread_t waiter_id,
2637                   ACE_thread_t *thr_id,
2638                   ACE_THR_FUNC_RETURN *status)
2640   ACE_OS_TRACE ("ACE_OS::thr_join");
2641 #if defined (ACE_HAS_THREADS)
2642 # if defined (ACE_HAS_PTHREADS)
2643 #  if defined (ACE_LACKS_PTHREAD_JOIN)
2644   ACE_UNUSED_ARG (waiter_id);
2645   ACE_UNUSED_ARG (thr_id);
2646   ACE_UNUSED_ARG (status);
2647   ACE_NOTSUP_RETURN (-1);
2648 #  else
2649   ACE_UNUSED_ARG (thr_id);
2650   int result;
2651   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (waiter_id, status), result),
2652                      int);
2653 #  endif /* ACE_LACKS_PTHREAD_JOIN */
2654 # elif defined (ACE_HAS_WTHREADS)
2655   ACE_UNUSED_ARG (waiter_id);
2656   ACE_UNUSED_ARG (thr_id);
2657   ACE_UNUSED_ARG (status);
2659   // This could be implemented if the DLL-Main function or the
2660   // task exit base class some log the threads which have exited
2661   ACE_NOTSUP_RETURN (-1);
2662 # endif /* ACE_HAS_PTHREADS */
2663 #else
2664   ACE_UNUSED_ARG (waiter_id);
2665   ACE_UNUSED_ARG (thr_id);
2666   ACE_UNUSED_ARG (status);
2667   ACE_NOTSUP_RETURN (-1);
2668 #endif /* ACE_HAS_THREADS */
2670 #endif /* !VXWORKS */
2672 ACE_INLINE int
2673 ACE_OS::thr_kill (ACE_thread_t thr_id, int signum)
2675   ACE_OS_TRACE ("ACE_OS::thr_kill");
2676 #if defined (ACE_HAS_THREADS)
2677 # if defined (ACE_HAS_PTHREADS)
2678 #   if defined (ACE_LACKS_PTHREAD_KILL)
2679   ACE_UNUSED_ARG (signum);
2680   ACE_UNUSED_ARG (thr_id);
2681   ACE_NOTSUP_RETURN (-1);
2682 #   else
2683   int result;
2684   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_kill (thr_id, signum),
2685                                        result),
2686                      int);
2687 #   endif /* ACE_LACKS_PTHREAD_KILL */
2688 # elif defined (ACE_HAS_VXTHREADS)
2689   //FUZZ: disable check_for_lack_ACE_OS
2690   return ::kill (thr_id, signum);
2691   //FUZZ: enable check_for_lack_ACE_OS
2692 # else
2693   ACE_UNUSED_ARG (thr_id);
2694   ACE_UNUSED_ARG (signum);
2695   ACE_NOTSUP_RETURN (-1);
2696 # endif /* ACE_HAS_PTHREADS */
2697 #else
2698   ACE_UNUSED_ARG (thr_id);
2699   ACE_UNUSED_ARG (signum);
2700   ACE_NOTSUP_RETURN (-1);
2701 #endif /* ACE_HAS_THREADS */
2704 ACE_INLINE size_t
2705 ACE_OS::thr_min_stack ()
2707   ACE_OS_TRACE ("ACE_OS::thr_min_stack");
2708 #if defined (ACE_HAS_THREADS)
2709 # if defined (ACE_HAS_PTHREADS)
2710 #   if defined (_SC_THREAD_STACK_MIN)
2711   return (size_t) ACE_OS::sysconf (_SC_THREAD_STACK_MIN);
2712 #   elif defined (PTHREAD_STACK_MIN)
2713   return PTHREAD_STACK_MIN;
2714 #   else
2715   ACE_NOTSUP_RETURN (0);
2716 #   endif /* _SC_THREAD_STACK_MIN */
2717 # elif defined (ACE_HAS_WTHREADS)
2718   ACE_NOTSUP_RETURN (0);
2719 # elif defined (ACE_HAS_VXTHREADS)
2720   TASK_DESC taskDesc;
2721   STATUS status;
2723   ACE_thread_t tid = ACE_OS::thr_self ();
2725   ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (tid, &taskDesc),
2726                                 status),
2727               STATUS, status);
2728   return status == OK ? taskDesc.td_stackSize : 0;
2729 # else /* Should not happen... */
2730   ACE_NOTSUP_RETURN (0);
2731 # endif /* ACE_HAS_PTHREADS */
2732 #else
2733   ACE_NOTSUP_RETURN (0);
2734 #endif /* ACE_HAS_THREADS */
2737 ACE_INLINE ssize_t
2738 ACE_OS::thr_id (char buffer[], size_t buffer_length)
2740 #if defined (ACE_WIN32)
2741   return ACE_OS::snprintf (buffer,
2742                            buffer_length,
2743                            "%u",
2744                            static_cast <unsigned> (ACE_OS::thr_self ()));
2745 #else /* ACE_WIN32 */
2746   ACE_hthread_t t_id;
2747   ACE_OS::thr_self (t_id);
2748 #if defined(ACE_HAS_OPAQUE_PTHREAD_T)
2749   return ACE_OS::snprintf (buffer,
2750                            buffer_length,
2751                            "%s",
2752                            "<unknown>");
2753 #else /* ACE_HAS_OPAQUE_PTHREAD_T */
2754   return ACE_OS::snprintf (buffer,
2755                            buffer_length,
2756                            "%lu",
2757                            (unsigned long) t_id);
2758 #endif /* ACE_HAS_OPAQUE_PTHREAD_T */
2759 #endif /* WIN32 */
2762 ACE_INLINE ssize_t
2763 ACE_OS::thr_gettid (char buffer[], size_t buffer_length)
2765   return ACE_OS::snprintf (buffer, buffer_length, "%d",
2766     static_cast<int> (ACE_OS::thr_gettid ()));
2769 ACE_INLINE pid_t
2770 ACE_OS::thr_gettid ()
2772 #ifdef ACE_HAS_GETTID
2773   return syscall (SYS_gettid);
2774 #else
2775   ACE_NOTSUP_RETURN (-1);
2776 #endif
2779 ACE_INLINE ACE_thread_t
2780 ACE_OS::thr_self ()
2782   // ACE_OS_TRACE ("ACE_OS::thr_self");
2783 #if defined (ACE_HAS_THREADS)
2784 # if defined (ACE_HAS_PTHREADS)
2785   // Note, don't use "::" here since the following call is often a macro.
2786   return pthread_self ();
2787 # elif defined (ACE_HAS_WTHREADS)
2788   return ::GetCurrentThreadId ();
2789 # elif defined (ACE_HAS_VXTHREADS)
2790   return ::taskIdSelf ();
2791 # endif /* ACE_HAS_PTHREADS */
2792 #else
2793   return 1; // Might as well make it the first thread ;-)
2794 #endif /* ACE_HAS_THREADS */
2797 ACE_INLINE const char*
2798 ACE_OS::thr_name ()
2800 #if defined (ACE_HAS_THREADS)
2801 #if defined (ACE_HAS_VXTHREADS)
2802   return ::taskName (ACE_OS::thr_self ());
2803 #else
2804   ACE_NOTSUP_RETURN (0);
2805 #endif
2806 #else
2807   ACE_NOTSUP_RETURN (0);
2808 #endif
2811 ACE_INLINE void
2812 ACE_OS::thr_self (ACE_hthread_t &self)
2814   ACE_OS_TRACE ("ACE_OS::thr_self");
2815 #if defined (ACE_HAS_THREADS)
2816 # if defined (ACE_HAS_PTHREADS)
2817   // Note, don't use "::" here since the following call is often a macro.
2818   self = pthread_self ();
2819 # elif defined (ACE_HAS_THREAD_SELF)
2820   self = ::thread_self ();
2821 # elif defined (ACE_HAS_WTHREADS)
2822   self = ::GetCurrentThread ();
2823 # elif defined (ACE_HAS_VXTHREADS)
2824   self = ::taskIdSelf ();
2825 # endif /* ACE_HAS_PTHREADS */
2826 #else
2827   self = 1; // Might as well make it the main thread ;-)
2828 #endif /* ACE_HAS_THREADS */
2831 ACE_INLINE int
2832 ACE_OS::thr_setcancelstate (int new_state, int *old_state)
2834   ACE_OS_TRACE ("ACE_OS::thr_setcancelstate");
2835 #if defined (ACE_HAS_THREADS)
2836 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
2837   int result;
2838   int local_new, local_old;
2839   switch (new_state)
2840     {
2841     case THR_CANCEL_ENABLE:
2842       local_new = PTHREAD_CANCEL_ENABLE;
2843       break;
2844     case THR_CANCEL_DISABLE:
2845       local_new = PTHREAD_CANCEL_DISABLE;
2846       break;
2847     default:
2848       errno = EINVAL;
2849       return -1;
2850     }
2851   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_setcancelstate (local_new,
2852                                                         &local_old),
2853                                 result),
2854               int, result);
2855   if (result == -1)
2856     return -1;
2857   switch (local_old)
2858     {
2859     case PTHREAD_CANCEL_ENABLE:
2860       *old_state = THR_CANCEL_ENABLE;
2861       break;
2862     case PTHREAD_CANCEL_DISABLE:
2863       *old_state = THR_CANCEL_DISABLE;
2864       break;
2865     }
2866   return result;
2867 # elif defined (ACE_HAS_WTHREADS)
2868   ACE_UNUSED_ARG (new_state);
2869   ACE_UNUSED_ARG (old_state);
2870   ACE_NOTSUP_RETURN (-1);
2871 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
2872   ACE_UNUSED_ARG (new_state);
2873   ACE_UNUSED_ARG (old_state);
2874   ACE_NOTSUP_RETURN (-1);
2875 # endif /* ACE_HAS_PTHREADS */
2876 #else
2877   ACE_UNUSED_ARG (new_state);
2878   ACE_UNUSED_ARG (old_state);
2879   ACE_NOTSUP_RETURN (-1);
2880 #endif /* ACE_HAS_THREADS */
2883 ACE_INLINE int
2884 ACE_OS::thr_setcanceltype (int new_type, int *old_type)
2886   ACE_OS_TRACE ("ACE_OS::thr_setcanceltype");
2887 #if defined (ACE_HAS_THREADS)
2888 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
2889   int result;
2890   int local_new, local_old;
2891   switch (new_type)
2892     {
2893     case THR_CANCEL_DEFERRED:
2894       local_new = PTHREAD_CANCEL_DEFERRED;
2895       break;
2896     case THR_CANCEL_ASYNCHRONOUS:
2897       local_new = PTHREAD_CANCEL_ASYNCHRONOUS;
2898       break;
2899     default:
2900       errno = EINVAL;
2901       return -1;
2902     }
2903   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_setcanceltype (local_new,
2904                                                        &local_old),
2905                                 result),
2906               int, result);
2907   if (result == -1)
2908     return -1;
2909   switch (local_old)
2910     {
2911     case PTHREAD_CANCEL_DEFERRED:
2912       *old_type = THR_CANCEL_DEFERRED;
2913       break;
2914     case PTHREAD_CANCEL_ASYNCHRONOUS:
2915       *old_type = THR_CANCEL_ASYNCHRONOUS;
2916       break;
2917     }
2918   return result;
2919 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
2920   ACE_UNUSED_ARG (new_type);
2921   ACE_UNUSED_ARG (old_type);
2922   ACE_NOTSUP_RETURN (-1);
2923 # endif /* ACE_HAS_PTHREADS */
2924 #else
2925   ACE_UNUSED_ARG (new_type);
2926   ACE_UNUSED_ARG (old_type);
2927   ACE_NOTSUP_RETURN (-1);
2928 #endif /* ACE_HAS_THREADS */
2931 ACE_INLINE int
2932 ACE_OS::thr_setconcurrency (int hint)
2934   ACE_OS_TRACE ("ACE_OS::thr_setconcurrency");
2935 #if defined (ACE_HAS_THREADS)
2936 # if defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_SETCONCURRENCY)
2937   int result;
2938   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setconcurrency (hint), result), int);
2939 # else
2940   ACE_UNUSED_ARG (hint);
2941   ACE_NOTSUP_RETURN (-1);
2942 # endif /* ACE_HAS_PTHREADS */
2943 #else
2944   ACE_UNUSED_ARG (hint);
2945   ACE_NOTSUP_RETURN (-1);
2946 #endif /* ACE_HAS_THREADS */
2949 ACE_INLINE int
2950 ACE_OS::thr_setprio (ACE_hthread_t ht_id, int priority, int policy)
2952   ACE_OS_TRACE ("ACE_OS::thr_setprio");
2953   ACE_UNUSED_ARG (policy);
2954 #if defined (ACE_HAS_THREADS)
2955 # if (defined (ACE_HAS_PTHREADS) && \
2956       (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
2958   int result;
2959   struct sched_param param;
2960   ACE_OS::memset ((void *) &param, 0, sizeof param);
2962   // If <policy> is -1, we don't want to use it for
2963   // pthread_setschedparam().  Instead, obtain policy from
2964   // pthread_getschedparam().
2965   if (policy == -1)
2966     {
2967       ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param), result), int, result);
2968       if (result == -1)
2969         return result;
2970     }
2972   param.sched_priority = priority;
2974   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setschedparam (ht_id,
2975                                                               policy,
2976                                                               &param),
2977                                        result),
2978                      int);
2979 # elif defined (ACE_HAS_WTHREADS)
2980   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetThreadPriority (ht_id, priority),
2981                                           ace_result_),
2982                         int, -1);
2983 # elif defined (ACE_HAS_VXTHREADS)
2984   ACE_OSCALL_RETURN (::taskPrioritySet (ht_id, priority), int);
2985 # else
2986   // For example, platforms that support Pthreads but LACK_SETSCHED.
2987   ACE_UNUSED_ARG (ht_id);
2988   ACE_UNUSED_ARG (priority);
2989   ACE_NOTSUP_RETURN (-1);
2990 # endif /* ACE_HAS_PTHREADS */
2991 #else
2992   ACE_UNUSED_ARG (ht_id);
2993   ACE_UNUSED_ARG (priority);
2994   ACE_NOTSUP_RETURN (-1);
2995 #endif /* ACE_HAS_THREADS */
2998 ACE_INLINE int
2999 ACE_OS::thr_sigsetmask (int how,
3000                         const sigset_t *nsm,
3001                         sigset_t *osm)
3003   ACE_OS_TRACE ("ACE_OS::thr_sigsetmask");
3004 #if defined (ACE_HAS_THREADS)
3005 # if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
3006   // DCE threads
3007   ACE_UNUSED_ARG (osm);
3008   ACE_UNUSED_ARG (nsm);
3009   ACE_UNUSED_ARG (how);
3011   ACE_NOTSUP_RETURN (-1);
3012 # elif defined (ACE_HAS_SIGTHREADMASK)
3013   int result;
3014   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigthreadmask (how, nsm, osm), result), int);
3015 # elif defined (ACE_HAS_PTHREADS)
3016 #   if !defined (ACE_LACKS_PTHREAD_SIGMASK)
3017   int result;
3018   //FUZZ: disable check_for_lack_ACE_OS
3019 #    if defined (ACE_HAS_NONCONST_PTHREAD_SIGMASK)
3020   sigset_t *ncnsm = const_cast<sigset_t *>(nsm);
3021   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, ncnsm, osm), result), int);
3022 #    else
3023   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm), result), int);
3024 #    endif /* ACE_HAS_NONCONST__PTHREAD_SIGMASK */
3025   //FUZZ: enable check_for_lack_ACE_OS
3026 #   endif /* !ACE_LACKS_PTHREAD_SIGMASK */
3028 # elif defined (ACE_HAS_WTHREADS)
3029   ACE_UNUSED_ARG (osm);
3030   ACE_UNUSED_ARG (nsm);
3031   ACE_UNUSED_ARG (how);
3033   ACE_NOTSUP_RETURN (-1);
3034 # elif defined (ACE_VXWORKS)
3035   int old_mask = 0;
3036   switch (how)
3037     {
3038     case SIG_BLOCK:
3039     case SIG_UNBLOCK:
3040       {
3041         // get the old mask
3042         old_mask = ::sigsetmask (*nsm);
3043         // create a new mask:  the following assumes that sigset_t is 4 bytes,
3044         // which it is on VxWorks 5.2, so bit operations are done simply . . .
3045         ::sigsetmask (how == SIG_BLOCK ? (old_mask |= *nsm) : (old_mask &= ~*nsm));
3046         if (osm)
3047           *osm = old_mask;
3048         break;
3049       }
3050     case SIG_SETMASK:
3051       old_mask = ::sigsetmask (*nsm);
3052       if (osm)
3053         *osm = old_mask;
3054       break;
3055     default:
3056       return -1;
3057     }
3059   return 0;
3060 # else /* Should not happen. */
3061   ACE_UNUSED_ARG (how);
3062   ACE_UNUSED_ARG (nsm);
3063   ACE_UNUSED_ARG (osm);
3064   ACE_NOTSUP_RETURN (-1);
3065 # endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
3066 #else
3067   ACE_UNUSED_ARG (how);
3068   ACE_UNUSED_ARG (nsm);
3069   ACE_UNUSED_ARG (osm);
3070   ACE_NOTSUP_RETURN (-1);
3071 #endif /* ACE_HAS_THREADS */
3074 ACE_INLINE int
3075 ACE_OS::thr_suspend (ACE_hthread_t target_thread)
3077   ACE_OS_TRACE ("ACE_OS::thr_suspend");
3078 #if defined (ACE_HAS_THREADS)
3079 # if defined (ACE_HAS_PTHREADS)
3080 #  if defined (ACE_HAS_PTHREAD_SUSPEND)
3081   int result;
3082   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend (target_thread), result), int);
3083 #  elif defined (ACE_HAS_PTHREAD_SUSPEND_NP)
3084   int result;
3085   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend_np (target_thread), result), int);
3086 #  else
3087   ACE_UNUSED_ARG (target_thread);
3088   ACE_NOTSUP_RETURN (-1);
3089 #  endif /* ACE_HAS_PTHREAD_SUSPEND */
3090 # elif defined (ACE_HAS_WTHREADS)
3091   if (::SuspendThread (target_thread) != ACE_SYSCALL_FAILED)
3092     return 0;
3093   else
3094     ACE_FAIL_RETURN (-1);
3095   /* NOTREACHED */
3096 # elif defined (ACE_HAS_VXTHREADS)
3097   return ::taskSuspend (target_thread);
3098 # endif /* ACE_HAS_PTHREADS */
3099 #else
3100   ACE_UNUSED_ARG (target_thread);
3101   ACE_NOTSUP_RETURN (-1);
3102 #endif /* ACE_HAS_THREADS */
3105 ACE_INLINE void
3106 ACE_OS::thr_testcancel ()
3108   ACE_OS_TRACE ("ACE_OS::thr_testcancel");
3109 #if defined (ACE_HAS_THREADS)
3110 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
3111   pthread_testcancel ();
3112 # else
3113   // no-op:  can't use ACE_NOTSUP_RETURN because there is no return value
3114 # endif /* ACE_HAS_PTHREADS */
3115 #else
3116 #endif /* ACE_HAS_THREADS */
3119 ACE_INLINE void
3120 ACE_OS::thr_yield ()
3122   ACE_OS_TRACE ("ACE_OS::thr_yield");
3123 #if defined (ACE_HAS_THREADS)
3124 # if defined (ACE_HAS_PTHREADS)
3125   ::sched_yield ();
3126 # elif defined (ACE_HAS_WTHREADS)
3127   ::Sleep (0);
3128 # elif defined (ACE_HAS_VXTHREADS)
3129   // An argument of 0 to ::taskDelay doesn't appear to yield the
3130   // current thread.
3131   // Now, it does seem to work.  The context_switch_time test
3132   // works fine with task_delay set to 0.
3133   ::taskDelay (0);
3134 # endif /* ACE_HAS_PTHREADS */
3135 #else
3136   ;
3137 #endif /* ACE_HAS_THREADS */
3140 ACE_INLINE int
3141 ACE_OS::thread_mutex_destroy (ACE_thread_mutex_t *m)
3143   ACE_OS_TRACE ("ACE_OS::thread_mutex_destroy");
3144 #if defined (ACE_HAS_THREADS)
3145 # if defined (ACE_HAS_WTHREADS)
3146   ::DeleteCriticalSection (m);
3147   return 0;
3148 # else
3149   return ACE_OS::mutex_destroy (m);
3150 # endif /* ACE_HAS_WTHREADS */
3151 #else
3152   ACE_UNUSED_ARG (m);
3153   ACE_NOTSUP_RETURN (-1);
3155 #endif /* ACE_HAS_THREADS */
3158 ACE_INLINE int
3159 ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
3160                            int lock_type,
3161                            const char *name,
3162                            ACE_mutexattr_t *arg)
3164   // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
3165 #if defined (ACE_HAS_THREADS)
3166 # if defined (ACE_HAS_WTHREADS)
3167   ACE_UNUSED_ARG (lock_type);
3168   ACE_UNUSED_ARG (name);
3169   ACE_UNUSED_ARG (arg);
3171   ACE_SEH_TRY
3172     {
3173       ::InitializeCriticalSection (m);
3174     }
3175   ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3176     {
3177       errno = ENOMEM;
3178       return -1;
3179     }
3180   return 0;
3182 # elif defined (ACE_HAS_PTHREADS)
3183   // Force the use of USYNC_THREAD!
3184   return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
3185 # elif defined (ACE_HAS_VXTHREADS)
3186   return mutex_init (m, lock_type, name, arg);
3188 # endif /* ACE_HAS_PTHREADS */
3190 #else
3191   ACE_UNUSED_ARG (m);
3192   ACE_UNUSED_ARG (lock_type);
3193   ACE_UNUSED_ARG (name);
3194   ACE_UNUSED_ARG (arg);
3195   ACE_NOTSUP_RETURN (-1);
3197 #endif /* ACE_HAS_THREADS */
3200 #if defined (ACE_HAS_WCHAR)
3201 ACE_INLINE int
3202 ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
3203                            int lock_type,
3204                            const wchar_t *name,
3205                            ACE_mutexattr_t *arg)
3207   // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
3208 #if defined (ACE_HAS_THREADS)
3209 # if defined (ACE_HAS_WTHREADS)
3210   ACE_UNUSED_ARG (lock_type);
3211   ACE_UNUSED_ARG (name);
3212   ACE_UNUSED_ARG (arg);
3214   ACE_SEH_TRY
3215     {
3216       ::InitializeCriticalSection (m);
3217     }
3218   ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3219     {
3220       errno = ENOMEM;
3221       return -1;
3222     }
3223   return 0;
3225 # elif defined (ACE_HAS_PTHREADS)
3226   // Force the use of USYNC_THREAD!
3227   return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
3228 # elif defined (ACE_HAS_VXTHREADS)
3229   return mutex_init (m, lock_type, name, arg);
3230 # endif /* ACE_HAS_PTHREADS */
3231 #else
3232   ACE_UNUSED_ARG (m);
3233   ACE_UNUSED_ARG (lock_type);
3234   ACE_UNUSED_ARG (name);
3235   ACE_UNUSED_ARG (arg);
3236   ACE_NOTSUP_RETURN (-1);
3238 #endif /* ACE_HAS_THREADS */
3240 #endif /* ACE_HAS_WCHAR */
3242 ACE_INLINE int
3243 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m)
3245   // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
3246 #if defined (ACE_HAS_THREADS)
3247 # if defined (ACE_HAS_WTHREADS)
3248   ::EnterCriticalSection (m);
3249   return 0;
3250 # else
3251   return ACE_OS::mutex_lock (m);
3252 # endif /* ACE_HAS_WTHREADS */
3253 #else
3254   ACE_UNUSED_ARG (m);
3255   ACE_NOTSUP_RETURN (-1);
3256 #endif /* ACE_HAS_THREADS */
3259 ACE_INLINE int
3260 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
3261                            const ACE_Time_Value &timeout)
3263   // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
3265   // For all platforms, except MS Windows, this method is equivalent
3266   // to calling ACE_OS::mutex_lock() since ACE_thread_mutex_t and
3267   // ACE_mutex_t are the same type.  However, those typedefs evaluate
3268   // to different types on MS Windows.  The "thread mutex"
3269   // implementation in ACE for MS Windows cannot readily support
3270   // timeouts due to a lack of timeout features for this type of MS
3271   // Windows synchronization mechanism.
3273 #if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_WTHREADS)
3274   return ACE_OS::mutex_lock (m, timeout);
3275 #else
3276   ACE_UNUSED_ARG (m);
3277   ACE_UNUSED_ARG (timeout);
3278   ACE_NOTSUP_RETURN (-1);
3279 #endif /* ACE_HAS_THREADS */
3282 ACE_INLINE int
3283 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
3284                            const ACE_Time_Value *timeout)
3286   return timeout == 0
3287     ? ACE_OS::thread_mutex_lock (m)
3288     : ACE_OS::thread_mutex_lock (m, *timeout);
3291 ACE_INLINE int
3292 ACE_OS::thread_mutex_trylock (ACE_thread_mutex_t *m)
3294   ACE_OS_TRACE ("ACE_OS::thread_mutex_trylock");
3296 #if defined (ACE_HAS_THREADS)
3297 # if defined (ACE_HAS_WTHREADS)
3298 #   if defined (ACE_HAS_WIN32_TRYLOCK)
3299   BOOL result = ::TryEnterCriticalSection (m);
3300   if (result)
3301     {
3302       return 0;
3303     }
3304   else
3305     {
3306       errno = EBUSY;
3307       return -1;
3308     }
3309 #   else
3310   ACE_UNUSED_ARG (m);
3311   ACE_NOTSUP_RETURN (-1);
3312 #   endif /* ACE_HAS_WIN32_TRYLOCK */
3313 # elif defined (ACE_HAS_PTHREADS) || defined (ACE_VXWORKS)
3314   return ACE_OS::mutex_trylock (m);
3315 #endif /* Threads variety case */
3317 #else
3318   ACE_UNUSED_ARG (m);
3319   ACE_NOTSUP_RETURN (-1);
3320 #endif /* ACE_HAS_THREADS */
3323 ACE_INLINE int
3324 ACE_OS::thread_mutex_unlock (ACE_thread_mutex_t *m)
3326   ACE_OS_TRACE ("ACE_OS::thread_mutex_unlock");
3327 #if defined (ACE_HAS_THREADS)
3328 # if defined (ACE_HAS_WTHREADS)
3329   ::LeaveCriticalSection (m);
3330   return 0;
3331 # else
3332   return ACE_OS::mutex_unlock (m);
3333 # endif /* ACE_HAS_WTHREADS */
3334 #else
3335   ACE_UNUSED_ARG (m);
3336   ACE_NOTSUP_RETURN (-1);
3337 #endif /* ACE_HAS_THREADS */
3340 /*****************************************************************************/
3342 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
3344 ACE_INLINE
3346 ACE_OS_Thread_Mutex_Guard::acquire ()
3348   return owner_ = ACE_OS::thread_mutex_lock (&lock_);
3351 ACE_INLINE
3353 ACE_OS_Thread_Mutex_Guard::release ()
3355   if (owner_ == -1)
3356     return 0;
3357   else
3358     {
3359       owner_ = -1;
3360       return ACE_OS::thread_mutex_unlock (&lock_);
3361     }
3364 ACE_INLINE
3365 ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m)
3366   : lock_ (m), owner_ (-1)
3368   if (!ACE_OS_Object_Manager::starting_up ())
3369     acquire ();
3372 ACE_INLINE
3373 ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard ()
3375   release ();
3378 /*****************************************************************************/
3380 ACE_INLINE
3382 ACE_OS_Recursive_Thread_Mutex_Guard::acquire ()
3384   return owner_ = ACE_OS::recursive_mutex_lock (&lock_);
3387 ACE_INLINE
3389 ACE_OS_Recursive_Thread_Mutex_Guard::release ()
3391   if (owner_ == -1)
3392     return 0;
3393   else
3394     {
3395       owner_ = -1;
3396       return ACE_OS::recursive_mutex_unlock (&lock_);
3397     }
3400 ACE_INLINE
3401 ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard (
3402   ACE_recursive_thread_mutex_t &m)
3403    : lock_ (m),
3404      owner_ (-1)
3406   if (!ACE_OS_Object_Manager::starting_up ())
3407     acquire ();
3410 ACE_INLINE
3411 ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard ()
3413   release ();
3416 #endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
3419 /*****************************************************************************/
3421 ACE_INLINE
3422 ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id,
3423                               ACE_hthread_t thread_handle)
3424   : thread_id_ (thread_id),
3425     thread_handle_ (thread_handle)
3429 ACE_INLINE
3430 ACE_Thread_ID::ACE_Thread_ID (const ACE_Thread_ID &id)
3431   : thread_id_ (id.thread_id_),
3432     thread_handle_ (id.thread_handle_)
3436 ACE_INLINE
3437 ACE_Thread_ID&
3438 ACE_Thread_ID::operator= (const ACE_Thread_ID &id)
3440   if (this != &id)
3441     {
3442       this->thread_id_ = id.thread_id_;
3443       this->thread_handle_ = id.thread_handle_;
3444     }
3445   return *this;
3448 ACE_INLINE
3449 ACE_Thread_ID::ACE_Thread_ID ()
3450   : thread_id_ (ACE_OS::thr_self ())
3452   ACE_OS::thr_self (thread_handle_);
3455 ACE_INLINE
3456 ACE_thread_t
3457 ACE_Thread_ID::id () const
3459   return this->thread_id_;
3462 ACE_INLINE void
3463 ACE_Thread_ID::id (ACE_thread_t thread_id)
3465   this->thread_id_ = thread_id;
3468 ACE_INLINE ACE_hthread_t
3469 ACE_Thread_ID::handle () const
3471   return this->thread_handle_;
3474 ACE_INLINE void
3475 ACE_Thread_ID::handle (ACE_hthread_t thread_handle)
3477   this->thread_handle_ = thread_handle;
3480 ACE_INLINE bool
3481 ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const
3483   return
3484     ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_)
3485     && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_);
3488 ACE_INLINE bool
3489 ACE_Thread_ID::operator!= (const ACE_Thread_ID &rhs) const
3491   return !(*this == rhs);
3494 #if !defined (ACE_WIN32)
3496 ACE_INLINE
3497 ACE_event_t::ACE_event_t () :
3498   name_ (0),
3499   eventdata_ (0)
3503 #endif /* !ACE_WIN32 */
3505 ACE_END_VERSIONED_NAMESPACE_DECL