Also use Objects as part of an operation but as a result don't generate Any operation...
[ACE_TAO.git] / ACE / ace / OS_NS_Thread.inl
blob8e1e1e94204500470236ca6b28b526059af51b7e
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_PRIOCNTL)
20 #  include /**/ <sys/priocntl.h>
21 #endif /* ACE_HAS_PRIOCNTL */
23 #if defined (ACE_HAS_ALLOC_HOOKS)
24 # include "ace/Malloc_Base.h"
25 #endif /* ACE_HAS_ALLOC_HOOKS */
27 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
29 /*****************************************************************************/
31 #if defined (ACE_LACKS_COND_T) && defined (ACE_HAS_THREADS)
32 ACE_INLINE long
33 ACE_cond_t::waiters (void) const
35   return this->waiters_;
37 #endif /* ACE_LACKS_COND_T && ACE_HAS_THREADS */
39 /*****************************************************************************/
41 #if defined (ACE_HAS_TSS_EMULATION)
43 #  if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
44 ACE_INLINE
45 void **&
46 ACE_TSS_Emulation::tss_base ()
48 #    if defined (ACE_HAS_VXTHREADS)
49 #      if (!defined (_WRS_CONFIG_SMP) && !defined (INCLUDE_AMP_CPU))
50   if (taskVarGet(0, reinterpret_cast<int*>(&ace_tss_keys)) == ERROR)
51     taskVarAdd(0, reinterpret_cast<int*>(&ace_tss_keys));
52 #      endif
53   return reinterpret_cast <void **&> (ace_tss_keys);
54 #    else
55   // Uh oh.
56   ACE_NOTSUP_RETURN (0);
57 #    endif /* ACE_HAS_VXTHREADS */
59 #  endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
61 ACE_INLINE
62 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
63 ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key)
65   return tss_destructor_ [key];
68 ACE_INLINE
69 void
70 ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key,
71                                    ACE_TSS_DESTRUCTOR destructor)
73   tss_destructor_ [key] = destructor;
76 ACE_INLINE
77 void *&
78 ACE_TSS_Emulation::ts_object (const ACE_thread_key_t key)
80 #    if defined (ACE_HAS_VXTHREADS)
81     /* If someone wants tss_base make sure they get one.  This
82        gets used if someone spawns a VxWorks task directly, not
83        through ACE.  The allocated array will never be deleted! */
84     if (ace_tss_keys == 0)
85       {
86         ace_tss_keys = new void *[ACE_TSS_THREAD_KEYS_MAX];
88         // Zero the entire TSS array.  Do it manually instead of using
89         // memset, for optimum speed.  Though, memset may be faster :-)
90         void **tss_base_p = reinterpret_cast<void **> (ace_tss_keys);
91         for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
92           {
93             *tss_base_p = 0;
94           }
95       }
96 #    endif /* ACE_HAS_VXTHREADS */
98   return tss_base ()[key];
101 #endif /* ACE_HAS_TSS_EMULATION */
103 /*****************************************************************************/
105 ACE_INLINE int
106 ACE_OS::thr_equal (ACE_thread_t t1, ACE_thread_t t2)
108 #if defined (ACE_HAS_PTHREADS)
109 # if defined (pthread_equal)
110   // If it's a macro we can't say "pthread_equal"...
111   return pthread_equal (t1, t2);
112 # else
113   return pthread_equal (t1, t2);
114 # endif /* pthread_equal */
115 #else /* For both STHREADS and WTHREADS... */
116   // Hum, Do we need to treat WTHREAD differently?
117   // levine 13 oct 98 % I don't think so, ACE_thread_t is a DWORD.
118   return t1 == t2;
119 #endif /* ACE_HAS_PTHREADS */
122 ACE_INLINE int
123 ACE_OS::condattr_destroy (ACE_condattr_t &attributes)
125 #if defined (ACE_HAS_THREADS) && !defined (ACE_LACKS_CONDATTR)
126 #   if defined (ACE_HAS_PTHREADS)
127   pthread_condattr_destroy (&attributes);
128 #   else
129   attributes.type = 0;
130 #   endif /* ACE_HAS_PTHREADS */
131   return 0;
132 # else
133   ACE_UNUSED_ARG (attributes);
134   return 0;
135 # endif /* ACE_HAS_THREADS  */
138 ACE_INLINE int
139 ACE_OS::condattr_init (ACE_condattr_t &attributes, int type)
141   ACE_UNUSED_ARG (type);
142 # if defined (ACE_HAS_THREADS)
143 #   if defined (ACE_HAS_PTHREADS)
144   int result = -1;
146 #     if !defined (ACE_LACKS_CONDATTR)
147 #       if defined (ACE_PTHREAD_CONDATTR_T_INITIALIZE)
148   /* Tests show that VxWorks 6.x pthread lib does not only
149     * require zeroing of mutex/condition objects to function correctly
150     * but also of the attribute objects.
151     */
152   ACE_OS::memset (&attributes, 0, sizeof (attributes));
153 #       endif
154   if (
155       ACE_ADAPT_RETVAL (pthread_condattr_init (&attributes), result) == 0
156 #       if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)
157       && ACE_ADAPT_RETVAL (pthread_condattr_setpshared (&attributes, type),
158                            result) == 0
159 #       endif /* _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_CONDATTR_PSHARED */
160       )
161 #     else
162   if (type == USYNC_THREAD)
163 #     endif /* !ACE_LACKS_CONDATTR */
164      result = 0;
165   else
166     {
167       ACE_UNUSED_ARG (attributes);
168       result = -1;       // ACE_ADAPT_RETVAL used it for intermediate status
169     }
171   return result;
172 #   else
173   attributes.type = type;
174   return 0;
175 #   endif /* ACE_HAS_PTHREADS */
177 # else
178   ACE_UNUSED_ARG (attributes);
179   ACE_UNUSED_ARG (type);
180   ACE_NOTSUP_RETURN (-1);
181 # endif /* ACE_HAS_THREADS */
184 ACE_INLINE int
185 ACE_OS::condattr_synctype (ACE_condattr_t &attributes, int& type)
187 # if defined (ACE_HAS_THREADS)
188 #   if defined (ACE_HAS_PTHREADS)
189 #   if !defined (ACE_LACKS_CONDATTR) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)
190   int result = -1;
192   if (
193       ACE_ADAPT_RETVAL (pthread_condattr_getpshared (&attributes, &type),
194                            result) == 0
195      )
196     {
197       result = 0;
198     }
199 #   else
200   ACE_UNUSED_ARG (attributes);
201   int result = 0;
202   type = USYNC_THREAD;
203 #   endif /* !ACE_LACKS_CONDATTR && _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_CONDATTR_PSHARED */
205   return result;
206 #   else
207   type = attributes.type;
208   return 0;
209 #   endif /* ACE_HAS_PTHREADS */
211 # else
212   ACE_UNUSED_ARG (attributes);
213   ACE_UNUSED_ARG (type);
214   ACE_NOTSUP_RETURN (-1);
215 # endif /* ACE_HAS_THREADS */
218 ACE_INLINE int
219 ACE_OS::condattr_setclock (ACE_condattr_t &attributes, clockid_t clock_id)
221 #if defined (ACE_HAS_CONDATTR_SETCLOCK) && !defined (ACE_LACKS_CONDATTR_SETCLOCK) && \
222   !defined (ACE_LACKS_CONDATTR_SETCLOCK)
223   int result = -1;
224   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_condattr_setclock (&attributes, clock_id),
225                                        result),
226                      int, -1);
227   return result;
228 #else
229   ACE_UNUSED_ARG (clock_id);
230   ACE_UNUSED_ARG (attributes);
231   ACE_NOTSUP_RETURN (-1);
232 #endif
235 #if !defined (ACE_LACKS_COND_T)
236 // NOTE: The ACE_OS::cond_* functions for Unix platforms are defined
237 // here because the ACE_OS::sema_* functions below need them.
238 // However, ACE_WIN32 and VXWORKS define the ACE_OS::cond_* functions
239 // using the ACE_OS::sema_* functions.  So, they are defined in OS_NS_Tread.cpp.
241 ACE_INLINE int
242 ACE_OS::cond_broadcast (ACE_cond_t *cv)
244   ACE_OS_TRACE ("ACE_OS::cond_broadcast");
245 # if defined (ACE_HAS_THREADS)
246 #   if defined (ACE_HAS_PTHREADS)
247   int result;
248   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_broadcast (cv),
249                                        result),
250                      int, -1);
251 #   elif defined (ACE_HAS_STHREADS)
252   int result;
253   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_broadcast (cv),
254                                        result),
255                      int, -1);
256 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
257   ::WakeAllConditionVariable  (cv);
258   return 0;
259 #   endif /* ACE_HAS_STHREADS */
260 # else
261   ACE_UNUSED_ARG (cv);
262   ACE_NOTSUP_RETURN (-1);
263 # endif /* ACE_HAS_THREADS */
266 ACE_INLINE int
267 ACE_OS::cond_destroy (ACE_cond_t *cv)
269   ACE_OS_TRACE ("ACE_OS::cond_destroy");
270 # if defined (ACE_HAS_THREADS)
271 #   if defined (ACE_HAS_PTHREADS)
272   int result;
273   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_destroy (cv), result), int, -1);
274 #   elif defined (ACE_HAS_STHREADS)
275   int result;
276   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_destroy (cv), result), int, -1);
277 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
278   // Windows doesn't have a destroy
279   return 0;
280 #   endif /* ACE_HAS_STHREADS */
281 # else
282   ACE_UNUSED_ARG (cv);
283   ACE_NOTSUP_RETURN (-1);
284 # endif /* ACE_HAS_THREADS */
287 ACE_INLINE int
288 ACE_OS::cond_init (ACE_cond_t *cv,
289                    ACE_condattr_t &attributes,
290                    const char *name,
291                    void *arg)
293   // ACE_OS_TRACE ("ACE_OS::cond_init");
294   ACE_UNUSED_ARG (name);
295   ACE_UNUSED_ARG (arg);
296 # if defined (ACE_HAS_THREADS)
297 #   if defined (ACE_HAS_PTHREADS)
298   int result = -1;
300 #     if defined (ACE_PTHREAD_COND_T_INITIALIZE)
301   /* VxWorks 6.x API reference states:
302    *   If the memory for the condition variable object has been allocated
303    *   dynamically, it is a good policy to always zero out the
304    *   block of memory so as to avoid spurious EBUSY return code
305    *   when calling this routine.
306    */
307   ACE_OS::memset (cv, 0, sizeof (*cv));
308 #     endif
310   if (ACE_ADAPT_RETVAL (pthread_cond_init (cv, &attributes), result) == 0)
311      result = 0;
312   else
313      result = -1;       // ACE_ADAPT_RETVAL used it for intermediate status
315   return result;
316 #   elif defined (ACE_HAS_STHREADS)
317   int result;
318   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_init (cv,
319                                                     attributes.type,
320                                                     arg),
321                                        result),
322                      int, -1);
323 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
324     ::InitializeConditionVariable (cv);
325     return 0;
326 #   endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
327 # else
328   ACE_UNUSED_ARG (cv);
329   ACE_UNUSED_ARG (attributes);
330   ACE_UNUSED_ARG (name);
331   ACE_UNUSED_ARG (arg);
332   ACE_NOTSUP_RETURN (-1);
333 # endif /* ACE_HAS_THREADS */
336 #if defined (ACE_HAS_WCHAR)
337 ACE_INLINE int
338 ACE_OS::cond_init (ACE_cond_t *cv,
339                    ACE_condattr_t &attributes,
340                    const wchar_t *name,
341                    void *arg)
343   return ACE_OS::cond_init (cv, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg);
345 #endif /* ACE_HAS_WCHAR */
347 #if defined (ACE_HAS_WCHAR)
348 ACE_INLINE int
349 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
351   return ACE_OS::cond_init (cv, type, ACE_Wide_To_Ascii (name).char_rep (), arg);
353 #endif /* ACE_HAS_WCHAR */
355 ACE_INLINE int
356 ACE_OS::cond_signal (ACE_cond_t *cv)
358   ACE_OS_TRACE ("ACE_OS::cond_signal");
359 # if defined (ACE_HAS_THREADS)
360 #   if defined (ACE_HAS_PTHREADS)
361   int result;
362   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_signal (cv), result),
363                      int, -1);
364 #   elif defined (ACE_HAS_STHREADS)
365   int result;
366   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_signal (cv), result), int, -1);
367 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
368   ::WakeConditionVariable (cv);
369   return 0;
370 #   endif /* ACE_HAS_STHREADS */
371 # else
372   ACE_UNUSED_ARG (cv);
373   ACE_NOTSUP_RETURN (-1);
374 # endif /* ACE_HAS_THREADS */
377 ACE_INLINE int
378 ACE_OS::cond_wait (ACE_cond_t *cv,
379                    ACE_mutex_t *external_mutex)
381   ACE_OS_TRACE ("ACE_OS::cond_wait");
382 # if defined (ACE_HAS_THREADS)
383 #   if defined (ACE_HAS_PTHREADS)
384   int result;
385   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_wait (cv, external_mutex), result),
386                      int, -1);
387 #   elif defined (ACE_HAS_STHREADS)
388   int result;
389   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_wait (cv, external_mutex), result),
390                      int, -1);
391 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
392   int result;
393   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, &external_mutex->thr_mutex_, INFINITE), result),
394                      int, -1);
395 #   endif /* ACE_HAS_PTHREADS */
396 # else
397   ACE_UNUSED_ARG (cv);
398   ACE_UNUSED_ARG (external_mutex);
399   ACE_NOTSUP_RETURN (-1);
400 # endif /* ACE_HAS_THREADS */
403 ACE_INLINE int
404 ACE_OS::cond_timedwait (ACE_cond_t *cv,
405                         ACE_mutex_t *external_mutex,
406                         ACE_Time_Value *timeout)
408   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
409 # if defined (ACE_HAS_THREADS)
410   int result = 0;
411   timespec_t ts;
413   if (timeout != 0)
414     ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
416 #   if defined (ACE_HAS_PTHREADS)
418   ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
419                                 ? pthread_cond_wait (cv, external_mutex)
420                                 : pthread_cond_timedwait (cv, external_mutex,
421                                                             (ACE_TIMESPEC_PTR) &ts),
422                                 result),
423               int, -1, result);
424   // We need to adjust this to make the POSIX and Solaris return
425   // values consistent.  EAGAIN is from Pthreads DRAFT4 (HP-UX 10.20 and down)
426   if (result == -1 &&
427       (errno == ETIMEDOUT || errno == EAGAIN))
428     errno = ETIME;
430 #   elif defined (ACE_HAS_STHREADS)
431   ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
432                                 ? ::cond_wait (cv, external_mutex)
433                                 : ::cond_timedwait (cv,
434                                                     external_mutex,
435                                                     (timestruc_t*)&ts),
436                                 result),
437               int, -1, result);
438 #   elif defined (ACE_HAS_WTHREADS) && defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
439   int msec_timeout = 0;
440   if (timeout != 0)
441     {
442       ACE_Time_Value relative_time = timeout->to_relative_time ();
443       // Watchout for situations where a context switch has caused the
444       // current time to be > the timeout.
445       if (relative_time > ACE_Time_Value::zero)
446         msec_timeout = relative_time.msec ();
447     }
449   ACE_OSCALL (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, &external_mutex->thr_mutex_, msec_timeout),
450                                 result),
451               int, -1, result);
453   return result;
454 #   endif /* ACE_HAS_STHREADS */
455   if (timeout != 0)
456     timeout->set (ts); // Update the time value before returning.
458   return result;
459 # else
460   ACE_UNUSED_ARG (cv);
461   ACE_UNUSED_ARG (external_mutex);
462   ACE_UNUSED_ARG (timeout);
463   ACE_NOTSUP_RETURN (-1);
464 # endif /* ACE_HAS_THREADS */
466 #endif /* !ACE_LACKS_COND_T */
468 ACE_INLINE int
469 ACE_OS::mutex_lock (ACE_mutex_t *m,
470                     const ACE_Time_Value *timeout)
472   return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout);
475 ACE_INLINE int
476 ACE_OS::event_wait (ACE_event_t *event)
478   return ACE_OS::event_timedwait (event, 0);
481 ACE_INLINE int
482 ACE_OS::event_init (ACE_event_t *event,
483                     int manual_reset,
484                     int initial_state,
485                     int type,
486                     const char *name,
487                     void *arg,
488                     LPSECURITY_ATTRIBUTES sa)
490   ACE_condattr_t *pattr = 0;
491   return ACE_OS::event_init (event, type, pattr, manual_reset, initial_state, name, arg, sa);
494 #if defined (ACE_HAS_WCHAR)
495 ACE_INLINE int
496 ACE_OS::event_init (ACE_event_t *event,
497                     int manual_reset,
498                     int initial_state,
499                     int type,
500                     const wchar_t *name,
501                     void *arg,
502                     LPSECURITY_ATTRIBUTES sa)
504 #if defined (ACE_WIN32)
505   ACE_UNUSED_ARG (type);
506   ACE_UNUSED_ARG (arg);
507   SECURITY_ATTRIBUTES sa_buffer;
508   SECURITY_DESCRIPTOR sd_buffer;
509   *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
510       (sa, &sa_buffer, &sd_buffer),
511   manual_reset,
512   initial_state,
513   name);
514   if (*event == 0)
515     ACE_FAIL_RETURN (-1);
517   // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
518   ACE_OS::set_errno_to_last_error ();
519   return 0;
520 #else  /* ACE_WIN32 */
521   return ACE_OS::event_init (event,
522                              manual_reset,
523                              initial_state,
524                              type,
525                              ACE_Wide_To_Ascii (name).char_rep (),
526                              arg,
527                              sa);
528 #endif /* ACE_WIN32 */
531 ACE_INLINE int
532 ACE_OS::event_init (ACE_event_t *event,
533                     int type,
534                     ACE_condattr_t *attributes,
535                     int manual_reset,
536                     int initial_state,
537                     const wchar_t *name,
538                     void *arg,
539                     LPSECURITY_ATTRIBUTES sa)
541 #if defined (ACE_WIN32)
542   ACE_UNUSED_ARG (type);
543   ACE_UNUSED_ARG (attributes);
544   ACE_UNUSED_ARG (arg);
545   SECURITY_ATTRIBUTES sa_buffer;
546   SECURITY_DESCRIPTOR sd_buffer;
547   *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
548       (sa, &sa_buffer, &sd_buffer),
549   manual_reset,
550   initial_state,
551   name);
552   if (*event == 0)
553     ACE_FAIL_RETURN (-1);
555   // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
556   ACE_OS::set_errno_to_last_error ();
557   return 0;
558 #else  /* ACE_WIN32 */
559   return ACE_OS::event_init (event,
560                              type,
561                              attributes,
562                              manual_reset,
563                              initial_state,
564                              ACE_Wide_To_Ascii (name).char_rep (),
565                              arg,
566                              sa);
567 #endif /* ACE_WIN32 */
569 #endif /* ACE_HAS_WCHAR */
571 ACE_INLINE long
572 ACE_OS::priority_control (ACE_idtype_t idtype, ACE_id_t identifier, int cmd, void *arg)
574   ACE_OS_TRACE ("ACE_OS::priority_control");
575 #if defined (ACE_HAS_PRIOCNTL)
576   ACE_OSCALL_RETURN (priocntl (idtype, identifier, cmd, static_cast<caddr_t> (arg)),
577                      long, -1);
578 #else  /* ! ACE_HAS_PRIOCNTL*/
579   ACE_UNUSED_ARG (idtype);
580   ACE_UNUSED_ARG (identifier);
581   ACE_UNUSED_ARG (cmd);
582   ACE_UNUSED_ARG (arg);
583   ACE_NOTSUP_RETURN (-1);
584 #endif /* ! ACE_HAS_PRIOCNTL*/
587 // This method is used to prepare the recursive mutex for releasing
588 // when waiting on a condition variable. If the platform doesn't have
589 // native recursive mutex and condition variable support, then ACE needs
590 // to save the recursion state around the wait and also ensure that the
591 // wait and lock release are atomic. recursive_mutex_cond_relock()
592 // is the inverse of this method.
593 ACE_INLINE int
594 ACE_OS::recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m,
595                                      ACE_recursive_mutex_state &state)
597 #if defined (ACE_HAS_THREADS)
598   ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_unlock");
599 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
600   // Windows need special handling since it has recursive mutexes, but
601   // does not integrate them into a condition variable.
602 #    if defined (ACE_WIN32)
603   // For Windows, the OS takes care of the mutex and its recursion. We just
604   // need to release the lock one fewer times than this thread has acquired
605   // it. Remember how many times, and reacquire it that many more times when
606   // the condition is signaled.
608   // We're using undocumented fields in the CRITICAL_SECTION structure
609   // and they've been known to change across Windows variants and versions./
610   // So be careful if you need to change these - there may be other
611   // Windows variants that depend on existing values and limits.
613   state.relock_count_ = 0;
614   while (
615 #      if !defined (ACE_HAS_WINCE)
616          m->LockCount > 0 && m->RecursionCount > 1
617 #      else
618          // WinCE doesn't have RecursionCount and the LockCount semantic
619          // Mobile 5 has it 1-indexed.
620          m->LockCount > 1
621 #      endif /* ACE_HAS_WINCE */
622          )
623     {
624       // This may fail if the current thread doesn't own the mutex. If it
625       // does fail, it'll be on the first try, so don't worry about resetting
626       // the state.
627       if (ACE_OS::recursive_mutex_unlock (m) == -1)
628         return -1;
629       ++state.relock_count_;
630     }
631 #    else /* not ACE_WIN32 */
632     // prevent warnings for unused variables
633     ACE_UNUSED_ARG (state);
634     ACE_UNUSED_ARG (m);
635 #    endif /* ACE_WIN32 */
636   return 0;
637 #  else /* ACE_HAS_RECURSIVE_MUTEXES */
638   // For platforms without recursive mutexes, we obtain the nesting mutex
639   // to gain control over the mutex internals. Then set the internals to say
640   // the mutex is available. If there are waiters, signal the condition
641   // to notify them (this is mostly like the recursive_mutex_unlock() method).
642   // Then, return with the nesting mutex still held. The condition wait
643   // will release it atomically, allowing mutex waiters to continue.
644   // Note that this arrangement relies on the fact that on return from
645   // the condition wait, this thread will again own the nesting mutex
646   // and can either set the mutex internals directly or get in line for
647   // the mutex... this part is handled in recursive_mutex_cond_relock().
648   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
649     return -1;
651 #    if !defined (ACE_NDEBUG)
652   if (m->nesting_level_ == 0
653       || ACE_OS::thr_equal (ACE_OS::thr_self (), m->owner_id_) == 0)
654     {
655       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
656       errno = EINVAL;
657       return -1;
658     }
659 #    endif /* ACE_NDEBUG */
661   // To make error recovery a bit easier, signal the condition now. Any
662   // waiter won't regain control until the mutex is released, which won't
663   // be until the caller returns and does the wait on the condition.
664   if (ACE_OS::cond_signal (&m->lock_available_) == -1)
665     {
666       // Save/restore errno.
667       ACE_Errno_Guard error (errno);
668       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
669       return -1;
670     }
672   // Ok, the nesting_mutex_ lock is still held, the condition has been
673   // signaled... reset the nesting info and return _WITH_ the lock
674   // held. The lock will be released when the condition waits, in the
675   // caller.
676   state.nesting_level_ = m->nesting_level_;
677   state.owner_id_ = m->owner_id_;
678   m->nesting_level_ = 0;
679   m->owner_id_ = ACE_OS::NULL_thread;
680   return 0;
681 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
682 #else
683   ACE_UNUSED_ARG (m);
684   ACE_UNUSED_ARG (state);
685   ACE_NOTSUP_RETURN (-1);
686 #endif /* ACE_HAS_THREADS */
690 // This method is called after waiting on a condition variable when a
691 // recursive mutex must be reacquired. If the platform doesn't natively
692 // integrate recursive mutexes and condition variables, it's taken care
693 // of here (inverse of ACE_OS::recursive_mutex_cond_unlock).
694 ACE_INLINE void
695 ACE_OS::recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m,
696                                      ACE_recursive_mutex_state &state)
698 #if defined (ACE_HAS_THREADS)
699   ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_relock");
700 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
701   // Windows need special handling since it has recursive mutexes, but
702   // does not integrate them into a condition variable.
703   // On entry, the OS has already reacquired the lock for us. Just
704   // reacquire it the proper number of times so the recursion is the same as
705   // before waiting on the condition.
706 #    if defined (ACE_WIN32)
707   while (state.relock_count_ > 0)
708     {
709       ACE_OS::recursive_mutex_lock (m);
710       --state.relock_count_;
711     }
712   return;
713 #    else /* not ACE_WIN32 */
714     // prevent warnings for unused variables
715     ACE_UNUSED_ARG (state);
716     ACE_UNUSED_ARG (m);
718 #    endif /* ACE_WIN32 */
719 #  else
720   // Without recursive mutex support, it's somewhat trickier. On entry,
721   // the current thread holds the nesting_mutex_, but another thread may
722   // still be holding the ACE_recursive_mutex_t. If so, mimic the code
723   // in ACE_OS::recursive_mutex_lock that waits to acquire the mutex.
724   // After acquiring it, restore the nesting counts and release the
725   // nesting mutex. This will restore the conditions to what they were
726   // before calling ACE_OS::recursive_mutex_cond_unlock().
727   while (m->nesting_level_ > 0)
728     ACE_OS::cond_wait (&m->lock_available_, &m->nesting_mutex_);
730   // At this point, we still have nesting_mutex_ and the mutex is free.
731   m->nesting_level_ = state.nesting_level_;
732   m->owner_id_ = state.owner_id_;
733   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
734   return;
735 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
736 #else
737   ACE_UNUSED_ARG (m);
738   ACE_UNUSED_ARG (state);
739   return;
740 #endif /* ACE_HAS_THREADS */
743 ACE_INLINE int
744 ACE_OS::recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m)
746 #if defined (ACE_HAS_THREADS)
747 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
748   return ACE_OS::thread_mutex_destroy (m);
749 #else
750   if (ACE_OS::cond_destroy (&m->lock_available_) == -1
751       || ACE_OS::thread_mutex_destroy (&m->nesting_mutex_) == -1)
752     return -1;
753   return 0;
754 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
755 #else
756   ACE_UNUSED_ARG (m);
757   ACE_NOTSUP_RETURN (-1);
758 #endif /* ACE_HAS_THREADS */
761 ACE_INLINE int
762 ACE_OS::recursive_mutex_init (ACE_recursive_thread_mutex_t *m,
763                               const ACE_TCHAR *name,
764                               ACE_mutexattr_t *arg,
765                               LPSECURITY_ATTRIBUTES sa)
767   ACE_UNUSED_ARG (sa);
768 #if defined (ACE_HAS_THREADS)
769 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
770 #    if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
771   return ACE_OS::thread_mutex_init (m, PTHREAD_MUTEX_RECURSIVE, name, arg);
772 #    else
773   return ACE_OS::thread_mutex_init (m, 0, name, arg);
774 #    endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
775 #  else
776   if (ACE_OS::thread_mutex_init (&m->nesting_mutex_, 0, name, arg) == -1)
777     return -1;
778   else if (ACE_OS::cond_init (&m->lock_available_,
779                               (short) USYNC_THREAD,
780                               name,
781                               0) == -1)
782     return -1;
783   else
784     {
785       m->nesting_level_ = 0;
786       m->owner_id_ = ACE_OS::NULL_thread;
787       return 0;
788     }
789 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
790 #else
791   ACE_UNUSED_ARG (m);
792   ACE_UNUSED_ARG (name);
793   ACE_UNUSED_ARG (arg);
794   ACE_NOTSUP_RETURN (-1);
795 #endif /* ACE_HAS_THREADS */
798 ACE_INLINE int
799 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m)
801 #if defined (ACE_HAS_THREADS)
802 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
803   return ACE_OS::thread_mutex_lock (m);
804 #else
805   ACE_thread_t const t_id = ACE_OS::thr_self ();
806   int result = 0;
808   // Acquire the guard.
809   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -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         ACE_OS::cond_wait (&m->lock_available_,
825                             &m->nesting_mutex_);
827           // At this point the nesting_mutex_ is held...
828       m->owner_id_ = t_id;
829     }
831     // At this point, we can safely increment the nesting_level_ no
832     // matter how we got here!
833     ++m->nesting_level_;
834   }
836   {
837     // Save/restore errno.
838     ACE_Errno_Guard error (errno);
839     ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
840   }
841   return result;
842 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
843 #else
844   ACE_UNUSED_ARG (m);
845   ACE_NOTSUP_RETURN (-1);
846 #endif /* ACE_HAS_THREADS */
849 ACE_INLINE int
850 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
851                               const ACE_Time_Value &timeout)
853 #if defined (ACE_HAS_THREADS)
854 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
855   return ACE_OS::thread_mutex_lock (m, timeout);
856 #else
857   ACE_thread_t t_id = ACE_OS::thr_self ();
858   int result = 0;
860   // Try to acquire the guard.
861   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_, timeout) == -1)
862     result = -1;
863   else
864     {
865       // If there's no contention, just grab the lock immediately
866       // (since this is the common case we'll optimize for it).
867       if (m->nesting_level_ == 0)
868         m->owner_id_ = t_id;
869       // If we already own the lock, then increment the nesting level
870       // and return.
871       else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
872         {
873           // Wait until the nesting level has dropped to zero, at
874           // which point we can acquire the lock.
875           while (m->nesting_level_ > 0)
876             {
877               result = ACE_OS::cond_timedwait (&m->lock_available_,
878                                                &m->nesting_mutex_,
879                                                const_cast <ACE_Time_Value *> (&timeout));
881               // The mutex is reacquired even in the case of a timeout
882               // release the mutex to prevent a deadlock
883               if (result == -1)
884                 {
885                   // Save/restore errno.
886                   ACE_Errno_Guard error (errno);
887                   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
889                   return result;
890                 }
891             }
893           // At this point the nesting_mutex_ is held...
894           m->owner_id_ = t_id;
895         }
897       // At this point, we can safely increment the nesting_level_ no
898       // matter how we got here!
899       m->nesting_level_++;
901       // Save/restore errno.
902       ACE_Errno_Guard error (errno);
903       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
904     }
905   return result;
906 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
907 #else
908   ACE_UNUSED_ARG (m);
909   ACE_UNUSED_ARG (timeout);
910   ACE_NOTSUP_RETURN (-1);
911 #endif /* ACE_HAS_THREADS */
914 ACE_INLINE int
915 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
916                               const ACE_Time_Value *timeout)
918   return timeout == 0
919     ? ACE_OS::recursive_mutex_lock (m)
920     : ACE_OS::recursive_mutex_lock (m, *timeout);
923 ACE_INLINE int
924 ACE_OS::recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m)
926 #if defined (ACE_HAS_THREADS)
927 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
928   return ACE_OS::thread_mutex_trylock (m);
929 #else
930   ACE_thread_t t_id = ACE_OS::thr_self ();
931   int result = 0;
933   // Acquire the guard.
934   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
935     result = -1;
936   else
937   {
938       // If there's no contention, just grab the lock immediately.
939     if (m->nesting_level_ == 0)
940     {
941       m->owner_id_ = t_id;
942       m->nesting_level_ = 1;
943     }
944       // If we already own the lock, then increment the nesting level
945       // and proceed.
946     else if (ACE_OS::thr_equal (t_id, m->owner_id_))
947       m->nesting_level_++;
948     else
949     {
950       errno = EBUSY;
951       result = -1;
952     }
953   }
955   {
956     // Save/restore errno.
957     ACE_Errno_Guard error (errno);
958     ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
959   }
960   return result;
961 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
962 #else
963   ACE_UNUSED_ARG (m);
964   ACE_NOTSUP_RETURN (-1);
965 #endif /* ACE_HAS_THREADS */
968 ACE_INLINE int
969 ACE_OS::recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m)
971 #if defined (ACE_HAS_THREADS)
972 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
973   return ACE_OS::thread_mutex_unlock (m);
974 #  else
975   ACE_OS_TRACE ("ACE_OS::recursive_mutex_unlock");
976 #    if !defined (ACE_NDEBUG)
977   ACE_thread_t t_id = ACE_OS::thr_self ();
978 #    endif /* ACE_NDEBUG */
979   int result = 0;
981   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
982     result = -1;
983   else
984   {
985 #    if !defined (ACE_NDEBUG)
986       if (m->nesting_level_ == 0
987           || ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
989   errno = EINVAL;
990   result = -1;
992       else
993 #    endif /* ACE_NDEBUG */
995   m->nesting_level_--;
996   if (m->nesting_level_ == 0)
997   {
998               // This may not be strictly necessary, but it does put
999               // the mutex into a known state...
1000     m->owner_id_ = ACE_OS::NULL_thread;
1002               // Inform a waiter that the lock is free.
1003     if (ACE_OS::cond_signal (&m->lock_available_) == -1)
1004       result = -1;
1005   }
1007   }
1010     // Save/restore errno.
1011   ACE_Errno_Guard error (errno);
1012   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
1014   return result;
1015 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
1016 #else
1017   ACE_UNUSED_ARG (m);
1018   ACE_NOTSUP_RETURN (-1);
1019 #endif /* ACE_HAS_THREADS */
1022 ACE_INLINE int
1023 ACE_OS::rw_rdlock (ACE_rwlock_t *rw)
1025   ACE_OS_TRACE ("ACE_OS::rw_rdlock");
1026 #if defined (ACE_HAS_THREADS)
1027 # if !defined (ACE_LACKS_RWLOCK_T)
1028 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1029   int result;
1030   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_rdlock (rw),
1031                                        result),
1032                      int, -1);
1033 #  else /* Solaris */
1034   int result;
1035   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_rdlock (rw), result), int, -1);
1036 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1037 # else /* NT, POSIX, and VxWorks don't support this natively. */
1038 #   if defined (ACE_HAS_PTHREADS)
1039   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
1040 #   endif /* ACE_HAS_PTHREADS */
1041   int result = 0;
1042   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1043     result = -1; // -1 means didn't get the mutex.
1044   else
1045     {
1046       // Give preference to writers who are waiting.
1047       while (rw->ref_count_ < 0 || rw->num_waiting_writers_ > 0)
1048         {
1049           rw->num_waiting_readers_++;
1050           if (ACE_OS::cond_wait (&rw->waiting_readers_, &rw->lock_) == -1)
1051             {
1052               result = -2; // -2 means that we need to release the mutex.
1053               break;
1054             }
1055           rw->num_waiting_readers_--;
1056         }
1057     }
1058   if (result == 0)
1059     rw->ref_count_++;
1060   if (result != -1)
1061     ACE_OS::mutex_unlock (&rw->lock_);
1062 #   if defined (ACE_HAS_PTHREADS)
1063   ACE_PTHREAD_CLEANUP_POP (0);
1064 #   endif /* defined (ACE_HAS_PTHREADS) */
1065   return 0;
1066 # endif /* ! ACE_LACKS_RWLOCK_T */
1067 #else
1068   ACE_UNUSED_ARG (rw);
1069   ACE_NOTSUP_RETURN (-1);
1070 #endif /* ACE_HAS_THREADS */
1073 ACE_INLINE int
1074 ACE_OS::rw_tryrdlock (ACE_rwlock_t *rw)
1076   ACE_OS_TRACE ("ACE_OS::rw_tryrdlock");
1077 #if defined (ACE_HAS_THREADS)
1078 # if !defined (ACE_LACKS_RWLOCK_T)
1079 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1080   int result;
1081   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_tryrdlock (rw),
1082                                        result),
1083                      int, -1);
1084 #  else /* Solaris */
1085   int result;
1086   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_tryrdlock (rw), result), int, -1);
1087 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1088 # else /* NT, POSIX, and VxWorks don't support this natively. */
1089   int result = -1;
1091   if (ACE_OS::mutex_lock (&rw->lock_) != -1)
1092     {
1093       ACE_Errno_Guard error (errno);
1095       if (rw->ref_count_ == -1 || rw->num_waiting_writers_ > 0)
1096         {
1097           error = EBUSY;
1098           result = -1;
1099         }
1100       else
1101         {
1102           rw->ref_count_++;
1103           result = 0;
1104         }
1106       ACE_OS::mutex_unlock (&rw->lock_);
1107     }
1108   return result;
1109 # endif /* ! ACE_LACKS_RWLOCK_T */
1110 #else
1111   ACE_UNUSED_ARG (rw);
1112   ACE_NOTSUP_RETURN (-1);
1113 #endif /* ACE_HAS_THREADS */
1116 ACE_INLINE int
1117 ACE_OS::rw_trywrlock (ACE_rwlock_t *rw)
1119   ACE_OS_TRACE ("ACE_OS::rw_trywrlock");
1120 #if defined (ACE_HAS_THREADS)
1121 # if !defined (ACE_LACKS_RWLOCK_T)
1122 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1123   int result;
1124   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
1125                                        result),
1126                      int, -1);
1127 #  else /* Solaris */
1128   int result;
1129   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_trywrlock (rw), result), int, -1);
1130 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1131 # else /* NT, POSIX, and VxWorks don't support this natively. */
1132   int result = -1;
1134   if (ACE_OS::mutex_lock (&rw->lock_) != -1)
1135     {
1136       ACE_Errno_Guard error (errno);
1138       if (rw->ref_count_ != 0)
1139         {
1140           error = EBUSY;
1141           result = -1;
1142         }
1143       else
1144         {
1145           rw->ref_count_ = -1;
1146           result = 0;
1147         }
1149       ACE_OS::mutex_unlock (&rw->lock_);
1150     }
1151   return result;
1152 # endif /* ! ACE_LACKS_RWLOCK_T */
1153 #else
1154   ACE_UNUSED_ARG (rw);
1155   ACE_NOTSUP_RETURN (-1);
1156 #endif /* ACE_HAS_THREADS */
1159 // Note that the caller of this method *must* already possess this
1160 // lock as a read lock.
1161 // return {-1 and no errno set means: error,
1162 //         -1 and errno==EBUSY set means: could not upgrade,
1163 //         0 means: upgraded successfully}
1165 ACE_INLINE int
1166 ACE_OS::rw_trywrlock_upgrade (ACE_rwlock_t *rw)
1168   ACE_OS_TRACE ("ACE_OS::rw_trywrlock_upgrade");
1169 #if defined (ACE_HAS_THREADS)
1170 # if defined (ACE_HAS_PTHREADS_UNIX98_EXT) && !defined (ACE_LACKS_RWLOCK_T)
1171   int result;
1172   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
1173                                        result),
1174                      int, -1);
1175 # elif !defined (ACE_LACKS_RWLOCK_T)
1176   // Some native rwlocks, such as those on Solaris, don't
1177   // support the upgrade feature . . .
1178   ACE_UNUSED_ARG (rw);
1179   ACE_NOTSUP_RETURN (-1);
1180 # else /* NT, POSIX, and VxWorks don't support this natively. */
1181   // The ACE rwlock emulation does support upgrade . . .
1182   int result = 0;
1184 #   if defined (ACE_HAS_PTHREADS)
1185   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
1186 #   endif /* defined (ACE_HAS_PTHREADS) */
1188   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1189     return -1;
1190     // -1 means didn't get the mutex, error
1191   else if (rw->important_writer_)
1192     // an other reader upgrades already
1193     {
1194       result = -1;
1195       errno = EBUSY;
1196     }
1197   else
1198     {
1199       while (rw->ref_count_ > 1) // wait until only I am left
1200         {
1201           rw->num_waiting_writers_++; // prohibit any more readers
1202           rw->important_writer_ = true;
1204           if (ACE_OS::cond_wait (&rw->waiting_important_writer_, &rw->lock_) == -1)
1205             {
1206               result = -1;
1207               // we know that we have the lock again, we have this guarantee,
1208               // but something went wrong
1209             }
1210           rw->important_writer_ = false;
1211           rw->num_waiting_writers_--;
1212         }
1213       if (result == 0)
1214         {
1215           // nothing bad happend
1216           rw->ref_count_ = -1;
1217           // now I am a writer
1218           // everything is O.K.
1219         }
1220     }
1222   ACE_OS::mutex_unlock (&rw->lock_);
1224 #   if defined (ACE_HAS_PTHREADS)
1225   ACE_PTHREAD_CLEANUP_POP (0);
1226 #   endif /* defined (ACE_HAS_PTHREADS) */
1228   return result;
1230 # endif /* ! ACE_LACKS_RWLOCK_T */
1231 #else
1232   ACE_UNUSED_ARG (rw);
1233   ACE_NOTSUP_RETURN (-1);
1234 #endif /* ACE_HAS_THREADS */
1237 ACE_INLINE int
1238 ACE_OS::rw_unlock (ACE_rwlock_t *rw)
1240   ACE_OS_TRACE ("ACE_OS::rw_unlock");
1241 #if defined (ACE_HAS_THREADS)
1242 # if !defined (ACE_LACKS_RWLOCK_T)
1243 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1244   int result;
1245   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_unlock (rw),
1246                                        result),
1247                      int, -1);
1248 #  else /* Solaris */
1249   int result;
1250   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_unlock (rw), result), int, -1);
1251 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1252 # else /* NT, POSIX, and VxWorks don't support this natively. */
1253   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1254     return -1;
1256   if (rw->ref_count_ > 0) // Releasing a reader.
1257     rw->ref_count_--;
1258   else if (rw->ref_count_ == -1) // Releasing a writer.
1259     rw->ref_count_ = 0;
1260   else
1261     {
1262       (void) ACE_OS::mutex_unlock (&rw->lock_);
1263       return -1; // @@ ACE_ASSERT (!"count should not be 0!\n");
1264     }
1266   int result = 0;
1267   ACE_Errno_Guard error (errno);
1269   if (rw->important_writer_ && rw->ref_count_ == 1)
1270     // only the reader requesting to upgrade its lock is left over.
1271     {
1272       result = ACE_OS::cond_signal (&rw->waiting_important_writer_);
1273       error = errno;
1274     }
1275   else if (rw->num_waiting_writers_ > 0 && rw->ref_count_ == 0)
1276     // give preference to writers over readers...
1277     {
1278       result = ACE_OS::cond_signal (&rw->waiting_writers_);
1279       error =  errno;
1280     }
1281   else if (rw->num_waiting_readers_ > 0 && rw->num_waiting_writers_ == 0)
1282     {
1283       result = ACE_OS::cond_broadcast (&rw->waiting_readers_);
1284       error = errno;
1285     }
1287   (void) ACE_OS::mutex_unlock (&rw->lock_);
1288   return result;
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::rw_wrlock (ACE_rwlock_t *rw)
1299   ACE_OS_TRACE ("ACE_OS::rw_wrlock");
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_wrlock (rw),
1305                                        result),
1306                      int, -1);
1307 #  else /* Solaris */
1308   int result;
1309   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_wrlock (rw), result), int, -1);
1310 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1311 # else /* NT, POSIX, and VxWorks don't support this natively. */
1312 #   if defined (ACE_HAS_PTHREADS)
1313   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
1314 #   endif /* defined (ACE_HAS_PTHREADS) */
1315   int result = 0;
1317   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
1318     result = -1; // -1 means didn't get the mutex.
1319   else
1320     {
1321       while (rw->ref_count_ != 0)
1322         {
1323           rw->num_waiting_writers_++;
1325           if (ACE_OS::cond_wait (&rw->waiting_writers_, &rw->lock_) == -1)
1326             {
1327               result = -2; // -2 means we need to release the mutex.
1328               break;
1329             }
1331           rw->num_waiting_writers_--;
1332         }
1333     }
1334   if (result == 0)
1335     rw->ref_count_ = -1;
1336   if (result != -1)
1337     ACE_OS::mutex_unlock (&rw->lock_);
1338 #   if defined (ACE_HAS_PTHREADS)
1339   ACE_PTHREAD_CLEANUP_POP (0);
1340 #   endif /* defined (ACE_HAS_PTHREADS) */
1341   return 0;
1342 # endif /* ! ACE_LACKS_RWLOCK_T */
1343 #else
1344   ACE_UNUSED_ARG (rw);
1345   ACE_NOTSUP_RETURN (-1);
1346 #endif /* ACE_HAS_THREADS */
1349 ACE_INLINE int
1350 ACE_OS::rwlock_destroy (ACE_rwlock_t *rw)
1352   ACE_OS_TRACE ("ACE_OS::rwlock_destroy");
1353 #if defined (ACE_HAS_THREADS)
1354 # if !defined (ACE_LACKS_RWLOCK_T)
1355 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1356   int result;
1357   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_destroy (rw),
1358                                        result),
1359                      int, -1);
1360 #  else /* Solaris */
1361   int result;
1362   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_destroy (rw), result), int, -1);
1363 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1364 # else /* NT, POSIX, and VxWorks don't support this natively. */
1365   ACE_OS::mutex_destroy (&rw->lock_);
1366   ACE_OS::cond_destroy (&rw->waiting_readers_);
1367   ACE_OS::cond_destroy (&rw->waiting_important_writer_);
1368   return ACE_OS::cond_destroy (&rw->waiting_writers_);
1369 # endif /* ACE_HAS_STHREADS && !defined (ACE_LACKS_RWLOCK_T) */
1370 #else
1371   ACE_UNUSED_ARG (rw);
1372   ACE_NOTSUP_RETURN (-1);
1373 #endif /* ACE_HAS_THREADS */
1376 #if defined (ACE_HAS_THREADS) && !defined (ACE_LACKS_RWLOCK_T)
1377 ACE_INLINE int
1378 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
1379                      int type,
1380                      const ACE_TCHAR *name,
1381                      void *arg)
1383   // ACE_OS_TRACE ("ACE_OS::rwlock_init");
1384 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
1385   ACE_UNUSED_ARG (name);
1386   ACE_UNUSED_ARG (arg);
1388   int status;
1389   pthread_rwlockattr_t attr;
1390   pthread_rwlockattr_init (&attr);
1391 #    if !defined (ACE_LACKS_RWLOCKATTR_PSHARED)
1392   pthread_rwlockattr_setpshared (&attr, (type == USYNC_THREAD ?
1393                                          PTHREAD_PROCESS_PRIVATE :
1394                                          PTHREAD_PROCESS_SHARED));
1395 #    else
1396   ACE_UNUSED_ARG (type);
1397 #    endif /* !ACE_LACKS_RWLOCKATTR_PSHARED */
1398   status = ACE_ADAPT_RETVAL (pthread_rwlock_init (rw, &attr), status);
1399   pthread_rwlockattr_destroy (&attr);
1401   return status;
1403 #  else
1404   type = type;
1405   name = name;
1406   int result;
1407   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_init (rw, type, arg), result), int, -1);
1408 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
1410 #endif /* ACE_HAS_THREADS && !defined (ACE_LACKS_RWLOCK_T) */
1412 ACE_INLINE int
1413 ACE_OS::sema_destroy (ACE_sema_t *s)
1415   ACE_OS_TRACE ("ACE_OS::sema_destroy");
1416 #if defined (ACE_HAS_POSIX_SEM)
1417   int result = 0;
1418 # if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
1419   ACE_OS::mutex_destroy (&s->lock_);
1420   ACE_OS::cond_destroy (&s->count_nonzero_);
1421 # endif /* !ACE_HAS_POSIX_SEM_TIMEOUT && !ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
1422 # if defined (ACE_LACKS_NAMED_POSIX_SEM)
1423   if (s->name_)
1424     {
1425       // Only destroy the semaphore if we're the ones who
1426       // initialized it.
1427 #  if !defined (ACE_LACKS_SEM_DESTROY)
1428       ACE_OSCALL (::sem_destroy (s->sema_),int, -1, result);
1429 #  endif /* ACE_LACKS_SEM_DESTROY */
1430       ACE_OS::shm_unlink (s->name_);
1431       delete s->name_;
1432       return result;
1433     }
1434 # else
1435   if (s->name_)
1436     {
1437       if (!s->avoid_unlink_)
1438         ACE_OS::sema_unlink (s->name_);
1439 #if defined (ACE_HAS_ALLOC_HOOKS)
1440       ACE_Allocator::instance()->free ((void *) s->name_);
1441 #else
1442       ACE_OS::free ((void *) s->name_);
1443 #endif /* ACE_HAS_ALLOC_HOOKS */
1444       ACE_OSCALL_RETURN (::sem_close (s->sema_), int, -1);
1445     }
1446 # endif /*  ACE_LACKS_NAMED_POSIX_SEM */
1447   else
1448     {
1449 # if !defined (ACE_LACKS_UNNAMED_SEMAPHORE) && !defined (ACE_LACKS_SEM_DESTROY)
1450       ACE_OSCALL (::sem_destroy (s->sema_), int, -1, result);
1451 # endif /* !ACE_LACKS_UNNAMED_SEMAPHORE  && !ACE_LACKS_SEM_DESTROY */
1452 # if defined (ACE_LACKS_NAMED_POSIX_SEM)
1453       if (s->new_sema_)
1454 # endif /* ACE_LACKS_NAMED_POSIX_SEM */
1455 #if defined (ACE_HAS_ALLOC_HOOKS)
1456         ACE_Allocator::instance()->free(s->sema_);
1457 #else
1458         delete s->sema_;
1459 #endif /* ACE_HAS_ALLOC_HOOKS */
1460       s->sema_ = 0;
1461       return result;
1462     }
1463 #elif defined (ACE_USES_FIFO_SEM)
1464   int r0 = 0;
1465   if (s->name_)
1466     {
1467       r0 = ACE_OS::unlink (s->name_);
1468 #if defined (ACE_HAS_ALLOC_HOOKS)
1469       ACE_Allocator::instance()->free ((void *) s->name_);
1470 #else
1471       ACE_OS::free ((void *) s->name_);
1472 #endif /* ACE_HAS_ALLOC_HOOKS */
1473       s->name_ = 0;
1474     }
1475   int r1 = ACE_OS::close (s->fd_[0]);      /* ignore error */
1476   int r2 = ACE_OS::close (s->fd_[1]);      /* ignore error */
1477   return r0 != 0 || r1 != 0 || r2 != 0 ? -1 : 0;
1478 #elif defined (ACE_HAS_THREADS)
1479 # if defined (ACE_HAS_STHREADS)
1480   int result;
1481   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_destroy (s), result), int, -1);
1482 # elif defined (ACE_HAS_PTHREADS)
1483   int r1 = ACE_OS::mutex_destroy (&s->lock_);
1484   int r2 = ACE_OS::cond_destroy (&s->count_nonzero_);
1485   return r1 != 0 || r2 != 0 ? -1 : 0;
1486 # elif defined (ACE_HAS_WTHREADS)
1487 #  if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1488   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*s), ace_result_), int, -1);
1489 #  else /* ACE_USES_WINCE_SEMA_SIMULATION */
1490   // Free up underlying objects of the simulated semaphore.
1491   int const r1 = ACE_OS::thread_mutex_destroy (&s->lock_);
1492   int const r2 = ACE_OS::event_destroy (&s->count_nonzero_);
1493   return r1 != 0 || r2 != 0 ? -1 : 0;
1494 #  endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1495 # elif defined (ACE_VXWORKS)
1496   int result;
1497   ACE_OSCALL (::semDelete (s->sema_), int, -1, result);
1498   s->sema_ = 0;
1499   return result;
1500 # endif /* ACE_HAS_STHREADS */
1501 #else
1502   ACE_UNUSED_ARG (s);
1503   ACE_NOTSUP_RETURN (-1);
1504 #endif /* ACE_HAS_POSIX_SEM */
1507 // NOTE: The previous four function definitions must appear before
1508 // ACE_OS::sema_init ().
1510 ACE_INLINE int
1511 ACE_OS::sema_init (ACE_sema_t *s,
1512                    u_int count,
1513                    int type,
1514                    const char *name,
1515                    void *arg,
1516                    int max,
1517                    LPSECURITY_ATTRIBUTES sa)
1519   ACE_condattr_t *pattr = 0;
1520   return ACE_OS::sema_init (s, count, type, pattr, name, arg, max, sa);
1523 ACE_INLINE int
1524 ACE_OS::sema_init (ACE_sema_t *s,
1525                    u_int count,
1526                    int type,
1527                    ACE_condattr_t *attributes,
1528                    const char *name,
1529                    void *arg,
1530                    int max,
1531                    LPSECURITY_ATTRIBUTES sa)
1533   ACE_OS_TRACE ("ACE_OS::sema_init");
1534 #if defined (ACE_HAS_POSIX_SEM)
1535   ACE_UNUSED_ARG (max);
1536   ACE_UNUSED_ARG (sa);
1538   s->name_ = 0;
1539   s->avoid_unlink_ = false;
1540 #  if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
1541   ACE_UNUSED_ARG (arg);
1542   ACE_UNUSED_ARG (attributes);
1543 #  else
1544   int result = -1;
1546   if (ACE_OS::mutex_init (&s->lock_, type, name,
1547                           (ACE_mutexattr_t *) arg) == 0
1548       && (attributes == 0 ?
1549           ACE_OS::cond_init (&s->count_nonzero_, (short)type, name, arg) :
1550             ACE_OS::cond_init (&s->count_nonzero_, *attributes, name, arg)) == 0
1551       && ACE_OS::mutex_lock (&s->lock_) == 0)
1552     {
1553       if (ACE_OS::mutex_unlock (&s->lock_) == 0)
1554         result = 0;
1555     }
1557   if (result == -1)
1558     {
1559       ACE_OS::mutex_destroy (&s->lock_);
1560       ACE_OS::cond_destroy (&s->count_nonzero_);
1561       return result;
1562     }
1563 #  endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
1565 #  if defined (ACE_LACKS_NAMED_POSIX_SEM)
1566   s->new_sema_ = false;
1567   if (type == USYNC_PROCESS)
1568     {
1569       // Let's see if it already exists.
1570       ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
1571                                         O_RDWR | O_CREAT | O_EXCL,
1572                                         ACE_DEFAULT_FILE_PERMS);
1573       if (fd == ACE_INVALID_HANDLE)
1574         {
1575           if (errno == EEXIST)
1576             fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
1577                                    O_RDWR | O_CREAT,
1578                                    ACE_DEFAULT_FILE_PERMS);
1579           else
1580             return -1;
1581         }
1582       else
1583         {
1584           // We own this shared memory object!  Let's set its
1585           // size.
1586           if (ACE_OS::ftruncate (fd,
1587                                  sizeof (ACE_sema_t)) == -1)
1588             return -1;
1589           s->name_ = ACE_OS::strdup (name);
1590           if (s->name_ == 0)
1591             return -1;
1592         }
1593       if (fd == -1)
1594         return -1;
1596       s->sema_ = (sem_t *)
1597         ACE_OS::mmap (0,
1598                       sizeof (ACE_sema_t),
1599                       PROT_RDWR,
1600                       MAP_SHARED,
1601                       fd,
1602                       0);
1603       ACE_OS::close (fd);
1604       if (s->sema_ == (sem_t *) MAP_FAILED)
1605         return -1;
1606       if (s->name_
1607           // @@ According UNIX Network Programming V2 by Stevens,
1608           //    sem_init() is currently not required to return zero on
1609           //    success, but it *does* return -1 upon failure.  For
1610           //    this reason, check for failure by comparing to -1,
1611           //    instead of checking for success by comparing to zero.
1612           //        -Ossama
1613           // Only initialize it if we're the one who created it.
1614           && ::sem_init (s->sema_, type == USYNC_PROCESS, count) == -1)
1615         return -1;
1616       return 0;
1617     }
1618 #  else
1619   if (name)
1620     {
1621 #    if defined (sun) || defined (HPUX)
1622       // Solaris and HP-UX require the name to start with a slash. Solaris
1623       // further requires that there be no other slashes than the first.
1624       const char *last_slash = ACE_OS::strrchr (name, '/');
1625       char name2[MAXPATHLEN];
1626       if (0 == last_slash)
1627         {
1628           ACE_OS::strcpy (name2, "/");
1629           ACE_OS::strcat (name2, name);
1630           name = name2;
1631         }
1632 #      if defined (sun)
1633       else
1634         name = last_slash;         // Chop off chars preceding last slash
1635 #      endif /* sun */
1636 #    endif /* sun || HPUX */
1638       ACE_ALLOCATOR_RETURN (s->name_,
1639                             ACE_OS::strdup (name),
1640                             -1);
1641       s->sema_ = ::sem_open (s->name_,
1642                              O_CREAT,
1643                              ACE_DEFAULT_FILE_PERMS,
1644                              count);
1645       if (s->sema_ == (sem_t *) SEM_FAILED)
1646         return -1;
1647       else
1648         return 0;
1649     }
1650 #  endif /* ACE_LACKS_NAMED_POSIX_SEM */
1651   else
1652     {
1653 #  if defined (ACE_LACKS_UNNAMED_SEMAPHORE)
1654       ACE_NOTSUP_RETURN (-1);
1655 #  else
1656 #if defined (ACE_HAS_ALLOC_HOOKS)
1657       ACE_ALLOCATOR_RETURN (s->sema_,
1658                             static_cast<sem_t*>(ACE_Allocator::instance()->malloc(sizeof(sem_t))),
1659                             -1);
1660 #else
1661       ACE_NEW_RETURN (s->sema_,
1662                       sem_t,
1663                       -1);
1664 #endif /* ACE_HAS_ALLOC_HOOKS */
1666 #   if defined (ACE_LACKS_NAMED_POSIX_SEM)
1667       s->new_sema_ = true;
1668 #   endif /* ACE_LACKS_NAMED_POSIX_SEM */
1669       ACE_OS::memset(s->sema_, 0, sizeof(*s->sema_));
1670       ACE_OSCALL_RETURN (::sem_init (s->sema_,
1671                                      type != USYNC_THREAD,
1672                                      count), int, -1);
1673 #  endif /* ACE_LACKS_UNNAMED_SEMAPHORE */
1674     }
1676 #elif defined (ACE_USES_FIFO_SEM)
1677   ACE_UNUSED_ARG (arg);
1678   ACE_UNUSED_ARG (max);
1679   ACE_UNUSED_ARG (sa);
1680   int             flags = 0;
1681   mode_t          mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
1683   if (type == USYNC_THREAD)
1684     {
1685       // Create systemwide unique name for semaphore
1686       char   uname[ACE_UNIQUE_NAME_LEN];
1687       ACE_OS::unique_name ((const void *) s,
1688                             uname,
1689                             ACE_UNIQUE_NAME_LEN);
1690       name = &uname[0];
1691     }
1693   s->name_ = 0;
1694   s->fd_[0] = s->fd_[1] = ACE_INVALID_HANDLE;
1695   bool creator = false;
1697   if (ACE_OS::mkfifo (ACE_TEXT_CHAR_TO_TCHAR (name), mode) < 0)
1698     {
1699       if (errno != EEXIST)    /* already exists OK else ERR */
1700         return -1;
1701       // check if this is a real FIFO, not just some other existing file
1702       ACE_stat fs;
1703       if (ACE_OS::stat (name, &fs))
1704         return -1;
1705       if (!S_ISFIFO (fs.st_mode))
1706         {
1707           // existing file is not a FIFO
1708           errno = EEXIST;
1709           return -1;
1710         }
1711     }
1712     else
1713       creator = true; // remember we created it for initialization at end
1715   // for processshared semaphores remember who we are to be able to remove
1716   // the FIFO when we're done with it
1717   if (type == USYNC_PROCESS)
1718     {
1719       s->name_ = ACE_OS::strdup (name);
1720       if (s->name_ == 0)
1721         {
1722           if (creator)
1723             ACE_OS::unlink (name);
1724           return -1;
1725         }
1726     }
1728   if ((s->fd_[0] = ACE_OS::open (name, O_RDONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE
1729       || (s->fd_[1] = ACE_OS::open (name, O_WRONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE)
1730     return -1;
1732   /* turn off nonblocking for fd_[0] */
1733   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
1734     return -1;
1736   flags &= ~O_NONBLOCK;
1737   if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
1738     return -1;
1740   //if (s->name_ && count)
1741   if (creator && count)
1742     {
1743       char    c = 1;
1744       for (u_int i=0; i<count ;++i)
1745         if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) != 1)
1746           return -1;
1747     }
1749   // In the case of process scope semaphores we can already unlink the FIFO now that
1750   // we completely set it up (the opened handles will keep it active until we close
1751   // thos down). This way we're protected against unexpected crashes as far as removal
1752   // is concerned.
1753   // Unfortunately this does not work for processshared FIFOs since as soon as we
1754   // have unlinked the semaphore no other process will be able to open it anymore.
1755   if (type == USYNC_THREAD)
1756     {
1757       ACE_OS::unlink (name);
1758     }
1760   return 0;
1761 #elif defined (ACE_HAS_THREADS)
1762 #  if defined (ACE_HAS_STHREADS)
1763   ACE_UNUSED_ARG (name);
1764   ACE_UNUSED_ARG (max);
1765   ACE_UNUSED_ARG (sa);
1766   ACE_UNUSED_ARG (attributes);
1767   int result;
1768   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_init (s, count, type, arg), result),
1769                      int, -1);
1770 #  elif defined (ACE_HAS_PTHREADS)
1771   ACE_UNUSED_ARG (max);
1772   ACE_UNUSED_ARG (sa);
1773   int result = -1;
1775   if (ACE_OS::mutex_init (&s->lock_, type, name,
1776                           (ACE_mutexattr_t *) arg) == 0
1777       && (attributes == 0 ?
1778           ACE_OS::cond_init (&s->count_nonzero_, (short)type, name, arg) :
1779             ACE_OS::cond_init (&s->count_nonzero_, *attributes, name, arg)) == 0
1780       && ACE_OS::mutex_lock (&s->lock_) == 0)
1781     {
1782       s->count_ = count;
1783       s->waiters_ = 0;
1785       if (ACE_OS::mutex_unlock (&s->lock_) == 0)
1786         result = 0;
1787     }
1789   if (result == -1)
1790     {
1791       ACE_OS::mutex_destroy (&s->lock_);
1792       ACE_OS::cond_destroy (&s->count_nonzero_);
1793     }
1794   return result;
1795 #  elif defined (ACE_HAS_WTHREADS)
1796   ACE_UNUSED_ARG (attributes);
1797 #    if ! defined (ACE_USES_WINCE_SEMA_SIMULATION)
1798   ACE_UNUSED_ARG (type);
1799   ACE_UNUSED_ARG (arg);
1800   // Create the semaphore with its value initialized to <count> and
1801   // its maximum value initialized to <max>.
1802   SECURITY_ATTRIBUTES sa_buffer;
1803   SECURITY_DESCRIPTOR sd_buffer;
1804   *s = ACE_TEXT_CreateSemaphore
1805     (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
1806      count,
1807      max,
1808      ACE_TEXT_CHAR_TO_TCHAR (name));
1810   if (*s == 0)
1811     ACE_FAIL_RETURN (-1);
1812   /* NOTREACHED */
1813   else
1814     {
1815       // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1816       ACE_OS::set_errno_to_last_error ();
1817       return 0;
1818     }
1819 #    else /* ACE_USES_WINCE_SEMA_SIMULATION */
1820   int result = -1;
1822   // Initialize internal object for semaphore simulation.
1823   // Grab the lock as soon as possible when we initializing
1824   // the semaphore count.  Notice that we initialize the
1825   // event object as "manually reset" so we can amortize the
1826   // cost for singling/reseting the event.
1827   // @@ I changed the mutex type to thread_mutex.  Notice that this
1828   // is basically a CriticalSection object and doesn't not has
1829   // any security attribute whatsoever.  However, since this
1830   // semaphore implementation only works within a process, there
1831   // shouldn't any security issue at all.
1832   if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0
1833       && ACE_OS::event_init (&s->count_nonzero_, 1,
1834                              count > 0, type, name, arg, sa) == 0
1835       && ACE_OS::thread_mutex_lock (&s->lock_) == 0)
1836     {
1837       s->count_ = count;
1839       if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0)
1840         result = 0;
1841     }
1843   // Destroy the internal objects if we didn't initialize
1844   // either of them successfully.  Don't bother to check
1845   // for errors.
1846   if (result == -1)
1847     {
1848       ACE_OS::thread_mutex_destroy (&s->lock_);
1849       ACE_OS::event_destroy (&s->count_nonzero_);
1850     }
1851   return result;
1852 #    endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1853 #  elif defined (ACE_VXWORKS)
1854   ACE_UNUSED_ARG (attributes);
1855   ACE_UNUSED_ARG (name);
1856   ACE_UNUSED_ARG (arg);
1857   ACE_UNUSED_ARG (max);
1858   ACE_UNUSED_ARG (sa);
1859   s->name_ = 0;
1860   s->sema_ = ::semCCreate (type, count);
1861   return s->sema_ ? 0 : -1;
1862 #  endif /* ACE_HAS_STHREADS */
1863 #else
1864   ACE_UNUSED_ARG (s);
1865   ACE_UNUSED_ARG (count);
1866   ACE_UNUSED_ARG (type);
1867   ACE_UNUSED_ARG (attributes);
1868   ACE_UNUSED_ARG (name);
1869   ACE_UNUSED_ARG (arg);
1870   ACE_UNUSED_ARG (max);
1871   ACE_UNUSED_ARG (sa);
1872   ACE_NOTSUP_RETURN (-1);
1873 #endif /* ACE_HAS_POSIX_SEM */
1876 #if defined (ACE_HAS_WCHAR)
1877 ACE_INLINE int
1878 ACE_OS::sema_init (ACE_sema_t *s,
1879                    u_int count,
1880                    int type,
1881                    const wchar_t *name,
1882                    void *arg,
1883                    int max,
1884                    LPSECURITY_ATTRIBUTES sa)
1886   ACE_condattr_t *pattr = 0;
1887   return ACE_OS::sema_init (s, count, type, pattr, name, arg, max, sa);
1890 ACE_INLINE int
1891 ACE_OS::sema_init (ACE_sema_t *s,
1892                    u_int count,
1893                    int type,
1894                    ACE_condattr_t *attributes,
1895                    const wchar_t *name,
1896                    void *arg,
1897                    int max,
1898                    LPSECURITY_ATTRIBUTES sa)
1900 # if defined (ACE_HAS_WTHREADS)
1901   ACE_UNUSED_ARG (attributes);
1902 #   if ! defined (ACE_USES_WINCE_SEMA_SIMULATION)
1903   ACE_UNUSED_ARG (type);
1904   ACE_UNUSED_ARG (arg);
1905   // Create the semaphore with its value initialized to <count> and
1906   // its maximum value initialized to <max>.
1907   SECURITY_ATTRIBUTES sa_buffer;
1908   SECURITY_DESCRIPTOR sd_buffer;
1909   *s = ::CreateSemaphoreW
1910     (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
1911      count,
1912      max,
1913      name);
1915   if (*s == 0)
1916     ACE_FAIL_RETURN (-1);
1917   /* NOTREACHED */
1918   else
1919     {
1920       // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1921       ACE_OS::set_errno_to_last_error ();
1922       return 0;
1923     }
1924 #   else /* ACE_USES_WINCE_SEMA_SIMULATION */
1925   int result = -1;
1927   // Initialize internal object for semaphore simulation.
1928   // Grab the lock as soon as possible when we initializing
1929   // the semaphore count.  Notice that we initialize the
1930   // event object as "manually reset" so we can amortize the
1931   // cost for singling/reseting the event.
1932   // @@ I changed the mutex type to thread_mutex.  Notice that this
1933   // is basically a CriticalSection object and doesn't not has
1934   // any security attribute whatsoever.  However, since this
1935   // semaphore implementation only works within a process, there
1936   // shouldn't any security issue at all.
1937   if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0
1938       && ACE_OS::event_init (&s->count_nonzero_, 1,
1939                              count > 0, type, name, arg, sa) == 0
1940       && ACE_OS::thread_mutex_lock (&s->lock_) == 0)
1941     {
1942       s->count_ = count;
1944       if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0)
1945         result = 0;
1946     }
1948   // Destroy the internal objects if we didn't initialize
1949   // either of them successfully.  Don't bother to check
1950   // for errors.
1951   if (result == -1)
1952     {
1953       ACE_OS::thread_mutex_destroy (&s->lock_);
1954       ACE_OS::event_destroy (&s->count_nonzero_);
1955     }
1956   return result;
1957 #   endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1958 # else /* ACE_HAS_WTHREADS */
1959   // Just call the normal char version.
1960   return ACE_OS::sema_init (s, count, type, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg, max, sa);
1961 # endif /* ACE_HAS_WTHREADS */
1963 #endif /* ACE_HAS_WCHAR */
1965 ACE_INLINE void
1966 ACE_OS::sema_avoid_unlink (ACE_sema_t *s, bool avoid_unlink)
1968 #if defined (ACE_HAS_POSIX_SEM)
1969   s->avoid_unlink_ = avoid_unlink;
1970 #else
1971   ACE_UNUSED_ARG (s);
1972   ACE_UNUSED_ARG (avoid_unlink);
1973 #endif
1976 ACE_INLINE int
1977 ACE_OS::sema_unlink (const char *name)
1979 #if defined (ACE_HAS_POSIX_SEM) && !defined (ACE_LACKS_SEM_UNLINK)
1980   ACE_OSCALL_RETURN (::sem_unlink (name), int, -1);
1981 #else
1982   ACE_UNUSED_ARG (name);
1983   ACE_NOTSUP_RETURN (-1);
1984 #endif
1987 ACE_INLINE int
1988 ACE_OS::sema_post (ACE_sema_t *s)
1990   ACE_OS_TRACE ("ACE_OS::sema_post");
1991 # if defined (ACE_HAS_POSIX_SEM)
1992 #   if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
1993   ACE_OSCALL_RETURN (::sem_post (s->sema_), int, -1);
1994 #   else
1995   int result = -1;
1997   if (ACE_OS::mutex_lock (&s->lock_) == 0)
1998     {
1999       if (::sem_post (s->sema_) == 0)
2000         result = ACE_OS::cond_signal (&s->count_nonzero_);
2002       ACE_OS::mutex_unlock (&s->lock_);
2003     }
2004   return result;
2005 #   endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
2006 # elif defined (ACE_USES_FIFO_SEM)
2007   char    c = 1;
2008   if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) == sizeof (char))
2009     return 0;
2010   return -1;
2011 # elif defined (ACE_HAS_THREADS)
2012 #   if defined (ACE_HAS_STHREADS)
2013   int result;
2014   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_post (s), result), int, -1);
2015 #   elif defined (ACE_HAS_PTHREADS)
2016   int result = -1;
2018   if (ACE_OS::mutex_lock (&s->lock_) == 0)
2019     {
2020       // Always allow a waiter to continue if there is one.
2021       if (s->waiters_ > 0)
2022         result = ACE_OS::cond_signal (&s->count_nonzero_);
2023       else
2024         result = 0;
2026       s->count_++;
2027       ACE_OS::mutex_unlock (&s->lock_);
2028     }
2029   return result;
2030 #   elif defined (ACE_HAS_WTHREADS)
2031 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
2032   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, 1, 0),
2033                                           ace_result_),
2034                         int, -1);
2035 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
2036   int result = -1;
2038   // Since we are simulating semaphores, we need to update semaphore
2039   // count manually.  Grab the lock to prevent race condition first.
2040   if (ACE_OS::thread_mutex_lock (&s->lock_) == 0)
2041     {
2042       // Check the original state of event object.  Single the event
2043       // object in transition from semaphore not available to
2044       // semaphore available.
2045       if (s->count_++ <= 0)
2046         result = ACE_OS::event_signal (&s->count_nonzero_);
2047       else
2048         result = 0;
2050       ACE_OS::thread_mutex_unlock (&s->lock_);
2051     }
2052   return result;
2053 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
2054 #   elif defined (ACE_VXWORKS)
2055   ACE_OSCALL_RETURN (::semGive (s->sema_), int, -1);
2056 #   endif /* ACE_HAS_STHREADS */
2057 # else
2058   ACE_UNUSED_ARG (s);
2059   ACE_NOTSUP_RETURN (-1);
2060 # endif /* ACE_HAS_POSIX_SEM */
2063 ACE_INLINE int
2064 ACE_OS::sema_post (ACE_sema_t *s, u_int release_count)
2066 #if defined (ACE_WIN32) && !defined (ACE_USES_WINCE_SEMA_SIMULATION)
2067   // Win32 supports this natively.
2068   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, release_count, 0),
2069                                           ace_result_), int, -1);
2070 #else
2071   // On POSIX platforms we need to emulate this ourselves.
2072   // @@ We can optimize on this implementation.  However,
2073   // the semaphore promitive on Win32 doesn't allow one
2074   // to increase a semaphore to more than the count it was
2075   // first initialized.  Posix and solaris don't seem to have
2076   // this restriction.  Should we impose the restriction in
2077   // our semaphore simulation?
2078   for (size_t i = 0; i < release_count; i++)
2079     if (ACE_OS::sema_post (s) == -1)
2080       return -1;
2082   return 0;
2083 #endif /* ACE_WIN32 */
2086 ACE_INLINE int
2087 ACE_OS::sema_trywait (ACE_sema_t *s)
2089   ACE_OS_TRACE ("ACE_OS::sema_trywait");
2090 # if defined (ACE_HAS_POSIX_SEM)
2091   // POSIX semaphores set errno to EAGAIN if trywait fails
2092   ACE_OSCALL_RETURN (::sem_trywait (s->sema_), int, -1);
2093 # elif defined (ACE_USES_FIFO_SEM)
2094   char  c;
2095   int     rc, flags;
2097   /* turn on nonblocking for s->fd_[0] */
2098   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
2099     return -1;
2100   flags |= O_NONBLOCK;
2101   if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
2102     return -1;
2104   // read sets errno to EAGAIN if no input
2105   rc = ACE_OS::read (s->fd_[0], &c, sizeof (char));
2107   /* turn off nonblocking for fd_[0] */
2108   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) >= 0)
2109   {
2110     flags &= ~O_NONBLOCK;
2111     ACE_OS::fcntl (s->fd_[0], F_SETFL, flags);
2112   }
2114   return rc == 1 ? 0 : (-1);
2115 # elif defined (ACE_HAS_THREADS)
2116 #   if defined (ACE_HAS_STHREADS)
2117   // STHREADS semaphores set errno to EBUSY if trywait fails.
2118   int result;
2119   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_trywait (s),
2120                                        result),
2121                      int, -1);
2122 #   elif defined (ACE_HAS_PTHREADS)
2124   int result = -1;
2126   if (ACE_OS::mutex_lock (&s->lock_) == 0)
2127     {
2128       if (s->count_ > 0)
2129         {
2130           --s->count_;
2131           result = 0;
2132         }
2133       else
2134         errno = EBUSY;
2136       ACE_OS::mutex_unlock (&s->lock_);
2137     }
2138   return result;
2139 #   elif defined (ACE_HAS_WTHREADS)
2140 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
2141   DWORD result = ::WaitForSingleObject (*s, 0);
2143   if (result == WAIT_OBJECT_0)
2144     return 0;
2145   else
2146     {
2147       if (result == WAIT_TIMEOUT)
2148         errno = EBUSY;
2149       else
2150         ACE_OS::set_errno_to_last_error ();
2151       // This is a hack, we need to find an appropriate mapping...
2152       return -1;
2153     }
2154 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
2155   // Check the status of semaphore first.  Return immediately
2156   // if the semaphore is not available and avoid grabing the
2157   // lock.
2158   DWORD result = ::WaitForSingleObject (s->count_nonzero_, 0);
2160   if (result == WAIT_OBJECT_0)  // Proceed when it is available.
2161     {
2162       ACE_OS::thread_mutex_lock (&s->lock_);
2164       // Need to double check if the semaphore is still available.
2165       // The double checking scheme will slightly affect the
2166       // efficiency if most of the time semaphores are not blocked.
2167       result = ::WaitForSingleObject (s->count_nonzero_, 0);
2168       if (result == WAIT_OBJECT_0)
2169         {
2170           // Adjust the semaphore count.  Only update the event
2171           // object status when the state changed.
2172           s->count_--;
2173           if (s->count_ <= 0)
2174             ACE_OS::event_reset (&s->count_nonzero_);
2175           result = 0;
2176         }
2178       ACE_OS::thread_mutex_unlock (&s->lock_);
2179     }
2181   // Translate error message to errno used by ACE.
2182   if (result == WAIT_TIMEOUT)
2183     errno = EBUSY;
2184   else
2185     ACE_OS::set_errno_to_last_error ();
2186   // This is taken from the hack above. ;)
2187   return -1;
2188 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
2189 #   elif defined (ACE_VXWORKS)
2190   if (::semTake (s->sema_, NO_WAIT) == ERROR)
2191     if (errno == S_objLib_OBJ_UNAVAILABLE)
2192       {
2193         // couldn't get the semaphore
2194         errno = EBUSY;
2195         return -1;
2196       }
2197     else
2198       // error
2199       return -1;
2200   else
2201     // got the semaphore
2202     return 0;
2203 #   endif /* ACE_HAS_STHREADS */
2204 # else
2205   ACE_UNUSED_ARG (s);
2206   ACE_NOTSUP_RETURN (-1);
2207 # endif /* ACE_HAS_POSIX_SEM */
2210 ACE_INLINE int
2211 ACE_OS::sema_wait (ACE_sema_t *s)
2213   ACE_OS_TRACE ("ACE_OS::sema_wait");
2214 # if defined (ACE_HAS_POSIX_SEM)
2215   ACE_OSCALL_RETURN (::sem_wait (s->sema_), int, -1);
2216 # elif defined (ACE_USES_FIFO_SEM)
2217   char c;
2218   if (ACE_OS::read (s->fd_[0], &c, sizeof (char)) == 1)
2219     return 0;
2220   return -1;
2221 # elif defined (ACE_HAS_THREADS)
2222 #   if defined (ACE_HAS_STHREADS)
2223   int result;
2224   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_wait (s), result), int, -1);
2225 #   elif defined (ACE_HAS_PTHREADS)
2226   int result = 0;
2228   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
2230   if (ACE_OS::mutex_lock (&s->lock_) != 0)
2231     result = -1;
2232   else
2233     {
2234       // Keep track of the number of waiters so that we can signal
2235       // them properly in <ACE_OS::sema_post>.
2236       s->waiters_++;
2238       // Wait until the semaphore count is > 0.
2239       while (s->count_ == 0)
2240         if (ACE_OS::cond_wait (&s->count_nonzero_,
2241                                &s->lock_) == -1)
2242           {
2243             result = -2; // -2 means that we need to release the mutex.
2244             break;
2245           }
2247       --s->waiters_;
2248     }
2250   if (result == 0)
2251     --s->count_;
2253   if (result != -1)
2254     ACE_OS::mutex_unlock (&s->lock_);
2255   ACE_PTHREAD_CLEANUP_POP (0);
2256   return result < 0 ? -1 : result;
2258 #   elif defined (ACE_HAS_WTHREADS)
2259 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
2260   switch (::WaitForSingleObject (*s, INFINITE))
2261     {
2262     case WAIT_OBJECT_0:
2263       return 0;
2264     default:
2265       // This is a hack, we need to find an appropriate mapping...
2266       ACE_OS::set_errno_to_last_error ();
2267       return -1;
2268     }
2269   /* NOTREACHED */
2270 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
2271   // Timed wait.
2272   int result = -1;
2273   for (;;)
2274     // Check if the semaphore is avialable or not and wait forever.
2275     // Don't bother to grab the lock if it is not available (to avoid
2276     // deadlock.)
2277     switch (::WaitForSingleObject (s->count_nonzero_, INFINITE))
2278       {
2279       case WAIT_OBJECT_0:
2280         ACE_OS::thread_mutex_lock (&s->lock_);
2282         // Need to double check if the semaphore is still available.
2283         // This time, we shouldn't wait at all.
2284         if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0)
2285           {
2286             // Decrease the internal counter.  Only update the event
2287             // object's status when the state changed.
2288             s->count_--;
2289             if (s->count_ <= 0)
2290               ACE_OS::event_reset (&s->count_nonzero_);
2291             result = 0;
2292           }
2294         ACE_OS::thread_mutex_unlock (&s->lock_);
2295         // if we didn't get a hold on the semaphore, the result won't
2296         // be 0 and thus, we'll start from the beginning again.
2297         if (result == 0)
2298           return 0;
2299         break;
2301       default:
2302         // Since we wait indefinitely, anything other than
2303         // WAIT_OBJECT_O indicates an error.
2304         ACE_OS::set_errno_to_last_error ();
2305         // This is taken from the hack above. ;)
2306         return -1;
2307       }
2308   /* NOTREACHED */
2309 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
2310 #   elif defined (ACE_VXWORKS)
2311   ACE_OSCALL_RETURN (::semTake (s->sema_, WAIT_FOREVER), int, -1);
2312 #   endif /* ACE_HAS_STHREADS */
2313 # else
2314   ACE_UNUSED_ARG (s);
2315   ACE_NOTSUP_RETURN (-1);
2316 # endif /* ACE_HAS_POSIX_SEM */
2319 ACE_INLINE int
2320 ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv)
2322   ACE_OS_TRACE ("ACE_OS::sema_wait");
2323 # if defined (ACE_HAS_POSIX_SEM)
2324 #   if defined (ACE_HAS_POSIX_SEM_TIMEOUT)
2325   int rc;
2326   timespec_t ts;
2327   ts = tv; // Calls ACE_Time_Value::operator timespec_t().
2328   ACE_OSCALL (::sem_timedwait (s->sema_, &ts), int, -1, rc);
2329   if (rc == -1 && errno == ETIMEDOUT)
2330     errno = ETIME;  /* POSIX returns ETIMEDOUT but we need ETIME */
2331   return rc;
2332 #   elif !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
2333   int result = 0;
2334   bool expired = false;
2335   ACE_Errno_Guard error (errno);
2337   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
2339   if (ACE_OS::mutex_lock (&s->lock_) != 0)
2340     result = -2;
2341   else
2342     {
2343       bool finished = true;
2344       do
2345       {
2346         result = ACE_OS::sema_trywait (s);
2347         if (result == -1 && errno == EAGAIN)
2348           expired = (tv.to_relative_time () <= ACE_Time_Value::zero);
2349         else
2350           expired = false;
2352         finished = result != -1 || expired ||
2353                    (result == -1 && errno != EAGAIN);
2354         if (!finished)
2355           {
2356             if (ACE_OS::cond_timedwait (&s->count_nonzero_,
2357                                         &s->lock_,
2358                                         &tv) == -1)
2359               {
2360                 error = errno;
2361                 result = -1;
2362                 break;
2363               }
2364           }
2365       } while (!finished);
2367       if (expired)
2368         error = ETIME;
2370 #     if defined (ACE_LACKS_COND_TIMEDWAIT_RESET)
2371       tv = tv.now ();
2372 #     endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */
2373     }
2375   if (result != -2)
2376     ACE_OS::mutex_unlock (&s->lock_);
2377   ACE_PTHREAD_CLEANUP_POP (0);
2378   return result < 0 ? -1 : result;
2379 #   else /* No native sem_timedwait(), and emulation disabled */
2380   ACE_UNUSED_ARG (s);
2381   ACE_UNUSED_ARG (tv);
2382   ACE_NOTSUP_RETURN (-1);
2383 #   endif /* ACE_HAS_POSIX_SEM_TIMEOUT */
2384 # elif defined (ACE_USES_FIFO_SEM)
2385   int rc;
2386   ACE_Time_Value timeout = tv.to_relative_time ();
2388   while (timeout > ACE_Time_Value::zero)
2389     {
2390       ACE_Handle_Set  fds_;
2392       fds_.set_bit (s->fd_[0]);
2393       if ((rc = ACE_OS::select (ACE_Handle_Set::MAXSIZE, fds_, 0, 0, timeout)) != 1)
2394         {
2395           if (rc == 0 || errno != EAGAIN)
2396           {
2397             if (rc == 0)
2398               errno = ETIME;
2399             return -1;
2400           }
2401         }
2403       // try to read the signal *but* do *not* block
2404       if (rc == 1 && ACE_OS::sema_trywait (s) == 0)
2405         return 0;
2407       // we were woken for input but someone beat us to it
2408       // so we wait again if there is still time
2409       timeout = tv.to_relative_time ();
2410     }
2412   // make sure errno is set right
2413   errno = ETIME;
2415   return -1;
2416 # elif defined (ACE_HAS_THREADS)
2417 #   if defined (ACE_HAS_STHREADS)
2418   ACE_UNUSED_ARG (s);
2419   ACE_UNUSED_ARG (tv);
2420   ACE_NOTSUP_RETURN (-1);
2421 #   elif defined (ACE_HAS_PTHREADS)
2422   int result = 0;
2423   ACE_Errno_Guard error (errno);
2425   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
2427   if (ACE_OS::mutex_lock (&s->lock_) != 0)
2428     result = -1;
2429   else
2430     {
2431       // Keep track of the number of waiters so that we can signal
2432       // them properly in <ACE_OS::sema_post>.
2433       s->waiters_++;
2435       // Wait until the semaphore count is > 0 or until we time out.
2436       while (s->count_ == 0)
2437         if (ACE_OS::cond_timedwait (&s->count_nonzero_,
2438                                     &s->lock_,
2439                                     &tv) == -1)
2440           {
2441             error = errno;
2442             result = -2; // -2 means that we need to release the mutex.
2443             break;
2444           }
2446       --s->waiters_;
2447     }
2449   if (result == 0)
2450     {
2451 #     if defined (ACE_LACKS_COND_TIMEDWAIT_RESET)
2452       tv = tv.now ();
2453 #     endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */
2454       --s->count_;
2455     }
2457   if (result != -1)
2458     ACE_OS::mutex_unlock (&s->lock_);
2459   ACE_PTHREAD_CLEANUP_POP (0);
2460   return result < 0 ? -1 : result;
2461 #   elif defined (ACE_HAS_WTHREADS)
2462 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
2463   int msec_timeout;
2465   if (tv == ACE_Time_Value::zero)
2466     msec_timeout = 0; // Do a "poll."
2467   else
2468     {
2469       // Note that we must convert between absolute time (which is
2470       // passed as a parameter) and relative time (which is what
2471       // <WaitForSingleObjects> expects).
2472       ACE_Time_Value relative_time = tv.to_relative_time ();
2474       // Watchout for situations where a context switch has caused the
2475       // current time to be > the timeout.
2476       if (relative_time < ACE_Time_Value::zero)
2477         msec_timeout = 0;
2478       else
2479         msec_timeout = relative_time.msec ();
2480     }
2482   switch (::WaitForSingleObject (*s, msec_timeout))
2483     {
2484     case WAIT_OBJECT_0:
2485       tv = tv.now ();     // Update time to when acquired
2486       return 0;
2487     case WAIT_TIMEOUT:
2488       errno = ETIME;
2489       return -1;
2490     default:
2491       // This is a hack, we need to find an appropriate mapping...
2492       ACE_OS::set_errno_to_last_error ();
2493       return -1;
2494     }
2495   /* NOTREACHED */
2496 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
2497   // Note that in this mode, the acquire is done in two steps, and
2498   // we may get signaled but cannot grab the semaphore before
2499   // timeout.  In that case, we'll need to restart the process with
2500   // updated timeout value.
2502   // tv is an absolute time, but we need relative to work with the Windows
2503   // API. Also, some users have become accustomed to using a 0 time value
2504   // as a shortcut for "now", which works on non-Windows because 0 is
2505   // always earlier than now. However, the need to convert to relative time
2506   // means we need to watch out for this case.
2507   ACE_Time_Value relative_time (ACE_Time_Value::zero);
2508   if (tv != ACE_Time_Value::zero)
2509     relative_time = tv.to_relative_time ();
2510   int result = -1;
2512   // While we are not timeout yet. >= 0 will let this go through once
2513   // and if not able to get the object, it should hit WAIT_TIMEOUT
2514   // right away.
2515   while (relative_time >= ACE_Time_Value::zero)
2516     {
2517       // Wait for our turn to get the object.
2518       switch (::WaitForSingleObject (s->count_nonzero_, relative_time.msec ()))
2519         {
2520         case WAIT_OBJECT_0:
2521           ACE_OS::thread_mutex_lock (&s->lock_);
2523           // Need to double check if the semaphore is still available.
2524           // We can only do a "try lock" styled wait here to avoid
2525           // blocking threads that want to signal the semaphore.
2526           if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0)
2527             {
2528               // As before, only reset the object when the semaphore
2529               // is no longer available.
2530               s->count_--;
2531               if (s->count_ <= 0)
2532                 ACE_OS::event_reset (&s->count_nonzero_);
2533               result = 0;
2534             }
2536           ACE_OS::thread_mutex_unlock (&s->lock_);
2538           // Only return when we successfully get the semaphore.
2539           if (result == 0)
2540             {
2541               tv = tv.now ();     // Update to time acquired
2542               return 0;
2543             }
2544           break;
2546           // We have timed out.
2547         case WAIT_TIMEOUT:
2548           errno = ETIME;
2549           return -1;
2551           // What?
2552         default:
2553           ACE_OS::set_errno_to_last_error ();
2554           // This is taken from the hack above. ;)
2555           return -1;
2556         };
2558       // Haven't been able to get the semaphore yet, update the
2559       // timeout value to reflect the remaining time we want to wait.
2560       // in case of tv == 0 relative_time will now be < 0 and we will be out of time
2561       relative_time = tv.to_relative_time ();
2562     }
2564   // We have timed out.
2565   errno = ETIME;
2566   return -1;
2567 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
2568 #   elif defined (ACE_VXWORKS)
2569   // Note that we must convert between absolute time (which is
2570   // passed as a parameter) and relative time (which is what
2571   // the system call expects).
2572   ACE_Time_Value relative_time = tv.to_relative_time ();
2574   int ticks_per_sec = ::sysClkRateGet ();
2576   int ticks = relative_time.sec () * ticks_per_sec +
2577               relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
2578   if (::semTake (s->sema_, ticks) == ERROR)
2579     {
2580       if (errno == S_objLib_OBJ_TIMEOUT)
2581         // Convert the VxWorks errno to one that's common for to ACE
2582         // platforms.
2583         errno = ETIME;
2584       else if (errno == S_objLib_OBJ_UNAVAILABLE)
2585         errno = EBUSY;
2586       return -1;
2587     }
2588   else
2589     {
2590       tv = tv.now ();  // Update to time acquired
2591       return 0;
2592     }
2593 #   endif /* ACE_HAS_STHREADS */
2594 # else
2595   ACE_UNUSED_ARG (s);
2596   ACE_UNUSED_ARG (tv);
2597   ACE_NOTSUP_RETURN (-1);
2598 # endif /* ACE_HAS_POSIX_SEM */
2601 ACE_INLINE int
2602 ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value *tv)
2604   return tv == 0 ? ACE_OS::sema_wait (s) : ACE_OS::sema_wait (s, *tv);
2607 ACE_INLINE int
2608 ACE_OS::semctl (int int_id, int semnum, int cmd, semun value)
2610   ACE_OS_TRACE ("ACE_OS::semctl");
2611 #if defined (ACE_HAS_SYSV_IPC)
2612   ACE_OSCALL_RETURN (::semctl (int_id, semnum, cmd, value), int, -1);
2613 #else
2614   ACE_UNUSED_ARG (int_id);
2615   ACE_UNUSED_ARG (semnum);
2616   ACE_UNUSED_ARG (cmd);
2617   ACE_UNUSED_ARG (value);
2619   ACE_NOTSUP_RETURN (-1);
2620 #endif /* ACE_HAS_SYSV_IPC */
2623 ACE_INLINE int
2624 ACE_OS::semget (key_t key, int nsems, int flags)
2626   ACE_OS_TRACE ("ACE_OS::semget");
2627 #if defined (ACE_HAS_SYSV_IPC)
2628   ACE_OSCALL_RETURN (::semget (key, nsems, flags), int, -1);
2629 #else
2630   ACE_UNUSED_ARG (key);
2631   ACE_UNUSED_ARG (nsems);
2632   ACE_UNUSED_ARG (flags);
2634   ACE_NOTSUP_RETURN (-1);
2635 #endif /* ACE_HAS_SYSV_IPC */
2638 ACE_INLINE int
2639 ACE_OS::semop (int int_id, struct sembuf *sops, size_t nsops)
2641   ACE_OS_TRACE ("ACE_OS::semop");
2642 #if defined (ACE_HAS_SYSV_IPC)
2643   ACE_OSCALL_RETURN (::semop (int_id, sops, nsops), int, -1);
2644 #else
2645   ACE_UNUSED_ARG (int_id);
2646   ACE_UNUSED_ARG (sops);
2647   ACE_UNUSED_ARG (nsops);
2649   ACE_NOTSUP_RETURN (-1);
2650 #endif /* ACE_HAS_SYSV_IPC */
2653 ACE_INLINE int
2654 ACE_OS::sigtimedwait (const sigset_t *sset,
2655                       siginfo_t *info,
2656                       const ACE_Time_Value *timeout)
2658   ACE_OS_TRACE ("ACE_OS::sigtimedwait");
2659 #if defined (ACE_HAS_SIGTIMEDWAIT)
2660   timespec_t ts;
2661   timespec_t *tsp = 0;
2663   if (timeout != 0)
2664     {
2665       ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
2666       tsp = &ts;
2667     }
2669   ACE_OSCALL_RETURN (::sigtimedwait (sset, info, tsp),
2670                      int, -1);
2671 #else
2672     ACE_UNUSED_ARG (sset);
2673     ACE_UNUSED_ARG (info);
2674     ACE_UNUSED_ARG (timeout);
2675     ACE_NOTSUP_RETURN (-1);
2676 #endif /* ACE_HAS_SIGTIMEDWAIT */
2679 ACE_INLINE int
2680 ACE_OS::sigwait (sigset_t *sset, int *sig)
2682   ACE_OS_TRACE ("ACE_OS::sigwait");
2683   int local_sig;
2684   if (sig == 0)
2685     sig = &local_sig;
2686 #if defined (ACE_HAS_THREADS)
2687 # if (defined (__FreeBSD__) && (__FreeBSD__ < 3))
2688     ACE_UNUSED_ARG (sset);
2689     ACE_NOTSUP_RETURN (-1);
2690 # elif defined (ACE_HAS_STHREADS)
2691    # if (_POSIX_C_SOURCE - 0 >= 199506L) || defined (_POSIX_PTHREAD_SEMANTICS)
2692      errno = ::sigwait (sset, sig);
2693      return errno == 0  ?  *sig  :  -1;
2694    #else
2695      *sig = ::sigwait (sset);
2696      return *sig;
2697    #endif /* _POSIX_C_SOURCE - 0 >= 199506L || _POSIX_PTHREAD_SEMANTICS */
2698 # elif defined (ACE_HAS_PTHREADS)
2699 #   if defined (CYGWIN32)
2700       // Cygwin has sigwait definition, but it is not implemented
2701       ACE_UNUSED_ARG (sset);
2702       ACE_NOTSUP_RETURN (-1);
2703 #   else   /* this is std */
2704       errno = ::sigwait (sset, sig);
2705       return errno == 0  ?  *sig  :  -1;
2706 #   endif /* CYGWIN32 */
2707 # elif defined (ACE_HAS_WTHREADS)
2708     ACE_UNUSED_ARG (sset);
2709     ACE_NOTSUP_RETURN (-1);
2710 # elif defined (ACE_VXWORKS)
2711     // Second arg is a struct siginfo *, which we don't need (the
2712     // selected signal number is returned).  Third arg is timeout:  0
2713     // means forever.
2714     *sig = ::sigtimedwait (sset, 0, 0);
2715     return *sig;
2716 # endif /* __FreeBSD__ */
2717 #else
2718     ACE_UNUSED_ARG (sset);
2719     ACE_UNUSED_ARG (sig);
2720     ACE_NOTSUP_RETURN (-1);
2721 #endif /* ACE_HAS_THREADS */
2724 ACE_INLINE int
2725 ACE_OS::sigwaitinfo (const sigset_t *sset,
2726                      siginfo_t *info)
2728   ACE_OS_TRACE ("ACE_OS::sigwaitinfo");
2729   // If this platform has sigtimedwait, it should have sigwaitinfo as well.
2730   // If this isn't true somewhere, let me know and I'll fix this.
2731   // -Steve Huston <shuston@riverace.com>.
2732 #if defined (ACE_HAS_SIGTIMEDWAIT)
2733   ACE_OSCALL_RETURN (::sigwaitinfo (sset, info), int, -1);
2734 #else
2735   ACE_UNUSED_ARG (sset);
2736   ACE_UNUSED_ARG (info);
2737   ACE_NOTSUP_RETURN (-1);
2738 #endif /* ACE_HAS_SIGTIMEDWAIT */
2741 ACE_INLINE int
2742 ACE_OS::thr_cancel (ACE_thread_t thr_id)
2744   ACE_OS_TRACE ("ACE_OS::thr_cancel");
2745 #if defined (ACE_HAS_THREADS)
2746 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
2747   int result;
2748   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cancel (thr_id),
2749                                         result),
2750                       int, -1);
2751 # elif defined (ACE_HAS_VXTHREADS)
2752   ACE_OSCALL_RETURN (::taskDelete (thr_id), int, -1);
2753 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
2754   ACE_UNUSED_ARG (thr_id);
2755   ACE_NOTSUP_RETURN (-1);
2756 # endif /* ACE_HAS_PTHREADS */
2757 #else
2758   ACE_UNUSED_ARG (thr_id);
2759   ACE_NOTSUP_RETURN (-1);
2760 #endif /* ACE_HAS_THREADS */
2763 ACE_INLINE int
2764 ACE_OS::thr_cmp (ACE_hthread_t t1, ACE_hthread_t t2)
2766 #if defined (ACE_HAS_PTHREADS)
2767 # if defined (pthread_equal)
2768   // If it's a macro we can't say "pthread_equal"...
2769   return pthread_equal (t1, t2);
2770 # else
2771   return pthread_equal (t1, t2);
2772 # endif /* pthread_equal */
2773 #else /* For STHREADS, WTHREADS, and VXWORKS ... */
2774   // Hum, Do we need to treat WTHREAD differently?
2775   // levine 13 oct 98 % Probably, ACE_hthread_t is a HANDLE.
2776   return t1 == t2;
2777 #endif /* ACE_HAS_PTHREADS */
2780 ACE_INLINE int
2781 ACE_OS::thr_continue (ACE_hthread_t target_thread)
2783   ACE_OS_TRACE ("ACE_OS::thr_continue");
2784 #if defined (ACE_HAS_THREADS)
2785 # if defined (ACE_HAS_STHREADS)
2786   int result;
2787   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_continue (target_thread), result), int, -1);
2788 # elif defined (ACE_HAS_PTHREADS)
2789 #  if defined (ACE_HAS_PTHREAD_CONTINUE)
2790   int result;
2791   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue (target_thread),
2792                                        result),
2793                      int, -1);
2794 #  elif defined (ACE_HAS_PTHREAD_CONTINUE_NP)
2795   int result;
2796   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue_np (target_thread),
2797                                        result),
2798                      int, -1);
2799 #  elif defined (ACE_HAS_PTHREAD_RESUME_NP)
2800   int result;
2801   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_resume_np (target_thread),
2802                                        result),
2803                      int, -1);
2804 #  else
2805   ACE_UNUSED_ARG (target_thread);
2806   ACE_NOTSUP_RETURN (-1);
2807 #  endif /* ACE_HAS_PTHREAD_CONTINUE */
2808 # elif defined (ACE_HAS_WTHREADS)
2809   DWORD result = ::ResumeThread (target_thread);
2810   if (result == ACE_SYSCALL_FAILED)
2811     ACE_FAIL_RETURN (-1);
2812   else
2813     return 0;
2814 # elif defined (ACE_HAS_VXTHREADS)
2815   ACE_OSCALL_RETURN (::taskResume (target_thread), int, -1);
2816 # endif /* ACE_HAS_STHREADS */
2817 #else
2818   ACE_UNUSED_ARG (target_thread);
2819   ACE_NOTSUP_RETURN (-1);
2820 #endif /* ACE_HAS_THREADS */
2823 ACE_INLINE int
2824 ACE_OS::thr_getconcurrency (void)
2826   ACE_OS_TRACE ("ACE_OS::thr_getconcurrency");
2827 #if defined (ACE_HAS_THREADS)
2828 # if defined (ACE_HAS_STHREADS)
2829   return ::thr_getconcurrency ();
2830 # elif defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_GETCONCURRENCY)
2831   return pthread_getconcurrency ();
2832 # else
2833   ACE_NOTSUP_RETURN (-1);
2834 # endif /* ACE_HAS_STHREADS */
2835 #else
2836   ACE_NOTSUP_RETURN (-1);
2837 #endif /* ACE_HAS_THREADS */
2840 ACE_INLINE int
2841 ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority, int &policy)
2843   ACE_OS_TRACE ("ACE_OS::thr_getprio");
2844   ACE_UNUSED_ARG (policy);
2845 #if defined (ACE_HAS_THREADS)
2846 # if (defined (ACE_HAS_PTHREADS) && \
2847      (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
2849   struct sched_param param;
2850   int result;
2852   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
2853                                 result), int,
2854               -1, result);
2855   priority = param.sched_priority;
2856   return result;
2857 # elif defined (ACE_HAS_STHREADS)
2858   int result;
2859   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getprio (ht_id, &priority), result), int, -1);
2860 # elif defined (ACE_HAS_WTHREADS)
2861   ACE_Errno_Guard error (errno);
2863 #   if defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_CE_THREAD_PRIORITY)
2864   priority = ::CeGetThreadPriority (ht_id);
2865 #   else
2866   priority = ::GetThreadPriority (ht_id);
2867 #   endif /* defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_CE_THREAD_PRIORITY) */
2869 #   if defined (ACE_HAS_PHARLAP)
2870 #     if defined (ACE_PHARLAP_LABVIEW_RT)
2871   policy = ACE_SCHED_FIFO;
2872 #     else
2873   DWORD timeslice = ::EtsGetTimeSlice ();
2874   policy = timeslice == 0 ? ACE_SCHED_OTHER : ACE_SCHED_FIFO;
2875 #     endif /* ACE_PHARLAP_LABVIEW_RT */
2876 #   elif !defined (ACE_HAS_WINCE)
2877   DWORD priority_class = ::GetPriorityClass (::GetCurrentProcess ());
2878   if (priority_class == 0 && (error = ::GetLastError ()) != NO_ERROR)
2879     ACE_FAIL_RETURN (-1);
2881   policy =
2882     (priority_class ==
2883      REALTIME_PRIORITY_CLASS) ? ACE_SCHED_FIFO : ACE_SCHED_OTHER;
2884 #   endif /* ACE_HAS_PHARLAP */
2886   return 0;
2887 # elif defined (ACE_HAS_VXTHREADS)
2888   ACE_OSCALL_RETURN (::taskPriorityGet (ht_id, &priority), int, -1);
2889 # else
2890   ACE_UNUSED_ARG (ht_id);
2891   ACE_UNUSED_ARG (priority);
2892   ACE_NOTSUP_RETURN (-1);
2893 # endif /* ACE_HAS_STHREADS */
2894 #else
2895   ACE_UNUSED_ARG (ht_id);
2896   ACE_UNUSED_ARG (priority);
2897   ACE_NOTSUP_RETURN (-1);
2898 #endif /* ACE_HAS_THREADS */
2901 ACE_INLINE int
2902 ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority)
2904   ACE_OS_TRACE ("ACE_OS::thr_getprio");
2905   int policy = 0;
2906   return ACE_OS::thr_getprio (ht_id, priority, policy);
2909 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
2910 ACE_INLINE int
2911 ACE_OS::thr_getspecific_native (ACE_OS_thread_key_t key, void **data)
2913 //  ACE_OS_TRACE ("ACE_OS::thr_getspecific_native");
2914 # if defined (ACE_HAS_PTHREADS)
2915     *data = pthread_getspecific (key);
2916     return 0;
2917 # elif defined (ACE_HAS_STHREADS)
2918     int result;
2919     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getspecific (key, data), result), int, -1);
2920 # elif defined (ACE_HAS_WTHREADS)
2921   *data = ::TlsGetValue (key);
2922   if (*data == 0 && ::GetLastError () != NO_ERROR)
2923     {
2924       ACE_OS::set_errno_to_last_error ();
2925       return -1;
2926     }
2927   else
2928     return 0;
2929 # else /* ACE_HAS_PTHREADS etc.*/
2930   ACE_UNUSED_ARG (key);
2931   ACE_UNUSED_ARG (data);
2932   ACE_NOTSUP_RETURN (-1);
2933 # endif /* ACE_HAS_PTHREADS etc.*/
2935 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
2937 ACE_INLINE int
2938 ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data)
2940 //   ACE_OS_TRACE ("ACE_OS::thr_getspecific");
2941 #if defined (ACE_HAS_THREADS)
2942 # if defined (ACE_HAS_TSS_EMULATION)
2943     if (ACE_TSS_Emulation::is_key (key) == 0)
2944       {
2945         errno = EINVAL;
2946         data = 0;
2947         return -1;
2948       }
2949     else
2950       {
2951         *data = ACE_TSS_Emulation::ts_object (key);
2952         return 0;
2953       }
2954 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
2955   return ACE_OS::thr_getspecific_native (key, data);
2956 #else
2957   ACE_UNUSED_ARG (key);
2958   ACE_UNUSED_ARG (data);
2959   ACE_NOTSUP_RETURN (-1);
2960 # endif /* ACE_HAS_TSS_EMULATION */
2961 #else
2962   ACE_UNUSED_ARG (key);
2963   ACE_UNUSED_ARG (data);
2964   ACE_NOTSUP_RETURN (-1);
2965 #endif /* ACE_HAS_THREADS */
2968 #if !defined (ACE_HAS_VXTHREADS)
2969 ACE_INLINE int
2970 ACE_OS::thr_join (ACE_hthread_t thr_handle,
2971                   ACE_THR_FUNC_RETURN *status)
2973   ACE_OS_TRACE ("ACE_OS::thr_join");
2974 #if defined (ACE_HAS_THREADS)
2975 # if defined (ACE_HAS_STHREADS)
2976   int result;
2977   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (thr_handle, 0, status), result),
2978                      int, -1);
2979 # elif defined (ACE_HAS_PTHREADS)
2980 #  if defined (ACE_LACKS_PTHREAD_JOIN)
2981   ACE_UNUSED_ARG (thr_handle);
2982   ACE_UNUSED_ARG (status);
2983   ACE_NOTSUP_RETURN (-1);
2984 #  else
2985   int result;
2986   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (thr_handle, status), result),
2987                      int, -1);
2988 #  endif /* ACE_LACKS_PTHREAD_JOIN */
2989 # elif defined (ACE_HAS_WTHREADS)
2990   // Waiting on the calling thread will deadlock, so try to avoid that. The
2991   // direct access to the needed info (GetThreadId) was added at Vista.
2992   // Win Server 2003 is 5.2; Vista is 6.0
2993 #   if defined (_WIN32_WINNT) && (_WIN32_WINNT >= 0x0502)
2994   const ACE_TEXT_OSVERSIONINFO &info = ACE_OS::get_win32_versioninfo ();
2995   if (info.dwMajorVersion >= 6 ||
2996       (info.dwMajorVersion == 5 && info.dwMinorVersion == 2))
2997     {
2998       if (::GetThreadId (thr_handle) == ::GetCurrentThreadId ())
2999         {
3000           errno = ERROR_POSSIBLE_DEADLOCK;
3001           return -1;
3002         }
3003     }
3004 #   endif /* _WIN32_WINNT */
3006   ACE_THR_FUNC_RETURN local_status = 0;
3008   // Make sure that status is non-NULL.
3009   if (status == 0)
3010     status = &local_status;
3012   if (::WaitForSingleObject (thr_handle, INFINITE) == WAIT_OBJECT_0
3013       && ::GetExitCodeThread (thr_handle, status) != FALSE)
3014     {
3015       ::CloseHandle (thr_handle);
3016       return 0;
3017     }
3018   ACE_FAIL_RETURN (-1);
3019   /* NOTREACHED */
3020 # else
3021   ACE_UNUSED_ARG (thr_handle);
3022   ACE_UNUSED_ARG (status);
3023   ACE_NOTSUP_RETURN (-1);
3024 # endif /* ACE_HAS_STHREADS */
3025 #else
3026   ACE_UNUSED_ARG (thr_handle);
3027   ACE_UNUSED_ARG (status);
3028   ACE_NOTSUP_RETURN (-1);
3029 #endif /* ACE_HAS_THREADS */
3032 ACE_INLINE int
3033 ACE_OS::thr_join (ACE_thread_t waiter_id,
3034                   ACE_thread_t *thr_id,
3035                   ACE_THR_FUNC_RETURN *status)
3037   ACE_OS_TRACE ("ACE_OS::thr_join");
3038 #if defined (ACE_HAS_THREADS)
3039 # if defined (ACE_HAS_STHREADS)
3040   int result;
3041   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (waiter_id, thr_id, status), result),
3042                      int, -1);
3043 # elif defined (ACE_HAS_PTHREADS)
3044 #  if defined (ACE_LACKS_PTHREAD_JOIN)
3045   ACE_UNUSED_ARG (waiter_id);
3046   ACE_UNUSED_ARG (thr_id);
3047   ACE_UNUSED_ARG (status);
3048   ACE_NOTSUP_RETURN (-1);
3049 #  else
3050   ACE_UNUSED_ARG (thr_id);
3051   int result;
3052   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (waiter_id, status), result),
3053                      int, -1);
3054 #  endif /* ACE_LACKS_PTHREAD_JOIN */
3055 # elif defined (ACE_HAS_WTHREADS)
3056   ACE_UNUSED_ARG (waiter_id);
3057   ACE_UNUSED_ARG (thr_id);
3058   ACE_UNUSED_ARG (status);
3060   // This could be implemented if the DLL-Main function or the
3061   // task exit base class some log the threads which have exited
3062   ACE_NOTSUP_RETURN (-1);
3063 # endif /* ACE_HAS_STHREADS */
3064 #else
3065   ACE_UNUSED_ARG (waiter_id);
3066   ACE_UNUSED_ARG (thr_id);
3067   ACE_UNUSED_ARG (status);
3068   ACE_NOTSUP_RETURN (-1);
3069 #endif /* ACE_HAS_THREADS */
3071 #endif /* !VXWORKS */
3073 ACE_INLINE int
3074 ACE_OS::thr_kill (ACE_thread_t thr_id, int signum)
3076   ACE_OS_TRACE ("ACE_OS::thr_kill");
3077 #if defined (ACE_HAS_THREADS)
3078 # if defined (ACE_HAS_PTHREADS)
3079 #   if defined (ACE_LACKS_PTHREAD_KILL)
3080   ACE_UNUSED_ARG (signum);
3081   ACE_UNUSED_ARG (thr_id);
3082   ACE_NOTSUP_RETURN (-1);
3083 #   else
3084   int result;
3085   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_kill (thr_id, signum),
3086                                        result),
3087                      int, -1);
3088 #   endif /* ACE_LACKS_PTHREAD_KILL */
3089 # elif defined (ACE_HAS_STHREADS)
3090   int result;
3091   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_kill (thr_id, signum),
3092                                        result),
3093                      int, -1);
3094 # elif defined (ACE_HAS_VXTHREADS)
3095   //FUZZ: disable check_for_lack_ACE_OS
3096   ACE_OSCALL_RETURN (::kill (thr_id, signum), int, -1);
3097   //FUZZ: enable check_for_lack_ACE_OS
3098 # else
3099   ACE_UNUSED_ARG (thr_id);
3100   ACE_UNUSED_ARG (signum);
3101   ACE_NOTSUP_RETURN (-1);
3102 # endif /* ACE_HAS_STHREADS */
3103 #else
3104   ACE_UNUSED_ARG (thr_id);
3105   ACE_UNUSED_ARG (signum);
3106   ACE_NOTSUP_RETURN (-1);
3107 #endif /* ACE_HAS_THREADS */
3110 ACE_INLINE size_t
3111 ACE_OS::thr_min_stack (void)
3113   ACE_OS_TRACE ("ACE_OS::thr_min_stack");
3114 #if defined (ACE_HAS_THREADS)
3115 # if defined (ACE_HAS_STHREADS)
3116 #   if defined (ACE_HAS_THR_MINSTACK)
3117   // Tandem did some weirdo mangling of STHREAD names...
3118   return ::thr_minstack ();
3119 #   else
3120   return ::thr_min_stack ();
3121 #   endif /* !ACE_HAS_THR_MINSTACK */
3122 # elif defined (ACE_HAS_PTHREADS)
3123 #   if defined (_SC_THREAD_STACK_MIN)
3124   return (size_t) ACE_OS::sysconf (_SC_THREAD_STACK_MIN);
3125 #   elif defined (PTHREAD_STACK_MIN)
3126   return PTHREAD_STACK_MIN;
3127 #   else
3128   ACE_NOTSUP_RETURN (0);
3129 #   endif /* _SC_THREAD_STACK_MIN */
3130 # elif defined (ACE_HAS_WTHREADS)
3131   ACE_NOTSUP_RETURN (0);
3132 # elif defined (ACE_HAS_VXTHREADS)
3133   TASK_DESC taskDesc;
3134   STATUS status;
3136   ACE_thread_t tid = ACE_OS::thr_self ();
3138   ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (tid, &taskDesc),
3139                                 status),
3140               STATUS, -1, status);
3141   return status == OK ? taskDesc.td_stackSize : 0;
3142 # else /* Should not happen... */
3143   ACE_NOTSUP_RETURN (0);
3144 # endif /* ACE_HAS_STHREADS */
3145 #else
3146   ACE_NOTSUP_RETURN (0);
3147 #endif /* ACE_HAS_THREADS */
3150 ACE_INLINE ssize_t
3151 ACE_OS::thr_id (char buffer[], size_t buffer_length)
3153 #if defined (ACE_WIN32)
3154   return ACE_OS::snprintf (buffer,
3155                            buffer_length,
3156                            "%u",
3157                            static_cast <unsigned> (ACE_OS::thr_self ()));
3158 #else /* ACE_WIN32 */
3159   ACE_hthread_t t_id;
3160   ACE_OS::thr_self (t_id);
3161 #if defined(ACE_HAS_OPAQUE_PTHREAD_T)
3162   return ACE_OS::snprintf (buffer,
3163                            buffer_length,
3164                            "%s",
3165                            "<unknown>");
3166 #else /* ACE_HAS_OPAQUE_PTHREAD_T */
3167   return ACE_OS::snprintf (buffer,
3168                            buffer_length,
3169                            "%lu",
3170                            (unsigned long) t_id);
3171 #endif /* ACE_HAS_OPAQUE_PTHREAD_T */
3172 #endif /* WIN32 */
3175 ACE_INLINE ssize_t
3176 ACE_OS::thr_gettid (char buffer[], size_t buffer_length)
3178   return ACE_OS::snprintf (buffer, buffer_length, "%d",
3179     static_cast<int> (ACE_OS::thr_gettid ()));
3182 ACE_INLINE ACE_thread_t
3183 ACE_OS::thr_self (void)
3185   // ACE_OS_TRACE ("ACE_OS::thr_self");
3186 #if defined (ACE_HAS_THREADS)
3187 # if defined (ACE_HAS_PTHREADS)
3188   // Note, don't use "::" here since the following call is often a macro.
3189   return pthread_self ();
3190 # elif defined (ACE_HAS_STHREADS)
3191   ACE_OSCALL_RETURN (::thr_self (), int, -1);
3192 # elif defined (ACE_HAS_WTHREADS)
3193   return ::GetCurrentThreadId ();
3194 # elif defined (ACE_HAS_VXTHREADS)
3195   return ::taskIdSelf ();
3196 # endif /* ACE_HAS_STHREADS */
3197 #else
3198   return 1; // Might as well make it the first thread ;-)
3199 #endif /* ACE_HAS_THREADS */
3202 ACE_INLINE const char*
3203 ACE_OS::thr_name (void)
3205 #if defined (ACE_HAS_THREADS)
3206 #if defined (ACE_HAS_VXTHREADS)
3207   return ::taskName (ACE_OS::thr_self ());
3208 #else
3209   ACE_NOTSUP_RETURN (0);
3210 #endif
3211 #else
3212   ACE_NOTSUP_RETURN (0);
3213 #endif
3216 ACE_INLINE void
3217 ACE_OS::thr_self (ACE_hthread_t &self)
3219   ACE_OS_TRACE ("ACE_OS::thr_self");
3220 #if defined (ACE_HAS_THREADS)
3221 # if defined (ACE_HAS_PTHREADS)
3222   // Note, don't use "::" here since the following call is often a macro.
3223   self = pthread_self ();
3224 # elif defined (ACE_HAS_THREAD_SELF)
3225   self = ::thread_self ();
3226 # elif defined (ACE_HAS_STHREADS)
3227   self = ::thr_self ();
3228 # elif defined (ACE_HAS_WTHREADS)
3229   self = ::GetCurrentThread ();
3230 # elif defined (ACE_HAS_VXTHREADS)
3231   self = ::taskIdSelf ();
3232 # endif /* ACE_HAS_STHREADS */
3233 #else
3234   self = 1; // Might as well make it the main thread ;-)
3235 #endif /* ACE_HAS_THREADS */
3238 ACE_INLINE int
3239 ACE_OS::thr_setcancelstate (int new_state, int *old_state)
3241   ACE_OS_TRACE ("ACE_OS::thr_setcancelstate");
3242 #if defined (ACE_HAS_THREADS)
3243 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
3244   int result;
3245   int local_new, local_old;
3246   switch (new_state)
3247     {
3248     case THR_CANCEL_ENABLE:
3249       local_new = PTHREAD_CANCEL_ENABLE;
3250       break;
3251     case THR_CANCEL_DISABLE:
3252       local_new = PTHREAD_CANCEL_DISABLE;
3253       break;
3254     default:
3255       errno = EINVAL;
3256       return -1;
3257     }
3258   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_setcancelstate (local_new,
3259                                                         &local_old),
3260                                 result),
3261               int, -1, result);
3262   if (result == -1)
3263     return -1;
3264   switch (local_old)
3265     {
3266     case PTHREAD_CANCEL_ENABLE:
3267       *old_state = THR_CANCEL_ENABLE;
3268       break;
3269     case PTHREAD_CANCEL_DISABLE:
3270       *old_state = THR_CANCEL_DISABLE;
3271       break;
3272     }
3273   return result;
3274 # elif defined (ACE_HAS_STHREADS)
3275   ACE_UNUSED_ARG (new_state);
3276   ACE_UNUSED_ARG (old_state);
3277   ACE_NOTSUP_RETURN (-1);
3278 # elif defined (ACE_HAS_WTHREADS)
3279   ACE_UNUSED_ARG (new_state);
3280   ACE_UNUSED_ARG (old_state);
3281   ACE_NOTSUP_RETURN (-1);
3282 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
3283   ACE_UNUSED_ARG (new_state);
3284   ACE_UNUSED_ARG (old_state);
3285   ACE_NOTSUP_RETURN (-1);
3286 # endif /* ACE_HAS_PTHREADS */
3287 #else
3288   ACE_UNUSED_ARG (new_state);
3289   ACE_UNUSED_ARG (old_state);
3290   ACE_NOTSUP_RETURN (-1);
3291 #endif /* ACE_HAS_THREADS */
3294 ACE_INLINE int
3295 ACE_OS::thr_setcanceltype (int new_type, int *old_type)
3297   ACE_OS_TRACE ("ACE_OS::thr_setcanceltype");
3298 #if defined (ACE_HAS_THREADS)
3299 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
3300   int result;
3301   int local_new, local_old;
3302   switch (new_type)
3303     {
3304     case THR_CANCEL_DEFERRED:
3305       local_new = PTHREAD_CANCEL_DEFERRED;
3306       break;
3307     case THR_CANCEL_ASYNCHRONOUS:
3308       local_new = PTHREAD_CANCEL_ASYNCHRONOUS;
3309       break;
3310     default:
3311       errno = EINVAL;
3312       return -1;
3313     }
3314   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_setcanceltype (local_new,
3315                                                        &local_old),
3316                                 result),
3317               int, -1, result);
3318   if (result == -1)
3319     return -1;
3320   switch (local_old)
3321     {
3322     case PTHREAD_CANCEL_DEFERRED:
3323       *old_type = THR_CANCEL_DEFERRED;
3324       break;
3325     case PTHREAD_CANCEL_ASYNCHRONOUS:
3326       *old_type = THR_CANCEL_ASYNCHRONOUS;
3327       break;
3328     }
3329   return result;
3330 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
3331   ACE_UNUSED_ARG (new_type);
3332   ACE_UNUSED_ARG (old_type);
3333   ACE_NOTSUP_RETURN (-1);
3334 # endif /* ACE_HAS_PTHREADS */
3335 #else
3336   ACE_UNUSED_ARG (new_type);
3337   ACE_UNUSED_ARG (old_type);
3338   ACE_NOTSUP_RETURN (-1);
3339 #endif /* ACE_HAS_THREADS */
3342 ACE_INLINE int
3343 ACE_OS::thr_setconcurrency (int hint)
3345   ACE_OS_TRACE ("ACE_OS::thr_setconcurrency");
3346 #if defined (ACE_HAS_THREADS)
3347 # if defined (ACE_HAS_STHREADS)
3348   int result;
3349   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setconcurrency (hint),
3350                                        result),
3351                      int, -1);
3352 # elif defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_SETCONCURRENCY)
3353   int result;
3354   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setconcurrency (hint),
3355                                        result),
3356                      int, -1);
3357 # else
3358   ACE_UNUSED_ARG (hint);
3359   ACE_NOTSUP_RETURN (-1);
3360 # endif /* ACE_HAS_STHREADS */
3361 #else
3362   ACE_UNUSED_ARG (hint);
3363   ACE_NOTSUP_RETURN (-1);
3364 #endif /* ACE_HAS_THREADS */
3367 ACE_INLINE int
3368 ACE_OS::thr_setprio (ACE_hthread_t ht_id, int priority, int policy)
3370   ACE_OS_TRACE ("ACE_OS::thr_setprio");
3371   ACE_UNUSED_ARG (policy);
3372 #if defined (ACE_HAS_THREADS)
3373 # if (defined (ACE_HAS_PTHREADS) && \
3374       (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
3376   int result;
3377   struct sched_param param;
3378   ACE_OS::memset ((void *) &param, 0, sizeof param);
3380   // If <policy> is -1, we don't want to use it for
3381   // pthread_setschedparam().  Instead, obtain policy from
3382   // pthread_getschedparam().
3383   if (policy == -1)
3384     {
3385       ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
3386                                     result),
3387                   int, -1, result);
3388       if (result == -1)
3389         return result;
3390     }
3392   param.sched_priority = priority;
3394   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setschedparam (ht_id,
3395                                                               policy,
3396                                                               &param),
3397                                        result),
3398                      int, -1);
3399 # elif defined (ACE_HAS_STHREADS)
3400   int result;
3401   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setprio (ht_id, priority),
3402                                        result),
3403                      int, -1);
3404 # elif defined (ACE_HAS_WTHREADS)
3406 #   if defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_CE_THREAD_PRIORITY)
3407   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CeSetThreadPriority (ht_id, priority),
3408                                           ace_result_),
3409                         int, -1);
3410 #   else
3411   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetThreadPriority (ht_id, priority),
3412                                           ace_result_),
3413                         int, -1);
3414 #   endif /* defined (ACE_HAS_WINCE) && !defined (ACE_LACKS_CE_THREAD_PRIORITY) */
3416 # elif defined (ACE_HAS_VXTHREADS)
3417   ACE_OSCALL_RETURN (::taskPrioritySet (ht_id, priority), int, -1);
3418 # else
3419   // For example, platforms that support Pthreads but LACK_SETSCHED.
3420   ACE_UNUSED_ARG (ht_id);
3421   ACE_UNUSED_ARG (priority);
3422   ACE_NOTSUP_RETURN (-1);
3423 # endif /* ACE_HAS_STHREADS */
3424 #else
3425   ACE_UNUSED_ARG (ht_id);
3426   ACE_UNUSED_ARG (priority);
3427   ACE_NOTSUP_RETURN (-1);
3428 #endif /* ACE_HAS_THREADS */
3431 ACE_INLINE int
3432 ACE_OS::thr_sigsetmask (int how,
3433                         const sigset_t *nsm,
3434                         sigset_t *osm)
3436   ACE_OS_TRACE ("ACE_OS::thr_sigsetmask");
3437 #if defined (ACE_HAS_THREADS)
3438 # if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
3439   // DCE threads and Solaris 2.4 have no such function.
3440   ACE_UNUSED_ARG (osm);
3441   ACE_UNUSED_ARG (nsm);
3442   ACE_UNUSED_ARG (how);
3444   ACE_NOTSUP_RETURN (-1);
3445 # elif defined (ACE_HAS_SIGTHREADMASK)
3446   int result;
3447   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigthreadmask (how, nsm, osm),
3448                                        result), int, -1);
3449 # elif defined (ACE_HAS_STHREADS)
3450   int result;
3451   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_sigsetmask (how, nsm, osm),
3452                                        result),
3453                      int, -1);
3454 # elif defined (ACE_HAS_PTHREADS)
3455 #   if !defined (ACE_LACKS_PTHREAD_SIGMASK)
3456   int result;
3457   //FUZZ: disable check_for_lack_ACE_OS
3458 #    if defined (ACE_HAS_NONCONST_PTHREAD_SIGMASK)
3459   sigset_t *ncnsm = const_cast<sigset_t *>(nsm);
3460   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, ncnsm, osm),
3461                                        result),
3462                      int,
3463                      -1);
3464 #    else
3465   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm),
3466                                        result),
3467                      int,
3468                      -1);
3469 #    endif /* ACE_HAS_NONCONST__PTHREAD_SIGMASK */
3470   //FUZZ: enable check_for_lack_ACE_OS
3471 #   endif /* !ACE_LACKS_PTHREAD_SIGMASK */
3473 # elif defined (ACE_HAS_WTHREADS)
3474   ACE_UNUSED_ARG (osm);
3475   ACE_UNUSED_ARG (nsm);
3476   ACE_UNUSED_ARG (how);
3478   ACE_NOTSUP_RETURN (-1);
3479 # elif defined (ACE_VXWORKS)
3480   int old_mask = 0;
3481   switch (how)
3482     {
3483     case SIG_BLOCK:
3484     case SIG_UNBLOCK:
3485       {
3486         // get the old mask
3487         old_mask = ::sigsetmask (*nsm);
3488         // create a new mask:  the following assumes that sigset_t is 4 bytes,
3489         // which it is on VxWorks 5.2, so bit operations are done simply . . .
3490         ::sigsetmask (how == SIG_BLOCK ? (old_mask |= *nsm) : (old_mask &= ~*nsm));
3491         if (osm)
3492           *osm = old_mask;
3493         break;
3494       }
3495     case SIG_SETMASK:
3496       old_mask = ::sigsetmask (*nsm);
3497       if (osm)
3498         *osm = old_mask;
3499       break;
3500     default:
3501       return -1;
3502     }
3504   return 0;
3505 # else /* Should not happen. */
3506   ACE_UNUSED_ARG (how);
3507   ACE_UNUSED_ARG (nsm);
3508   ACE_UNUSED_ARG (osm);
3509   ACE_NOTSUP_RETURN (-1);
3510 # endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
3511 #else
3512   ACE_UNUSED_ARG (how);
3513   ACE_UNUSED_ARG (nsm);
3514   ACE_UNUSED_ARG (osm);
3515   ACE_NOTSUP_RETURN (-1);
3516 #endif /* ACE_HAS_THREADS */
3519 ACE_INLINE int
3520 ACE_OS::thr_suspend (ACE_hthread_t target_thread)
3522   ACE_OS_TRACE ("ACE_OS::thr_suspend");
3523 #if defined (ACE_HAS_THREADS)
3524 # if defined (ACE_HAS_STHREADS)
3525   int result;
3526   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_suspend (target_thread), result), int, -1);
3527 # elif defined (ACE_HAS_PTHREADS)
3528 #  if defined (ACE_HAS_PTHREAD_SUSPEND)
3529   int result;
3530   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend (target_thread),
3531                                        result),
3532                      int, -1);
3533 #  elif defined (ACE_HAS_PTHREAD_SUSPEND_NP)
3534   int result;
3535   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend_np (target_thread),
3536                                        result),
3537                      int, -1);
3538 #  else
3539   ACE_UNUSED_ARG (target_thread);
3540   ACE_NOTSUP_RETURN (-1);
3541 #  endif /* ACE_HAS_PTHREAD_SUSPEND */
3542 # elif defined (ACE_HAS_WTHREADS)
3543   if (::SuspendThread (target_thread) != ACE_SYSCALL_FAILED)
3544     return 0;
3545   else
3546     ACE_FAIL_RETURN (-1);
3547   /* NOTREACHED */
3548 # elif defined (ACE_HAS_VXTHREADS)
3549   ACE_OSCALL_RETURN (::taskSuspend (target_thread), int, -1);
3550 # endif /* ACE_HAS_STHREADS */
3551 #else
3552   ACE_UNUSED_ARG (target_thread);
3553   ACE_NOTSUP_RETURN (-1);
3554 #endif /* ACE_HAS_THREADS */
3557 ACE_INLINE void
3558 ACE_OS::thr_testcancel (void)
3560   ACE_OS_TRACE ("ACE_OS::thr_testcancel");
3561 #if defined (ACE_HAS_THREADS)
3562 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
3563   pthread_testcancel ();
3564 # elif defined (ACE_HAS_STHREADS)
3565 # elif defined (ACE_HAS_WTHREADS)
3566 # elif defined (ACE_HAS_VXTHREADS)
3567 # else
3568   // no-op:  can't use ACE_NOTSUP_RETURN because there is no return value
3569 # endif /* ACE_HAS_PTHREADS */
3570 #else
3571 #endif /* ACE_HAS_THREADS */
3574 ACE_INLINE void
3575 ACE_OS::thr_yield (void)
3577   ACE_OS_TRACE ("ACE_OS::thr_yield");
3578 #if defined (ACE_HAS_THREADS)
3579 # if defined (ACE_HAS_PTHREADS)
3580   ::sched_yield ();
3581 # elif defined (ACE_HAS_STHREADS)
3582   ::thr_yield ();
3583 # elif defined (ACE_HAS_WTHREADS)
3584   ::Sleep (0);
3585 # elif defined (ACE_HAS_VXTHREADS)
3586   // An argument of 0 to ::taskDelay doesn't appear to yield the
3587   // current thread.
3588   // Now, it does seem to work.  The context_switch_time test
3589   // works fine with task_delay set to 0.
3590   ::taskDelay (0);
3591 # endif /* ACE_HAS_STHREADS */
3592 #else
3593   ;
3594 #endif /* ACE_HAS_THREADS */
3597 ACE_INLINE int
3598 ACE_OS::thread_mutex_destroy (ACE_thread_mutex_t *m)
3600   ACE_OS_TRACE ("ACE_OS::thread_mutex_destroy");
3601 #if defined (ACE_HAS_THREADS)
3602 # if defined (ACE_HAS_WTHREADS)
3603   ::DeleteCriticalSection (m);
3604   return 0;
3605 # else
3606   return ACE_OS::mutex_destroy (m);
3607 # endif /* ACE_HAS_WTHREADS */
3608 #else
3609   ACE_UNUSED_ARG (m);
3610   ACE_NOTSUP_RETURN (-1);
3612 #endif /* ACE_HAS_THREADS */
3615 ACE_INLINE int
3616 ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
3617                            int lock_type,
3618                            const char *name,
3619                            ACE_mutexattr_t *arg)
3621   // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
3622 #if defined (ACE_HAS_THREADS)
3623 # if defined (ACE_HAS_WTHREADS)
3624   ACE_UNUSED_ARG (lock_type);
3625   ACE_UNUSED_ARG (name);
3626   ACE_UNUSED_ARG (arg);
3628   ACE_SEH_TRY
3629     {
3630       ::InitializeCriticalSection (m);
3631     }
3632   ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3633     {
3634       errno = ENOMEM;
3635       return -1;
3636     }
3637   return 0;
3639 # elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS)
3640   // Force the use of USYNC_THREAD!
3641   return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
3642 # elif defined (ACE_HAS_VXTHREADS)
3643   return mutex_init (m, lock_type, name, arg);
3645 # endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */
3647 #else
3648   ACE_UNUSED_ARG (m);
3649   ACE_UNUSED_ARG (lock_type);
3650   ACE_UNUSED_ARG (name);
3651   ACE_UNUSED_ARG (arg);
3652   ACE_NOTSUP_RETURN (-1);
3654 #endif /* ACE_HAS_THREADS */
3657 #if defined (ACE_HAS_WCHAR)
3658 ACE_INLINE int
3659 ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
3660                            int lock_type,
3661                            const wchar_t *name,
3662                            ACE_mutexattr_t *arg)
3664   // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
3665 #if defined (ACE_HAS_THREADS)
3666 # if defined (ACE_HAS_WTHREADS)
3667   ACE_UNUSED_ARG (lock_type);
3668   ACE_UNUSED_ARG (name);
3669   ACE_UNUSED_ARG (arg);
3671   ACE_SEH_TRY
3672     {
3673       ::InitializeCriticalSection (m);
3674     }
3675   ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
3676     {
3677       errno = ENOMEM;
3678       return -1;
3679     }
3680   return 0;
3682 # elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS)
3683   // Force the use of USYNC_THREAD!
3684   return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
3685 # elif defined (ACE_HAS_VXTHREADS)
3686   return mutex_init (m, lock_type, name, arg);
3687 # endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */
3688 #else
3689   ACE_UNUSED_ARG (m);
3690   ACE_UNUSED_ARG (lock_type);
3691   ACE_UNUSED_ARG (name);
3692   ACE_UNUSED_ARG (arg);
3693   ACE_NOTSUP_RETURN (-1);
3695 #endif /* ACE_HAS_THREADS */
3697 #endif /* ACE_HAS_WCHAR */
3699 ACE_INLINE int
3700 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m)
3702   // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
3703 #if defined (ACE_HAS_THREADS)
3704 # if defined (ACE_HAS_WTHREADS)
3705   ::EnterCriticalSection (m);
3706   return 0;
3707 # else
3708   return ACE_OS::mutex_lock (m);
3709 # endif /* ACE_HAS_WTHREADS */
3710 #else
3711   ACE_UNUSED_ARG (m);
3712   ACE_NOTSUP_RETURN (-1);
3713 #endif /* ACE_HAS_THREADS */
3716 ACE_INLINE int
3717 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
3718                            const ACE_Time_Value &timeout)
3720   // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
3722   // For all platforms, except MS Windows, this method is equivalent
3723   // to calling ACE_OS::mutex_lock() since ACE_thread_mutex_t and
3724   // ACE_mutex_t are the same type.  However, those typedefs evaluate
3725   // to different types on MS Windows.  The "thread mutex"
3726   // implementation in ACE for MS Windows cannot readily support
3727   // timeouts due to a lack of timeout features for this type of MS
3728   // Windows synchronization mechanism.
3730 #if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_WTHREADS)
3731   return ACE_OS::mutex_lock (m, timeout);
3732 #else
3733   ACE_UNUSED_ARG (m);
3734   ACE_UNUSED_ARG (timeout);
3735   ACE_NOTSUP_RETURN (-1);
3736 #endif /* ACE_HAS_THREADS */
3739 ACE_INLINE int
3740 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
3741                            const ACE_Time_Value *timeout)
3743   return timeout == 0
3744     ? ACE_OS::thread_mutex_lock (m)
3745     : ACE_OS::thread_mutex_lock (m, *timeout);
3748 ACE_INLINE int
3749 ACE_OS::thread_mutex_trylock (ACE_thread_mutex_t *m)
3751   ACE_OS_TRACE ("ACE_OS::thread_mutex_trylock");
3753 #if defined (ACE_HAS_THREADS)
3754 # if defined (ACE_HAS_WTHREADS)
3755 #   if defined (ACE_HAS_WIN32_TRYLOCK)
3756   BOOL result = ::TryEnterCriticalSection (m);
3757   if (result == TRUE)
3758     {
3759       return 0;
3760     }
3761   else
3762     {
3763       errno = EBUSY;
3764       return -1;
3765     }
3766 #   else
3767   ACE_UNUSED_ARG (m);
3768   ACE_NOTSUP_RETURN (-1);
3769 #   endif /* ACE_HAS_WIN32_TRYLOCK */
3770 # elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_VXWORKS)
3771   return ACE_OS::mutex_trylock (m);
3772 #endif /* Threads variety case */
3774 #else
3775   ACE_UNUSED_ARG (m);
3776   ACE_NOTSUP_RETURN (-1);
3777 #endif /* ACE_HAS_THREADS */
3780 ACE_INLINE int
3781 ACE_OS::thread_mutex_unlock (ACE_thread_mutex_t *m)
3783   ACE_OS_TRACE ("ACE_OS::thread_mutex_unlock");
3784 #if defined (ACE_HAS_THREADS)
3785 # if defined (ACE_HAS_WTHREADS)
3786   ::LeaveCriticalSection (m);
3787   return 0;
3788 # else
3789   return ACE_OS::mutex_unlock (m);
3790 # endif /* ACE_HAS_WTHREADS */
3791 #else
3792   ACE_UNUSED_ARG (m);
3793   ACE_NOTSUP_RETURN (-1);
3794 #endif /* ACE_HAS_THREADS */
3797 /*****************************************************************************/
3799 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
3801 ACE_INLINE
3803 ACE_OS_Thread_Mutex_Guard::acquire (void)
3805   return owner_ = ACE_OS::thread_mutex_lock (&lock_);
3808 ACE_INLINE
3810 ACE_OS_Thread_Mutex_Guard::release (void)
3812   if (owner_ == -1)
3813     return 0;
3814   else
3815     {
3816       owner_ = -1;
3817       return ACE_OS::thread_mutex_unlock (&lock_);
3818     }
3821 ACE_INLINE
3822 ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m)
3823   : lock_ (m), owner_ (-1)
3825   if (!ACE_OS_Object_Manager::starting_up ())
3826     acquire ();
3829 ACE_INLINE
3830 ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard ()
3832   release ();
3835 /*****************************************************************************/
3837 ACE_INLINE
3839 ACE_OS_Recursive_Thread_Mutex_Guard::acquire (void)
3841   return owner_ = ACE_OS::recursive_mutex_lock (&lock_);
3844 ACE_INLINE
3846 ACE_OS_Recursive_Thread_Mutex_Guard::release (void)
3848   if (owner_ == -1)
3849     return 0;
3850   else
3851     {
3852       owner_ = -1;
3853       return ACE_OS::recursive_mutex_unlock (&lock_);
3854     }
3857 ACE_INLINE
3858 ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard (
3859   ACE_recursive_thread_mutex_t &m)
3860    : lock_ (m),
3861      owner_ (-1)
3863   if (!ACE_OS_Object_Manager::starting_up ())
3864     acquire ();
3867 ACE_INLINE
3868 ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard ()
3870   release ();
3873 #endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
3876 /*****************************************************************************/
3878 ACE_INLINE
3879 ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id,
3880                               ACE_hthread_t thread_handle)
3881   : thread_id_ (thread_id),
3882     thread_handle_ (thread_handle)
3886 ACE_INLINE
3887 ACE_Thread_ID::ACE_Thread_ID (const ACE_Thread_ID &id)
3888   : thread_id_ (id.thread_id_),
3889     thread_handle_ (id.thread_handle_)
3893 ACE_INLINE
3894 ACE_Thread_ID&
3895 ACE_Thread_ID::operator= (const ACE_Thread_ID &id)
3897   if (this != &id)
3898     {
3899       this->thread_id_ = id.thread_id_;
3900       this->thread_handle_ = id.thread_handle_;
3901     }
3902   return *this;
3905 ACE_INLINE
3906 ACE_Thread_ID::ACE_Thread_ID (void)
3907   : thread_id_ (ACE_OS::thr_self ())
3909   ACE_OS::thr_self (thread_handle_);
3912 ACE_INLINE
3913 ACE_thread_t
3914 ACE_Thread_ID::id (void) const
3916   return this->thread_id_;
3919 ACE_INLINE void
3920 ACE_Thread_ID::id (ACE_thread_t thread_id)
3922   this->thread_id_ = thread_id;
3925 ACE_INLINE ACE_hthread_t
3926 ACE_Thread_ID::handle (void) const
3928   return this->thread_handle_;
3931 ACE_INLINE void
3932 ACE_Thread_ID::handle (ACE_hthread_t thread_handle)
3934   this->thread_handle_ = thread_handle;
3937 ACE_INLINE bool
3938 ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const
3940   return
3941     ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_)
3942     && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_);
3945 ACE_INLINE bool
3946 ACE_Thread_ID::operator!= (const ACE_Thread_ID &rhs) const
3948   return !(*this == rhs);
3951 #if !defined (ACE_WIN32)
3953 ACE_INLINE
3954 ACE_event_t::ACE_event_t (void) :
3955   name_ (0),
3956   eventdata_ (0)
3960 #endif /* !ACE_WIN32 */
3962 ACE_END_VERSIONED_NAMESPACE_DECL