OS_NS_Thread.inl

Go to the documentation of this file.
00001 // -*- C++ -*-
00002 //
00003 // $Id: OS_NS_Thread.inl 80826 2008-03-04 14:51:23Z wotte $
00004 
00005 #include "ace/OS_NS_macros.h"
00006 // for timespec_t, perhaps move it to os_time.h
00007 #include "ace/Time_Value.h"
00008 #include "ace/OS_NS_sys_mman.h"
00009 #include "ace/OS_NS_sys_time.h"
00010 #include "ace/OS_NS_string.h"
00011 #include "ace/OS_NS_unistd.h"
00012 #include "ace/OS_NS_stdio.h"
00013 #include "ace/OS_NS_errno.h"
00014 
00015 #if defined (ACE_USES_FIFO_SEM)
00016 #  include "ace/OS_NS_sys_stat.h"
00017 #  include "ace/OS_NS_sys_select.h"
00018 #  include "ace/OS_NS_fcntl.h"
00019 #  include "ace/Handle_Set.h"
00020 # endif /* ACE_USES_FIFO_SEM */
00021 
00022 #if defined (ACE_HAS_PRIOCNTL)
00023 #  include /**/ <sys/priocntl.h>
00024 #endif /* ACE_HAS_PRIOCNTL */
00025 
00026 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00027 
00028 /*****************************************************************************/
00029 
00030 #if defined (ACE_LACKS_COND_T) && defined (ACE_HAS_THREADS)
00031 ACE_INLINE long
00032 ACE_cond_t::waiters (void) const
00033 {
00034   return this->waiters_;
00035 }
00036 #endif /* ACE_LACKS_COND_T && ACE_HAS_THREADS */
00037 
00038 /*****************************************************************************/
00039 
00040 #if defined (ACE_HAS_TSS_EMULATION)
00041 
00042 #  if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
00043 ACE_INLINE
00044 void **&
00045 ACE_TSS_Emulation::tss_base ()
00046 {
00047 #    if defined (ACE_HAS_VXTHREADS)
00048   int &spare = taskIdCurrent->ACE_VXWORKS_SPARE;
00049   return reinterpret_cast <void **&> (spare);
00050 #    else
00051   // Uh oh.
00052   ACE_NOTSUP_RETURN (0);
00053 #    endif /* ACE_HAS_VXTHREADS */
00054 }
00055 #  endif /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
00056 
00057 ACE_INLINE
00058 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
00059 ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key)
00060 {
00061   ACE_KEY_INDEX (key_index, key);
00062   return tss_destructor_ [key_index];
00063 }
00064 
00065 ACE_INLINE
00066 void
00067 ACE_TSS_Emulation::tss_destructor (const ACE_thread_key_t key,
00068                                    ACE_TSS_DESTRUCTOR destructor)
00069 {
00070   ACE_KEY_INDEX (key_index, key);
00071   tss_destructor_ [key_index] = destructor;
00072 }
00073 
00074 ACE_INLINE
00075 void *&
00076 ACE_TSS_Emulation::ts_object (const ACE_thread_key_t key)
00077 {
00078   ACE_KEY_INDEX (key_index, key);
00079 
00080 #    if defined (ACE_HAS_VXTHREADS)
00081     /* If someone wants tss_base make sure they get one.  This
00082        gets used if someone spawns a VxWorks task directly, not
00083        through ACE.  The allocated array will never be deleted! */
00084     if (0 == taskIdCurrent->ACE_VXWORKS_SPARE)
00085       {
00086         taskIdCurrent->ACE_VXWORKS_SPARE =
00087           reinterpret_cast<int> (new void *[ACE_TSS_THREAD_KEYS_MAX]);
00088 
00089         // Zero the entire TSS array.  Do it manually instead of using
00090         // memset, for optimum speed.  Though, memset may be faster :-)
00091         void **tss_base_p =
00092           reinterpret_cast<void **> (taskIdCurrent->ACE_VXWORKS_SPARE);
00093         for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
00094           {
00095             *tss_base_p = 0;
00096           }
00097       }
00098 #    endif /* ACE_HAS_VXTHREADS */
00099 
00100   return tss_base ()[key_index];
00101 }
00102 
00103 #endif /* ACE_HAS_TSS_EMULATION */
00104 
00105 /*****************************************************************************/
00106 
00107 ACE_INLINE int
00108 ACE_OS::thr_equal (ACE_thread_t t1, ACE_thread_t t2)
00109 {
00110 #if defined (ACE_HAS_PTHREADS)
00111 # if defined (pthread_equal)
00112   // If it's a macro we can't say "pthread_equal"...
00113   return pthread_equal (t1, t2);
00114 # else
00115   return pthread_equal (t1, t2);
00116 # endif /* pthread_equal */
00117 #else /* For both STHREADS and WTHREADS... */
00118   // Hum, Do we need to treat WTHREAD differently?
00119   // levine 13 oct 98 % I don't think so, ACE_thread_t is a DWORD.
00120   return t1 == t2;
00121 #endif /* ACE_HAS_PTHREADS */
00122 }
00123 
00124 #if !defined (ACE_LACKS_COND_T)
00125 // NOTE: The ACE_OS::cond_* functions for Unix platforms are defined
00126 // here because the ACE_OS::sema_* functions below need them.
00127 // However, ACE_WIN32 and VXWORKS define the ACE_OS::cond_* functions
00128 // using the ACE_OS::sema_* functions.  So, they are defined in OS.cpp.
00129 
00130 ACE_INLINE int
00131 ACE_OS::condattr_destroy (ACE_condattr_t &attributes)
00132 {
00133 #if defined (ACE_HAS_THREADS)
00134 #   if defined (ACE_HAS_PTHREADS)
00135 
00136   pthread_condattr_destroy (&attributes);
00137 
00138 #   elif defined (ACE_HAS_STHREADS)
00139   attributes.type = 0;
00140 
00141 #   endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
00142   return 0;
00143 # else
00144   ACE_UNUSED_ARG (attributes);
00145   return 0;
00146 # endif /* ACE_HAS_THREADS  */
00147 }
00148 
00149 ACE_INLINE int
00150 ACE_OS::condattr_init (ACE_condattr_t &attributes,
00151                        int type)
00152 {
00153   ACE_UNUSED_ARG (type);
00154 # if defined (ACE_HAS_THREADS)
00155 #   if defined (ACE_HAS_PTHREADS)
00156   int result = -1;
00157 
00158 #   if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
00159       /* Tests show that VxWorks 6.x pthread lib does not only
00160        * require zeroing of mutex/condition objects to function correctly
00161        * but also of the attribute objects.
00162        */
00163       ACE_OS::memset (&attributes, 0, sizeof (attributes));
00164 #   endif
00165   if (
00166       ACE_ADAPT_RETVAL (pthread_condattr_init (&attributes), result) == 0
00167 #       if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)
00168       && ACE_ADAPT_RETVAL (pthread_condattr_setpshared (&attributes, type),
00169                            result) == 0
00170 #       endif /* _POSIX_THREAD_PROCESS_SHARED && ! ACE_LACKS_CONDATTR_PSHARED */
00171       )
00172      result = 0;
00173   else
00174      result = -1;       // ACE_ADAPT_RETVAL used it for intermediate status
00175 
00176   return result;
00177 #   elif defined (ACE_HAS_STHREADS)
00178   attributes.type = type;
00179 
00180   return 0;
00181 
00182 #   else
00183   ACE_UNUSED_ARG (attributes);
00184   ACE_UNUSED_ARG (type);
00185   ACE_NOTSUP_RETURN (-1);
00186 
00187 #   endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
00188 
00189 # else
00190   ACE_UNUSED_ARG (attributes);
00191   ACE_UNUSED_ARG (type);
00192   ACE_NOTSUP_RETURN (-1);
00193 # endif /* ACE_HAS_THREADS */
00194 }
00195 
00196 ACE_INLINE int
00197 ACE_OS::cond_broadcast (ACE_cond_t *cv)
00198 {
00199   ACE_OS_TRACE ("ACE_OS::cond_broadcast");
00200 # if defined (ACE_HAS_THREADS)
00201 #   if defined (ACE_HAS_PTHREADS)
00202   int result;
00203   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_broadcast (cv),
00204                                        result),
00205                      int, -1);
00206 #   elif defined (ACE_HAS_STHREADS)
00207   int result;
00208   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_broadcast (cv),
00209                                        result),
00210                      int, -1);
00211 #   endif /* ACE_HAS_STHREADS */
00212 # else
00213   ACE_UNUSED_ARG (cv);
00214   ACE_NOTSUP_RETURN (-1);
00215 # endif /* ACE_HAS_THREADS */
00216 }
00217 
00218 ACE_INLINE int
00219 ACE_OS::cond_destroy (ACE_cond_t *cv)
00220 {
00221   ACE_OS_TRACE ("ACE_OS::cond_destroy");
00222 # if defined (ACE_HAS_THREADS)
00223 #   if defined (ACE_HAS_PTHREADS)
00224   int result;
00225   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_destroy (cv), result), int, -1);
00226 #   elif defined (ACE_HAS_STHREADS)
00227   int result;
00228   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_destroy (cv), result), int, -1);
00229 #   endif /* ACE_HAS_STHREADS */
00230 # else
00231   ACE_UNUSED_ARG (cv);
00232   ACE_NOTSUP_RETURN (-1);
00233 # endif /* ACE_HAS_THREADS */
00234 }
00235 
00236 ACE_INLINE int
00237 ACE_OS::cond_init (ACE_cond_t *cv,
00238                    ACE_condattr_t &attributes,
00239                    const char *name,
00240                    void *arg)
00241 {
00242   // ACE_OS_TRACE ("ACE_OS::cond_init");
00243   ACE_UNUSED_ARG (name);
00244   ACE_UNUSED_ARG (arg);
00245 # if defined (ACE_HAS_THREADS)
00246 #   if defined (ACE_HAS_PTHREADS)
00247   int result = -1;
00248 
00249 #     if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
00250   /* VxWorks 6.x API reference states:
00251    *   If the memory for the condition variable object has been allocated
00252    *   dynamically, it is a good policy to always zero out the
00253    *   block of memory so as to avoid spurious EBUSY return code
00254    *   when calling this routine.
00255    */
00256   ACE_OS::memset (cv, 0, sizeof (*cv));
00257 #     endif
00258 
00259   if (ACE_ADAPT_RETVAL (pthread_cond_init (cv, &attributes), result) == 0)
00260      result = 0;
00261   else
00262      result = -1;       // ACE_ADAPT_RETVAL used it for intermediate status
00263 
00264   return result;
00265 #   elif defined (ACE_HAS_STHREADS)
00266   int result;
00267   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_init (cv,
00268                                                     attributes.type,
00269                                                     arg),
00270                                        result),
00271                      int, -1);
00272 #   endif /* ACE_HAS_PTHREADS vs. ACE_HAS_STHREADS */
00273 # else
00274   ACE_UNUSED_ARG (cv);
00275   ACE_UNUSED_ARG (attributes);
00276   ACE_UNUSED_ARG (name);
00277   ACE_UNUSED_ARG (arg);
00278   ACE_NOTSUP_RETURN (-1);
00279 # endif /* ACE_HAS_THREADS */
00280 }
00281 
00282 #if defined (ACE_HAS_WCHAR)
00283 ACE_INLINE int
00284 ACE_OS::cond_init (ACE_cond_t *cv,
00285                    ACE_condattr_t &attributes,
00286                    const wchar_t *name,
00287                    void *arg)
00288 {
00289   return ACE_OS::cond_init (cv, attributes, ACE_Wide_To_Ascii (name).char_rep (), arg);
00290 }
00291 #endif /* ACE_HAS_WCHAR */
00292 
00293 #if defined (ACE_HAS_WCHAR)
00294 ACE_INLINE int
00295 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
00296 {
00297   return ACE_OS::cond_init (cv, type, ACE_Wide_To_Ascii (name).char_rep (), arg);
00298 }
00299 #endif /* ACE_HAS_WCHAR */
00300 
00301 ACE_INLINE int
00302 ACE_OS::cond_signal (ACE_cond_t *cv)
00303 {
00304   ACE_OS_TRACE ("ACE_OS::cond_signal");
00305 # if defined (ACE_HAS_THREADS)
00306 #   if defined (ACE_HAS_PTHREADS)
00307   int result;
00308   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_signal (cv), result),
00309                      int, -1);
00310 #   elif defined (ACE_HAS_STHREADS)
00311   int result;
00312   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_signal (cv), result), int, -1);
00313 #   endif /* ACE_HAS_STHREADS */
00314 # else
00315   ACE_UNUSED_ARG (cv);
00316   ACE_NOTSUP_RETURN (-1);
00317 # endif /* ACE_HAS_THREADS */
00318 }
00319 
00320 ACE_INLINE int
00321 ACE_OS::cond_wait (ACE_cond_t *cv,
00322                    ACE_mutex_t *external_mutex)
00323 {
00324   ACE_OS_TRACE ("ACE_OS::cond_wait");
00325 # if defined (ACE_HAS_THREADS)
00326 #   if defined (ACE_HAS_PTHREADS)
00327   int result;
00328   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cond_wait (cv, external_mutex), result),
00329                      int, -1);
00330 #   elif defined (ACE_HAS_STHREADS)
00331   int result;
00332   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::cond_wait (cv, external_mutex), result),
00333                      int, -1);
00334 #   endif /* ACE_HAS_PTHREADS */
00335 # else
00336   ACE_UNUSED_ARG (cv);
00337   ACE_UNUSED_ARG (external_mutex);
00338   ACE_NOTSUP_RETURN (-1);
00339 # endif /* ACE_HAS_THREADS */
00340 }
00341 
00342 ACE_INLINE int
00343 ACE_OS::cond_timedwait (ACE_cond_t *cv,
00344                         ACE_mutex_t *external_mutex,
00345                         ACE_Time_Value *timeout)
00346 {
00347   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
00348 # if defined (ACE_HAS_THREADS)
00349   int result;
00350   timespec_t ts;
00351 
00352   if (timeout != 0)
00353     ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
00354 
00355 #   if defined (ACE_HAS_PTHREADS)
00356 
00357   ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
00358                                 ? pthread_cond_wait (cv, external_mutex)
00359                                 : pthread_cond_timedwait (cv, external_mutex,
00360                                                             (ACE_TIMESPEC_PTR) &ts),
00361                                 result),
00362               int, -1, result);
00363   // We need to adjust this to make the POSIX and Solaris return
00364   // values consistent.  EAGAIN is from Pthreads DRAFT4 (HP-UX 10.20 and down)
00365   if (result == -1 &&
00366       (errno == ETIMEDOUT || errno == EAGAIN))
00367     errno = ETIME;
00368 
00369 #   elif defined (ACE_HAS_STHREADS)
00370   ACE_OSCALL (ACE_ADAPT_RETVAL (timeout == 0
00371                                 ? ::cond_wait (cv, external_mutex)
00372                                 : ::cond_timedwait (cv,
00373                                                     external_mutex,
00374                                                     (timestruc_t*)&ts),
00375                                 result),
00376               int, -1, result);
00377 #   endif /* ACE_HAS_STHREADS */
00378   if (timeout != 0)
00379     timeout->set (ts); // Update the time value before returning.
00380 
00381   return result;
00382 # else
00383   ACE_UNUSED_ARG (cv);
00384   ACE_UNUSED_ARG (external_mutex);
00385   ACE_UNUSED_ARG (timeout);
00386   ACE_NOTSUP_RETURN (-1);
00387 # endif /* ACE_HAS_THREADS */
00388 }
00389 #endif /* !ACE_LACKS_COND_T */
00390 
00391 ACE_INLINE int
00392 ACE_OS::mutex_lock (ACE_mutex_t *m,
00393                     const ACE_Time_Value *timeout)
00394 {
00395   return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout);
00396 }
00397 
00398 #if defined (ACE_HAS_WCHAR)
00399 ACE_INLINE int
00400 ACE_OS::event_init (ACE_event_t *event,
00401                     int manual_reset,
00402                     int initial_state,
00403                     int type,
00404                     const wchar_t *name,
00405                     void *arg,
00406                     LPSECURITY_ATTRIBUTES sa)
00407 {
00408 #if defined (ACE_WIN32)
00409   ACE_UNUSED_ARG (type);
00410   ACE_UNUSED_ARG (arg);
00411   SECURITY_ATTRIBUTES sa_buffer;
00412   SECURITY_DESCRIPTOR sd_buffer;
00413   *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
00414       (sa, &sa_buffer, &sd_buffer),
00415   manual_reset,
00416   initial_state,
00417   name);
00418   if (*event == 0)
00419     ACE_FAIL_RETURN (-1);
00420 
00421   return 0;
00422 #else  /* ACE_WIN32 */
00423   return ACE_OS::event_init (event,
00424                              manual_reset,
00425                              initial_state,
00426                              type,
00427                              ACE_Wide_To_Ascii (name).char_rep (),
00428                              arg,
00429                              sa);
00430 #endif /* ACE_WIN32 */
00431 }
00432 #endif /* ACE_HAS_WCHAR */
00433 
00434 ACE_INLINE long
00435 ACE_OS::priority_control (ACE_idtype_t idtype, ACE_id_t identifier, int cmd, void *arg)
00436 {
00437   ACE_OS_TRACE ("ACE_OS::priority_control");
00438 #if defined (ACE_HAS_PRIOCNTL)
00439   ACE_OSCALL_RETURN (priocntl (idtype, identifier, cmd, static_cast<caddr_t> (arg)),
00440                      long, -1);
00441 #else  /* ! ACE_HAS_PRIOCNTL*/
00442   ACE_UNUSED_ARG (idtype);
00443   ACE_UNUSED_ARG (identifier);
00444   ACE_UNUSED_ARG (cmd);
00445   ACE_UNUSED_ARG (arg);
00446   ACE_NOTSUP_RETURN (-1);
00447 #endif /* ! ACE_HAS_PRIOCNTL*/
00448 }
00449 
00450 // This method is used to prepare the recursive mutex for releasing
00451 // when waiting on a condition variable. If the platform doesn't have
00452 // native recursive mutex and condition variable support, then ACE needs
00453 // to save the recursion state around the wait and also ensure that the
00454 // wait and lock release are atomic. recursive_mutex_cond_relock()
00455 // is the inverse of this method.
00456 ACE_INLINE int
00457 ACE_OS::recursive_mutex_cond_unlock (ACE_recursive_thread_mutex_t *m,
00458                                      ACE_recursive_mutex_state &state)
00459 {
00460 #if defined (ACE_HAS_THREADS)
00461   ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_unlock");
00462 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
00463   // Windows need special handling since it has recursive mutexes, but
00464   // does not integrate them into a condition variable.
00465 #    if defined (ACE_WIN32)
00466   // For Windows, the OS takes care of the mutex and its recursion. We just
00467   // need to release the lock one fewer times than this thread has acquired
00468   // it. Remember how many times, and reacquire it that many more times when
00469   // the condition is signaled.
00470   //
00471   // For WinCE, the situation is a bit trickier. CE doesn't have
00472   // RecursionCount, and LockCount has changed semantics over time.
00473   // In CE 3 (and maybe 4?) LockCount is not an indicator of recursion;
00474   // instead, see when it's unlocked by watching the OwnerThread, which will
00475   // change to something other than the current thread when it's been
00476   // unlocked "enough" times. Note that checking for 0 (unlocked) is not
00477   // sufficient. Another thread may acquire the lock between our unlock and
00478   // checking the OwnerThread. So grab our thread ID value first, then
00479   // compare to it in the loop condition. NOTE - the problem with this
00480   // scheme is that we really want to unlock the mutex one _less_ times than
00481   // required to release it for another thread to acquire. With CE 5 we
00482   // can do this by watching LockCount alone. I _think_ it can be done by
00483   // watching LockCount on CE 4 as well (though its meaning is different),
00484   // but I'm leary of changing this code since a user reported success
00485   // with it.
00486   //
00487   // We're using undocumented fields in the CRITICAL_SECTION structure
00488   // and they've been known to change across Windows variants and versions./
00489   // So be careful if you need to change these - there may be other
00490   // Windows variants that depend on existing values and limits.
00491 #      if defined (ACE_HAS_WINCE) && (UNDER_CE < 500)
00492   ACE_thread_t me = ACE_OS::thr_self ();
00493 #      endif /* ACE_HAS_WINCE && CE 4 or earlier */
00494 
00495   state.relock_count_ = 0;
00496   while (
00497 #      if !defined (ACE_HAS_WINCE)
00498          m->LockCount > 0 && m->RecursionCount > 1
00499 #      else
00500          // WinCE doesn't have RecursionCount and the LockCount semantic
00501          // has changed between versions; pre-Mobile 5 the LockCount
00502          // was 0-indexed, and Mobile 5 has it 1-indexed.
00503 #        if (UNDER_CE < 500)
00504          m->LockCount > 0 && m->OwnerThread == (HANDLE)me
00505 #        else
00506          m->LockCount > 1
00507 #        endif /* UNDER_CE < 500 */
00508 #      endif /* ACE_HAS_WINCE */
00509          )
00510     {
00511       // This may fail if the current thread doesn't own the mutex. If it
00512       // does fail, it'll be on the first try, so don't worry about resetting
00513       // the state.
00514       if (ACE_OS::recursive_mutex_unlock (m) == -1)
00515         return -1;
00516       ++state.relock_count_;
00517     }
00518 #    else /* not ACE_WIN32 */
00519     // prevent warnings for unused variables
00520     ACE_UNUSED_ARG (state);
00521     ACE_UNUSED_ARG (m);
00522 #    endif /* ACE_WIN32 */
00523   return 0;
00524 #  else /* ACE_HAS_RECURSIVE_MUTEXES */
00525   // For platforms without recursive mutexes, we obtain the nesting mutex
00526   // to gain control over the mutex internals. Then set the internals to say
00527   // the mutex is available. If there are waiters, signal the condition
00528   // to notify them (this is mostly like the recursive_mutex_unlock() method).
00529   // Then, return with the nesting mutex still held. The condition wait
00530   // will release it atomically, allowing mutex waiters to continue.
00531   // Note that this arrangement relies on the fact that on return from
00532   // the condition wait, this thread will again own the nesting mutex
00533   // and can either set the mutex internals directly or get in line for
00534   // the mutex... this part is handled in recursive_mutex_cond_relock().
00535   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
00536     return -1;
00537 
00538 #    if !defined (ACE_NDEBUG)
00539   if (m->nesting_level_ == 0
00540       || ACE_OS::thr_equal (ACE_OS::thr_self (), m->owner_id_) == 0)
00541     {
00542       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00543       errno = EINVAL;
00544       return -1;
00545     }
00546 #    endif /* ACE_NDEBUG */
00547 
00548   // To make error recovery a bit easier, signal the condition now. Any
00549   // waiter won't regain control until the mutex is released, which won't
00550   // be until the caller returns and does the wait on the condition.
00551   if (ACE_OS::cond_signal (&m->lock_available_) == -1)
00552     {
00553       // Save/restore errno.
00554       ACE_Errno_Guard error (errno);
00555       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00556       return -1;
00557     }
00558 
00559   // Ok, the nesting_mutex_ lock is still held, the condition has been
00560   // signaled... reset the nesting info and return _WITH_ the lock
00561   // held. The lock will be released when the condition waits, in the
00562   // caller.
00563   state.nesting_level_ = m->nesting_level_;
00564   state.owner_id_ = m->owner_id_;
00565   m->nesting_level_ = 0;
00566   m->owner_id_ = ACE_OS::NULL_thread;
00567   return 0;
00568 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
00569 #else
00570   ACE_UNUSED_ARG (m);
00571   ACE_UNUSED_ARG (state);
00572   ACE_NOTSUP_RETURN (-1);
00573 #endif /* ACE_HAS_THREADS */
00574 }
00575 
00576 
00577 // This method is called after waiting on a condition variable when a
00578 // recursive mutex must be reacquired. If the platform doesn't natively
00579 // integrate recursive mutexes and condition variables, it's taken care
00580 // of here (inverse of ACE_OS::recursive_mutex_cond_unlock).
00581 ACE_INLINE void
00582 ACE_OS::recursive_mutex_cond_relock (ACE_recursive_thread_mutex_t *m,
00583                                      ACE_recursive_mutex_state &state)
00584 {
00585 #if defined (ACE_HAS_THREADS)
00586   ACE_OS_TRACE ("ACE_OS::recursive_mutex_cond_relock");
00587 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
00588   // Windows need special handling since it has recursive mutexes, but
00589   // does not integrate them into a condition variable.
00590   // On entry, the OS has already reacquired the lock for us. Just
00591   // reacquire it the proper number of times so the recursion is the same as
00592   // before waiting on the condition.
00593 #    if defined (ACE_WIN32)
00594   while (state.relock_count_ > 0)
00595     {
00596       ACE_OS::recursive_mutex_lock (m);
00597       --state.relock_count_;
00598     }
00599   return;
00600 #    else /* not ACE_WIN32 */
00601     // prevent warnings for unused variables
00602     ACE_UNUSED_ARG (state);
00603     ACE_UNUSED_ARG (m);
00604 
00605 #    endif /* ACE_WIN32 */
00606 #  else
00607   // Without recursive mutex support, it's somewhat trickier. On entry,
00608   // the current thread holds the nesting_mutex_, but another thread may
00609   // still be holding the ACE_recursive_mutex_t. If so, mimic the code
00610   // in ACE_OS::recursive_mutex_lock that waits to acquire the mutex.
00611   // After acquiring it, restore the nesting counts and release the
00612   // nesting mutex. This will restore the conditions to what they were
00613   // before calling ACE_OS::recursive_mutex_cond_unlock().
00614   while (m->nesting_level_ > 0)
00615     ACE_OS::cond_wait (&m->lock_available_, &m->nesting_mutex_);
00616 
00617   // At this point, we still have nesting_mutex_ and the mutex is free.
00618   m->nesting_level_ = state.nesting_level_;
00619   m->owner_id_ = state.owner_id_;
00620   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00621   return;
00622 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
00623 #else
00624   ACE_UNUSED_ARG (m);
00625   ACE_UNUSED_ARG (state);
00626   return;
00627 #endif /* ACE_HAS_THREADS */
00628 }
00629 
00630 ACE_INLINE int
00631 ACE_OS::recursive_mutex_destroy (ACE_recursive_thread_mutex_t *m)
00632 {
00633 #if defined (ACE_HAS_THREADS)
00634 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
00635   return ACE_OS::thread_mutex_destroy (m);
00636 #else
00637   if (ACE_OS::thread_mutex_destroy (&m->nesting_mutex_) == -1)
00638     return -1;
00639   else if (ACE_OS::cond_destroy (&m->lock_available_) == -1)
00640     return -1;
00641   else
00642     return 0;
00643 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
00644 #else
00645   ACE_UNUSED_ARG (m);
00646   ACE_NOTSUP_RETURN (-1);
00647 #endif /* ACE_HAS_THREADS */
00648 }
00649 
00650 ACE_INLINE int
00651 ACE_OS::recursive_mutex_init (ACE_recursive_thread_mutex_t *m,
00652                               const ACE_TCHAR *name,
00653                               ACE_mutexattr_t *arg,
00654                               LPSECURITY_ATTRIBUTES sa)
00655 {
00656   ACE_UNUSED_ARG (sa);
00657 #if defined (ACE_HAS_THREADS)
00658 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
00659 #    if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
00660   return ACE_OS::thread_mutex_init (m, PTHREAD_MUTEX_RECURSIVE, name, arg);
00661 #    else
00662   return ACE_OS::thread_mutex_init (m, 0, name, arg);
00663 #    endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
00664 #  else
00665   if (ACE_OS::thread_mutex_init (&m->nesting_mutex_, 0, name, arg) == -1)
00666     return -1;
00667   else if (ACE_OS::cond_init (&m->lock_available_,
00668                               (short) USYNC_THREAD,
00669                               name,
00670                               0) == -1)
00671     return -1;
00672   else
00673     {
00674       m->nesting_level_ = 0;
00675       m->owner_id_ = ACE_OS::NULL_thread;
00676       return 0;
00677     }
00678 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
00679 #else
00680   ACE_UNUSED_ARG (m);
00681   ACE_UNUSED_ARG (name);
00682   ACE_UNUSED_ARG (arg);
00683   ACE_NOTSUP_RETURN (-1);
00684 #endif /* ACE_HAS_THREADS */
00685 }
00686 
00687 ACE_INLINE int
00688 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m)
00689 {
00690 #if defined (ACE_HAS_THREADS)
00691 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
00692   return ACE_OS::thread_mutex_lock (m);
00693 #else
00694   ACE_thread_t const t_id = ACE_OS::thr_self ();
00695   int result = 0;
00696 
00697   // Acquire the guard.
00698   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
00699     result = -1;
00700   else
00701   {
00702     // If there's no contention, just grab the lock immediately
00703     // (since this is the common case we'll optimize for it).
00704     if (m->nesting_level_ == 0)
00705       m->owner_id_ = t_id;
00706       // If we already own the lock, then increment the nesting level
00707       // and return.
00708     else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
00709     {
00710           // Wait until the nesting level has dropped to zero, at
00711           // which point we can acquire the lock.
00712       while (m->nesting_level_ > 0)
00713         ACE_OS::cond_wait (&m->lock_available_,
00714                             &m->nesting_mutex_);
00715 
00716           // At this point the nesting_mutex_ is held...
00717       m->owner_id_ = t_id;
00718     }
00719 
00720     // At this point, we can safely increment the nesting_level_ no
00721     // matter how we got here!
00722     ++m->nesting_level_;
00723   }
00724 
00725   {
00726     // Save/restore errno.
00727     ACE_Errno_Guard error (errno);
00728     ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00729   }
00730   return result;
00731 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
00732 #else
00733   ACE_UNUSED_ARG (m);
00734   ACE_NOTSUP_RETURN (-1);
00735 #endif /* ACE_HAS_THREADS */
00736 }
00737 
00738 ACE_INLINE int
00739 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
00740                               const ACE_Time_Value &timeout)
00741 {
00742 #if defined (ACE_HAS_THREADS)
00743 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
00744   return ACE_OS::thread_mutex_lock (m, timeout);
00745 #else
00746   ACE_thread_t t_id = ACE_OS::thr_self ();
00747   int result = 0;
00748 
00749   // Try to acquire the guard.
00750   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_, timeout) == -1)
00751     result = -1;
00752   else
00753     {
00754       // If there's no contention, just grab the lock immediately
00755       // (since this is the common case we'll optimize for it).
00756       if (m->nesting_level_ == 0)
00757         m->owner_id_ = t_id;
00758       // If we already own the lock, then increment the nesting level
00759       // and return.
00760       else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
00761         {
00762           // Wait until the nesting level has dropped to zero, at
00763           // which point we can acquire the lock.
00764           while (m->nesting_level_ > 0)
00765             {
00766               result = ACE_OS::cond_timedwait (&m->lock_available_,
00767                                                &m->nesting_mutex_,
00768                                                const_cast <ACE_Time_Value *> (&timeout));
00769 
00770               // The mutex is reacquired even in the case of a timeout
00771               // release the mutex to prevent a deadlock
00772               if (result == -1)
00773                 {
00774                   // Save/restore errno.
00775                   ACE_Errno_Guard error (errno);
00776                   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00777 
00778                   return result;
00779                 }
00780             }
00781 
00782           // At this point the nesting_mutex_ is held...
00783           m->owner_id_ = t_id;
00784         }
00785 
00786       // At this point, we can safely increment the nesting_level_ no
00787       // matter how we got here!
00788       m->nesting_level_++;
00789 
00790       // Save/restore errno.
00791       ACE_Errno_Guard error (errno);
00792       ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00793     }
00794   return result;
00795 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
00796 #else
00797   ACE_UNUSED_ARG (m);
00798   ACE_UNUSED_ARG (timeout);
00799   ACE_NOTSUP_RETURN (-1);
00800 #endif /* ACE_HAS_THREADS */
00801 }
00802 
00803 ACE_INLINE int
00804 ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m,
00805                               const ACE_Time_Value *timeout)
00806 {
00807   return timeout == 0
00808     ? ACE_OS::recursive_mutex_lock (m)
00809     : ACE_OS::recursive_mutex_lock (m, *timeout);
00810 }
00811 
00812 ACE_INLINE int
00813 ACE_OS::recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m)
00814 {
00815 #if defined (ACE_HAS_THREADS)
00816 #if defined (ACE_HAS_RECURSIVE_MUTEXES)
00817   return ACE_OS::thread_mutex_trylock (m);
00818 #else
00819   ACE_thread_t t_id = ACE_OS::thr_self ();
00820   int result = 0;
00821 
00822   // Acquire the guard.
00823   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
00824     result = -1;
00825   else
00826   {
00827       // If there's no contention, just grab the lock immediately.
00828     if (m->nesting_level_ == 0)
00829     {
00830       m->owner_id_ = t_id;
00831       m->nesting_level_ = 1;
00832     }
00833       // If we already own the lock, then increment the nesting level
00834       // and proceed.
00835     else if (ACE_OS::thr_equal (t_id, m->owner_id_))
00836       m->nesting_level_++;
00837     else
00838     {
00839       errno = EBUSY;
00840       result = -1;
00841     }
00842   }
00843 
00844   {
00845     // Save/restore errno.
00846     ACE_Errno_Guard error (errno);
00847     ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00848   }
00849   return result;
00850 #endif /* ACE_HAS_RECURSIVE_MUTEXES */
00851 #else
00852   ACE_UNUSED_ARG (m);
00853   ACE_NOTSUP_RETURN (-1);
00854 #endif /* ACE_HAS_THREADS */
00855 }
00856 
00857 ACE_INLINE int
00858 ACE_OS::recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m)
00859 {
00860 #if defined (ACE_HAS_THREADS)
00861 #  if defined (ACE_HAS_RECURSIVE_MUTEXES)
00862   return ACE_OS::thread_mutex_unlock (m);
00863 #  else
00864   ACE_OS_TRACE ("ACE_OS::recursive_mutex_unlock");
00865 #    if !defined (ACE_NDEBUG)
00866   ACE_thread_t t_id = ACE_OS::thr_self ();
00867 #    endif /* ACE_NDEBUG */
00868   int result = 0;
00869 
00870   if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1)
00871     result = -1;
00872   else
00873   {
00874 #    if !defined (ACE_NDEBUG)
00875       if (m->nesting_level_ == 0
00876           || ACE_OS::thr_equal (t_id, m->owner_id_) == 0)
00877 {
00878   errno = EINVAL;
00879   result = -1;
00880 }
00881       else
00882 #    endif /* ACE_NDEBUG */
00883 {
00884   m->nesting_level_--;
00885   if (m->nesting_level_ == 0)
00886   {
00887               // This may not be strictly necessary, but it does put
00888               // the mutex into a known state...
00889     m->owner_id_ = ACE_OS::NULL_thread;
00890 
00891               // Inform a waiter that the lock is free.
00892     if (ACE_OS::cond_signal (&m->lock_available_) == -1)
00893       result = -1;
00894   }
00895 }
00896   }
00897 
00898 {
00899     // Save/restore errno.
00900   ACE_Errno_Guard error (errno);
00901   ACE_OS::thread_mutex_unlock (&m->nesting_mutex_);
00902 }
00903   return result;
00904 #  endif /* ACE_HAS_RECURSIVE_MUTEXES */
00905 #else
00906   ACE_UNUSED_ARG (m);
00907   ACE_NOTSUP_RETURN (-1);
00908 #endif /* ACE_HAS_THREADS */
00909 }
00910 
00911 ACE_INLINE int
00912 ACE_OS::rw_rdlock (ACE_rwlock_t *rw)
00913 {
00914   ACE_OS_TRACE ("ACE_OS::rw_rdlock");
00915 #if defined (ACE_HAS_THREADS)
00916 # if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
00917 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
00918   int result;
00919   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_rdlock (rw),
00920                                        result),
00921                      int, -1);
00922 #  else /* Solaris */
00923   int result;
00924   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_rdlock (rw), result), int, -1);
00925 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
00926 # else /* NT, POSIX, and VxWorks don't support this natively. */
00927 #   if defined (ACE_HAS_PTHREADS)
00928   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
00929 #   endif /* ACE_HAS_PTHREADS */
00930   int result = 0;
00931   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
00932     result = -1; // -1 means didn't get the mutex.
00933   else
00934     {
00935       // Give preference to writers who are waiting.
00936       while (rw->ref_count_ < 0 || rw->num_waiting_writers_ > 0)
00937         {
00938           rw->num_waiting_readers_++;
00939           if (ACE_OS::cond_wait (&rw->waiting_readers_, &rw->lock_) == -1)
00940             {
00941               result = -2; // -2 means that we need to release the mutex.
00942               break;
00943             }
00944           rw->num_waiting_readers_--;
00945         }
00946     }
00947   if (result == 0)
00948     rw->ref_count_++;
00949   if (result != -1)
00950     ACE_OS::mutex_unlock (&rw->lock_);
00951 #   if defined (ACE_HAS_PTHREADS)
00952   ACE_PTHREAD_CLEANUP_POP (0);
00953 #   endif /* defined (ACE_HAS_PTHREADS) */
00954   return 0;
00955 # endif /* ! ACE_LACKS_RWLOCK_T */
00956 #else
00957   ACE_UNUSED_ARG (rw);
00958   ACE_NOTSUP_RETURN (-1);
00959 #endif /* ACE_HAS_THREADS */
00960 }
00961 
00962 ACE_INLINE int
00963 ACE_OS::rw_tryrdlock (ACE_rwlock_t *rw)
00964 {
00965   ACE_OS_TRACE ("ACE_OS::rw_tryrdlock");
00966 #if defined (ACE_HAS_THREADS)
00967 # if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
00968 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
00969   int result;
00970   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_tryrdlock (rw),
00971                                        result),
00972                      int, -1);
00973 #  else /* Solaris */
00974   int result;
00975   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_tryrdlock (rw), result), int, -1);
00976 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
00977 # else /* NT, POSIX, and VxWorks don't support this natively. */
00978   int result = -1;
00979 
00980   if (ACE_OS::mutex_lock (&rw->lock_) != -1)
00981     {
00982       ACE_Errno_Guard error (errno);
00983 
00984       if (rw->ref_count_ == -1 || rw->num_waiting_writers_ > 0)
00985         {
00986           error = EBUSY;
00987           result = -1;
00988         }
00989       else
00990         {
00991           rw->ref_count_++;
00992           result = 0;
00993         }
00994 
00995       ACE_OS::mutex_unlock (&rw->lock_);
00996     }
00997   return result;
00998 # endif /* ! ACE_LACKS_RWLOCK_T */
00999 #else
01000   ACE_UNUSED_ARG (rw);
01001   ACE_NOTSUP_RETURN (-1);
01002 #endif /* ACE_HAS_THREADS */
01003 }
01004 
01005 ACE_INLINE int
01006 ACE_OS::rw_trywrlock (ACE_rwlock_t *rw)
01007 {
01008   ACE_OS_TRACE ("ACE_OS::rw_trywrlock");
01009 #if defined (ACE_HAS_THREADS)
01010 # if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01011 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01012   int result;
01013   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
01014                                        result),
01015                      int, -1);
01016 #  else /* Solaris */
01017   int result;
01018   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_trywrlock (rw), result), int, -1);
01019 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
01020 # else /* NT, POSIX, and VxWorks don't support this natively. */
01021   int result = -1;
01022 
01023   if (ACE_OS::mutex_lock (&rw->lock_) != -1)
01024     {
01025       ACE_Errno_Guard error (errno);
01026 
01027       if (rw->ref_count_ != 0)
01028         {
01029           error = EBUSY;
01030           result = -1;
01031         }
01032       else
01033         {
01034           rw->ref_count_ = -1;
01035           result = 0;
01036         }
01037 
01038       ACE_OS::mutex_unlock (&rw->lock_);
01039     }
01040   return result;
01041 # endif /* ! ACE_LACKS_RWLOCK_T */
01042 #else
01043   ACE_UNUSED_ARG (rw);
01044   ACE_NOTSUP_RETURN (-1);
01045 #endif /* ACE_HAS_THREADS */
01046 }
01047 
01048 // Note that the caller of this method *must* already possess this
01049 // lock as a read lock.
01050 // return {-1 and no errno set means: error,
01051 //         -1 and errno==EBUSY set means: could not upgrade,
01052 //         0 means: upgraded successfully}
01053 
01054 ACE_INLINE int
01055 ACE_OS::rw_trywrlock_upgrade (ACE_rwlock_t *rw)
01056 {
01057   ACE_OS_TRACE ("ACE_OS::rw_trywrlock_upgrade");
01058 #if defined (ACE_HAS_THREADS)
01059 # if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01060   // This will probably result in -1, EDEADLK, at least on HP-UX, but let it
01061   // go - it's a more descriptive error than ENOTSUP.
01062   int result;
01063   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_trywrlock (rw),
01064                                        result),
01065                      int, -1);
01066 # elif !defined (ACE_LACKS_RWLOCK_T)
01067   // Some native rwlocks, such as those on Solaris, don't
01068   // support the upgrade feature . . .
01069   ACE_UNUSED_ARG (rw);
01070   ACE_NOTSUP_RETURN (-1);
01071 # else /* NT, POSIX, and VxWorks don't support this natively. */
01072   // The ACE rwlock emulation does support upgrade . . .
01073   int result = 0;
01074 
01075 #   if defined (ACE_HAS_PTHREADS)
01076   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
01077 #   endif /* defined (ACE_HAS_PTHREADS) */
01078 
01079   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
01080     return -1;
01081     // -1 means didn't get the mutex, error
01082   else if (rw->important_writer_)
01083     // an other reader upgrades already
01084     {
01085       result = -1;
01086       errno = EBUSY;
01087     }
01088   else
01089     {
01090       while (rw->ref_count_ > 1) // wait until only I am left
01091         {
01092           rw->num_waiting_writers_++; // prohibit any more readers
01093           rw->important_writer_ = 1;
01094 
01095           if (ACE_OS::cond_wait (&rw->waiting_important_writer_, &rw->lock_) == -1)
01096             {
01097               result = -1;
01098               // we know that we have the lock again, we have this guarantee,
01099               // but something went wrong
01100             }
01101           rw->important_writer_ = 0;
01102           rw->num_waiting_writers_--;
01103         }
01104       if (result == 0)
01105         {
01106           // nothing bad happend
01107           rw->ref_count_ = -1;
01108           // now I am a writer
01109           // everything is O.K.
01110         }
01111     }
01112 
01113   ACE_OS::mutex_unlock (&rw->lock_);
01114 
01115 #   if defined (ACE_HAS_PTHREADS)
01116   ACE_PTHREAD_CLEANUP_POP (0);
01117 #   endif /* defined (ACE_HAS_PTHREADS) */
01118 
01119   return result;
01120 
01121 # endif /* ! ACE_LACKS_RWLOCK_T */
01122 #else
01123   ACE_UNUSED_ARG (rw);
01124   ACE_NOTSUP_RETURN (-1);
01125 #endif /* ACE_HAS_THREADS */
01126 }
01127 
01128 ACE_INLINE int
01129 ACE_OS::rw_unlock (ACE_rwlock_t *rw)
01130 {
01131   ACE_OS_TRACE ("ACE_OS::rw_unlock");
01132 #if defined (ACE_HAS_THREADS)
01133 # if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01134 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01135   int result;
01136   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_unlock (rw),
01137                                        result),
01138                      int, -1);
01139 #  else /* Solaris */
01140   int result;
01141   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_unlock (rw), result), int, -1);
01142 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
01143 # else /* NT, POSIX, and VxWorks don't support this natively. */
01144   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
01145     return -1;
01146 
01147   if (rw->ref_count_ > 0) // Releasing a reader.
01148     rw->ref_count_--;
01149   else if (rw->ref_count_ == -1) // Releasing a writer.
01150     rw->ref_count_ = 0;
01151   else
01152     {
01153       (void) ACE_OS::mutex_unlock (&rw->lock_);
01154       return -1; // @@ ACE_ASSERT (!"count should not be 0!\n");
01155     }
01156 
01157   int result = 0;
01158   ACE_Errno_Guard error (errno);
01159 
01160   if (rw->important_writer_ && rw->ref_count_ == 1)
01161     // only the reader requesting to upgrade its lock is left over.
01162     {
01163       result = ACE_OS::cond_signal (&rw->waiting_important_writer_);
01164       error = errno;
01165     }
01166   else if (rw->num_waiting_writers_ > 0 && rw->ref_count_ == 0)
01167     // give preference to writers over readers...
01168     {
01169       result = ACE_OS::cond_signal (&rw->waiting_writers_);
01170       error =  errno;
01171     }
01172   else if (rw->num_waiting_readers_ > 0 && rw->num_waiting_writers_ == 0)
01173     {
01174       result = ACE_OS::cond_broadcast (&rw->waiting_readers_);
01175       error = errno;
01176     }
01177 
01178   (void) ACE_OS::mutex_unlock (&rw->lock_);
01179   return result;
01180 # endif /* ! ace_lacks_rwlock_t */
01181 #else
01182   ACE_UNUSED_ARG (rw);
01183   ACE_NOTSUP_RETURN (-1);
01184 #endif /* ace_has_threads */
01185 }
01186 
01187 ACE_INLINE int
01188 ACE_OS::rw_wrlock (ACE_rwlock_t *rw)
01189 {
01190   ACE_OS_TRACE ("ACE_OS::rw_wrlock");
01191 #if defined (ACE_HAS_THREADS)
01192 # if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01193 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01194   int result;
01195   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_wrlock (rw),
01196                                        result),
01197                      int, -1);
01198 #  else /* Solaris */
01199   int result;
01200   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rw_wrlock (rw), result), int, -1);
01201 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
01202 # else /* NT, POSIX, and VxWorks don't support this natively. */
01203 #   if defined (ACE_HAS_PTHREADS)
01204   ACE_PTHREAD_CLEANUP_PUSH (&rw->lock_);
01205 #   endif /* defined (ACE_HAS_PTHREADS) */
01206   int result = 0;
01207 
01208   if (ACE_OS::mutex_lock (&rw->lock_) == -1)
01209     result = -1; // -1 means didn't get the mutex.
01210   else
01211     {
01212       while (rw->ref_count_ != 0)
01213         {
01214           rw->num_waiting_writers_++;
01215 
01216           if (ACE_OS::cond_wait (&rw->waiting_writers_, &rw->lock_) == -1)
01217             {
01218               result = -2; // -2 means we need to release the mutex.
01219               break;
01220             }
01221 
01222           rw->num_waiting_writers_--;
01223         }
01224     }
01225   if (result == 0)
01226     rw->ref_count_ = -1;
01227   if (result != -1)
01228     ACE_OS::mutex_unlock (&rw->lock_);
01229 #   if defined (ACE_HAS_PTHREADS)
01230   ACE_PTHREAD_CLEANUP_POP (0);
01231 #   endif /* defined (ACE_HAS_PTHREADS) */
01232   return 0;
01233 # endif /* ! ACE_LACKS_RWLOCK_T */
01234 #else
01235   ACE_UNUSED_ARG (rw);
01236   ACE_NOTSUP_RETURN (-1);
01237 #endif /* ACE_HAS_THREADS */
01238 }
01239 
01240 ACE_INLINE int
01241 ACE_OS::rwlock_destroy (ACE_rwlock_t *rw)
01242 {
01243   ACE_OS_TRACE ("ACE_OS::rwlock_destroy");
01244 #if defined (ACE_HAS_THREADS)
01245 # if !defined (ACE_LACKS_RWLOCK_T) || defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01246 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01247   int result;
01248   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_rwlock_destroy (rw),
01249                                        result),
01250                      int, -1);
01251 #  else /* Solaris */
01252   int result;
01253   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_destroy (rw), result), int, -1);
01254 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
01255 # else /* NT, POSIX, and VxWorks don't support this natively. */
01256   ACE_OS::mutex_destroy (&rw->lock_);
01257   ACE_OS::cond_destroy (&rw->waiting_readers_);
01258   ACE_OS::cond_destroy (&rw->waiting_important_writer_);
01259   return ACE_OS::cond_destroy (&rw->waiting_writers_);
01260 # endif /* ACE_HAS_STHREADS && !defined (ACE_LACKS_RWLOCK_T) */
01261 #else
01262   ACE_UNUSED_ARG (rw);
01263   ACE_NOTSUP_RETURN (-1);
01264 #endif /* ACE_HAS_THREADS */
01265 }
01266 
01267 #if defined (ACE_HAS_THREADS) && (!defined (ACE_LACKS_RWLOCK_T) || \
01268                                    defined (ACE_HAS_PTHREADS_UNIX98_EXT))
01269 ACE_INLINE int
01270 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
01271                      int type,
01272                      const ACE_TCHAR *name,
01273                      void *arg)
01274 {
01275   // ACE_OS_TRACE ("ACE_OS::rwlock_init");
01276 #  if defined (ACE_HAS_PTHREADS_UNIX98_EXT)
01277   ACE_UNUSED_ARG (name);
01278   ACE_UNUSED_ARG (arg);
01279 
01280   int status;
01281   pthread_rwlockattr_t attr;
01282   pthread_rwlockattr_init (&attr);
01283 #    if !defined (ACE_LACKS_RWLOCKATTR_PSHARED)
01284   pthread_rwlockattr_setpshared (&attr, (type == USYNC_THREAD ?
01285                                          PTHREAD_PROCESS_PRIVATE :
01286                                          PTHREAD_PROCESS_SHARED));
01287 #    else
01288   ACE_UNUSED_ARG (type);
01289 #    endif /* !ACE_LACKS_RWLOCKATTR_PSHARED */
01290   status = ACE_ADAPT_RETVAL (pthread_rwlock_init (rw, &attr), status);
01291   pthread_rwlockattr_destroy (&attr);
01292 
01293   return status;
01294 
01295 #  else
01296   type = type;
01297   name = name;
01298   int result;
01299   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::rwlock_init (rw, type, arg), result), int, -1);
01300 #  endif /* ACE_HAS_PTHREADS_UNIX98_EXT */
01301 }
01302 #endif /* ACE_HAS THREADS && !defined (ACE_LACKS_RWLOCK_T) */
01303 
01304 ACE_INLINE int
01305 ACE_OS::sema_destroy (ACE_sema_t *s)
01306 {
01307   ACE_OS_TRACE ("ACE_OS::sema_destroy");
01308 # if defined (ACE_HAS_POSIX_SEM)
01309   int result;
01310 #   if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
01311   ACE_OS::mutex_destroy (&s->lock_);
01312   ACE_OS::cond_destroy (&s->count_nonzero_);
01313 #   endif /* !ACE_HAS_POSIX_SEM_TIMEOUT && !ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
01314 #   if defined (ACE_LACKS_NAMED_POSIX_SEM)
01315   if (s->name_)
01316     {
01317       // Only destroy the semaphore if we're the ones who
01318       // initialized it.
01319       ACE_OSCALL (::sem_destroy (s->sema_),int, -1, result);
01320       ACE_OS::shm_unlink (s->name_);
01321       delete s->name_;
01322       return result;
01323     }
01324 #   else
01325   if (s->name_)
01326     {
01327       ACE_OSCALL (::sem_unlink (s->name_), int, -1, result);
01328       ACE_OS::free ((void *) s->name_);
01329       ACE_OSCALL_RETURN (::sem_close (s->sema_), int, -1);
01330     }
01331 #   endif /*  ACE_LACKS_NAMED_POSIX_SEM */
01332   else
01333     {
01334       ACE_OSCALL (::sem_destroy (s->sema_), int, -1, result);
01335 #   if defined (ACE_LACKS_NAMED_POSIX_SEM)
01336       if (s->new_sema_)
01337 #   endif /* ACE_LACKS_NAMED_POSIX_SEM */
01338         delete s->sema_;
01339       s->sema_ = 0;
01340       return result;
01341     }
01342 # elif defined (ACE_USES_FIFO_SEM)
01343   int r0 = 0;
01344   if (s->name_)
01345     {
01346       r0 = ACE_OS::unlink (s->name_);
01347       ACE_OS::free (s->name_);
01348       s->name_ = 0;
01349     }
01350   int r1 = ACE_OS::close (s->fd_[0]);      /* ignore error */
01351   int r2 = ACE_OS::close (s->fd_[1]);      /* ignore error */
01352   return r0 != 0 || r1 != 0 || r2 != 0 ? -1 : 0;
01353 # elif defined (ACE_HAS_THREADS)
01354 #   if defined (ACE_HAS_STHREADS)
01355   int result;
01356   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_destroy (s), result), int, -1);
01357 #   elif defined (ACE_HAS_PTHREADS)
01358   int r1 = ACE_OS::mutex_destroy (&s->lock_);
01359   int r2 = ACE_OS::cond_destroy (&s->count_nonzero_);
01360   return r1 != 0 || r2 != 0 ? -1 : 0;
01361 #   elif defined (ACE_HAS_WTHREADS)
01362 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
01363   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*s), ace_result_), int, -1);
01364 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
01365   // Free up underlying objects of the simulated semaphore.
01366   int r1 = ACE_OS::thread_mutex_destroy (&s->lock_);
01367   int r2 = ACE_OS::event_destroy (&s->count_nonzero_);
01368   return r1 != 0 || r2 != 0 ? -1 : 0;
01369 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01370 #   elif defined (ACE_VXWORKS)
01371   int result;
01372   ACE_OSCALL (::semDelete (s->sema_), int, -1, result);
01373   s->sema_ = 0;
01374   return result;
01375 #   endif /* ACE_HAS_STHREADS */
01376 # else
01377   ACE_UNUSED_ARG (s);
01378   ACE_NOTSUP_RETURN (-1);
01379 # endif /* ACE_HAS_POSIX_SEM */
01380 }
01381 
01382 // NOTE: The previous four function definitions must appear before
01383 // ACE_OS::sema_init ().
01384 
01385 ACE_INLINE int
01386 ACE_OS::sema_init (ACE_sema_t *s,
01387                    u_int count,
01388                    int type,
01389                    const char *name,
01390                    void *arg,
01391                    int max,
01392                    LPSECURITY_ATTRIBUTES sa)
01393 {
01394   ACE_OS_TRACE ("ACE_OS::sema_init");
01395 #if defined (ACE_HAS_POSIX_SEM)
01396   ACE_UNUSED_ARG (max);
01397   ACE_UNUSED_ARG (sa);
01398 
01399   s->name_ = 0;
01400 #  if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
01401   ACE_UNUSED_ARG (arg);
01402 #  else
01403   int result = -1;
01404 
01405   if (ACE_OS::mutex_init (&s->lock_, type, name,
01406                           (ACE_mutexattr_t *) arg) == 0
01407       && ACE_OS::cond_init (&s->count_nonzero_, (short)type, name, arg) == 0
01408       && ACE_OS::mutex_lock (&s->lock_) == 0)
01409     {
01410       if (ACE_OS::mutex_unlock (&s->lock_) == 0)
01411         result = 0;
01412     }
01413 
01414   if (result == -1)
01415     {
01416       ACE_OS::mutex_destroy (&s->lock_);
01417       ACE_OS::cond_destroy (&s->count_nonzero_);
01418       return result;
01419     }
01420 #  endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
01421 
01422 #  if defined (ACE_LACKS_NAMED_POSIX_SEM)
01423   s->new_sema_ = false;
01424   if (type == USYNC_PROCESS)
01425     {
01426       // Let's see if it already exists.
01427       ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
01428                                         O_RDWR | O_CREAT | O_EXCL,
01429                                         ACE_DEFAULT_FILE_PERMS);
01430       if (fd == ACE_INVALID_HANDLE)
01431         {
01432           if (errno == EEXIST)
01433             fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
01434                                    O_RDWR | O_CREAT,
01435                                    ACE_DEFAULT_FILE_PERMS);
01436           else
01437             return -1;
01438         }
01439       else
01440         {
01441           // We own this shared memory object!  Let's set its
01442           // size.
01443           if (ACE_OS::ftruncate (fd,
01444                                  sizeof (ACE_sema_t)) == -1)
01445             return -1;
01446           s->name_ = ACE_OS::strdup (name);
01447           if (s->name_ == 0)
01448             return -1;
01449         }
01450       if (fd == -1)
01451         return -1;
01452 
01453       s->sema_ = (sem_t *)
01454         ACE_OS::mmap (0,
01455                       sizeof (ACE_sema_t),
01456                       PROT_RDWR,
01457                       MAP_SHARED,
01458                       fd,
01459                       0);
01460       ACE_OS::close (fd);
01461       if (s->sema_ == (sem_t *) MAP_FAILED)
01462         return -1;
01463       if (s->name_
01464           // @@ According UNIX Network Programming V2 by Stevens,
01465           //    sem_init() is currently not required to return zero on
01466           //    success, but it *does* return -1 upon failure.  For
01467           //    this reason, check for failure by comparing to -1,
01468           //    instead of checking for success by comparing to zero.
01469           //        -Ossama
01470           // Only initialize it if we're the one who created it.
01471           && ::sem_init (s->sema_, type == USYNC_PROCESS, count) == -1)
01472         return -1;
01473       return 0;
01474     }
01475 #  else
01476   if (name)
01477     {
01478 #    if defined (sun) || defined (HPUX)
01479       // Solaris and HP-UX require the name to start with a slash. Solaris
01480       // further requires that there be no other slashes than the first.
01481       const char *last_slash = ACE_OS::strrchr (name, '/');
01482       char name2[MAXPATHLEN];
01483       if (0 == last_slash)
01484         {
01485           ACE_OS::strcpy (name2, "/");
01486           ACE_OS::strcat (name2, name);
01487           name = name2;
01488         }
01489 #      if defined (sun)
01490       else
01491         name = last_slash;         // Chop off chars preceding last slash
01492 #      endif /* sun */
01493 #    endif /* sun || HPUX */
01494 
01495       ACE_ALLOCATOR_RETURN (s->name_,
01496                             ACE_OS::strdup (name),
01497                             -1);
01498       s->sema_ = ::sem_open (s->name_,
01499                              O_CREAT,
01500                              ACE_DEFAULT_FILE_PERMS,
01501                              count);
01502       if (s->sema_ == (sem_t *) SEM_FAILED)
01503         return -1;
01504       else
01505         return 0;
01506     }
01507 #  endif /* ACE_LACKS_NAMED_POSIX_SEM */
01508   else
01509     {
01510       ACE_NEW_RETURN (s->sema_,
01511                       sem_t,
01512                       -1);
01513 #  if defined (ACE_LACKS_NAMED_POSIX_SEM)
01514       s->new_sema_ = true;
01515 #  endif /* ACE_LACKS_NAMED_POSIX_SEM */
01516       ACE_OSCALL_RETURN (::sem_init (s->sema_,
01517                                      type != USYNC_THREAD,
01518                                      count), int, -1);
01519     }
01520 
01521 #elif defined (ACE_USES_FIFO_SEM)
01522   ACE_UNUSED_ARG (arg);
01523   ACE_UNUSED_ARG (max);
01524   ACE_UNUSED_ARG (sa);
01525   int             flags = 0;
01526   mode_t          mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
01527 
01528   if (type == USYNC_THREAD)
01529     {
01530       // Create systemwide unique name for semaphore
01531       char   uname[ACE_UNIQUE_NAME_LEN];
01532       ACE_OS::unique_name ((const void *) s,
01533                             uname,
01534                             ACE_UNIQUE_NAME_LEN);
01535       name = &uname[0];
01536     }
01537 
01538   s->name_ = 0;
01539   s->fd_[0] = s->fd_[1] = ACE_INVALID_HANDLE;
01540   bool creator = false;
01541 
01542   if (ACE_OS::mkfifo (ACE_TEXT_CHAR_TO_TCHAR (name), mode) < 0)
01543     {
01544       if (errno != EEXIST)    /* already exists OK else ERR */
01545         return -1;
01546       // check if this is a real FIFO, not just some other existing file
01547       ACE_stat fs;
01548       if (ACE_OS::stat (name, &fs))
01549         return -1;
01550       if (!S_ISFIFO (fs.st_mode))
01551         {
01552           // existing file is not a FIFO
01553           errno = EEXIST;
01554           return -1;
01555         }
01556     }
01557     else
01558       creator = true; // remember we created it for initialization at end
01559 
01560   // for processshared semaphores remember who we are to be able to remove
01561   // the FIFO when we're done with it
01562   if (type == USYNC_PROCESS)
01563     {
01564       s->name_ = ACE_OS::strdup (name);
01565       if (s->name_ == 0)
01566         {
01567           if (creator)
01568             ACE_OS::unlink (name);
01569           return -1;
01570         }
01571     }
01572 
01573   if ((s->fd_[0] = ACE_OS::open (name, O_RDONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE
01574       || (s->fd_[1] = ACE_OS::open (name, O_WRONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE)
01575     return (-1);
01576 
01577   /* turn off nonblocking for fd_[0] */
01578   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
01579     return (-1);
01580 
01581   flags &= ~O_NONBLOCK;
01582   if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
01583     return (-1);
01584 
01585   //if (s->name_ && count)
01586   if (creator && count)
01587     {
01588       char    c = 1;
01589       for (u_int i=0; i<count ;++i)
01590         if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) != 1)
01591           return (-1);
01592     }
01593 
01594   // In the case of process scope semaphores we can already unlink the FIFO now that
01595   // we completely set it up (the opened handles will keep it active until we close
01596   // thos down). This way we're protected against unexpected crashes as far as removal
01597   // is concerned.
01598   // Unfortunately this does not work for processshared FIFOs since as soon as we
01599   // have unlinked the semaphore no other process will be able to open it anymore.
01600   if (type == USYNC_THREAD)
01601     {
01602       ACE_OS::unlink (name);
01603     }
01604 
01605   return (0);
01606 #elif defined (ACE_HAS_THREADS)
01607 #  if defined (ACE_HAS_STHREADS)
01608   ACE_UNUSED_ARG (name);
01609   ACE_UNUSED_ARG (max);
01610   ACE_UNUSED_ARG (sa);
01611   int result;
01612   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_init (s, count, type, arg), result),
01613                      int, -1);
01614 #  elif defined (ACE_HAS_PTHREADS)
01615   ACE_UNUSED_ARG (max);
01616   ACE_UNUSED_ARG (sa);
01617   int result = -1;
01618 
01619   if (ACE_OS::mutex_init (&s->lock_, type, name,
01620                           (ACE_mutexattr_t *) arg) == 0
01621       && ACE_OS::cond_init (&s->count_nonzero_, type, name, arg) == 0
01622       && ACE_OS::mutex_lock (&s->lock_) == 0)
01623     {
01624       s->count_ = count;
01625       s->waiters_ = 0;
01626 
01627       if (ACE_OS::mutex_unlock (&s->lock_) == 0)
01628         result = 0;
01629     }
01630 
01631   if (result == -1)
01632     {
01633       ACE_OS::mutex_destroy (&s->lock_);
01634       ACE_OS::cond_destroy (&s->count_nonzero_);
01635     }
01636   return result;
01637 #  elif defined (ACE_HAS_WTHREADS)
01638 #    if ! defined (ACE_USES_WINCE_SEMA_SIMULATION)
01639   ACE_UNUSED_ARG (type);
01640   ACE_UNUSED_ARG (arg);
01641   // Create the semaphore with its value initialized to <count> and
01642   // its maximum value initialized to <max>.
01643   SECURITY_ATTRIBUTES sa_buffer;
01644   SECURITY_DESCRIPTOR sd_buffer;
01645   *s = ::CreateSemaphoreA
01646     (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
01647      count,
01648      max,
01649      name);
01650 
01651   if (*s == 0)
01652     ACE_FAIL_RETURN (-1);
01653   /* NOTREACHED */
01654   else
01655     return 0;
01656 #    else /* ACE_USES_WINCE_SEMA_SIMULATION */
01657   int result = -1;
01658 
01659   // Initialize internal object for semaphore simulation.
01660   // Grab the lock as soon as possible when we initializing
01661   // the semaphore count.  Notice that we initialize the
01662   // event object as "manually reset" so we can amortize the
01663   // cost for singling/reseting the event.
01664   // @@ I changed the mutex type to thread_mutex.  Notice that this
01665   // is basically a CriticalSection object and doesn't not has
01666   // any security attribute whatsoever.  However, since this
01667   // semaphore implementation only works within a process, there
01668   // shouldn't any security issue at all.
01669   if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0
01670       && ACE_OS::event_init (&s->count_nonzero_, 1,
01671                              count > 0, type, name, arg, sa) == 0
01672       && ACE_OS::thread_mutex_lock (&s->lock_) == 0)
01673     {
01674       s->count_ = count;
01675 
01676       if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0)
01677         result = 0;
01678     }
01679 
01680   // Destroy the internal objects if we didn't initialize
01681   // either of them successfully.  Don't bother to check
01682   // for errors.
01683   if (result == -1)
01684     {
01685       ACE_OS::thread_mutex_destroy (&s->lock_);
01686       ACE_OS::event_destroy (&s->count_nonzero_);
01687     }
01688   return result;
01689 #    endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01690 #  elif defined (ACE_VXWORKS)
01691   ACE_UNUSED_ARG (name);
01692   ACE_UNUSED_ARG (arg);
01693   ACE_UNUSED_ARG (max);
01694   ACE_UNUSED_ARG (sa);
01695   s->name_ = 0;
01696   s->sema_ = ::semCCreate (type, count);
01697   return s->sema_ ? 0 : -1;
01698 #  endif /* ACE_HAS_STHREADS */
01699 #else
01700   ACE_UNUSED_ARG (s);
01701   ACE_UNUSED_ARG (count);
01702   ACE_UNUSED_ARG (type);
01703   ACE_UNUSED_ARG (name);
01704   ACE_UNUSED_ARG (arg);
01705   ACE_UNUSED_ARG (max);
01706   ACE_UNUSED_ARG (sa);
01707   ACE_NOTSUP_RETURN (-1);
01708 #endif /* ACE_HAS_POSIX_SEM */
01709 }
01710 
01711 #if defined (ACE_HAS_WCHAR)
01712 ACE_INLINE int
01713 ACE_OS::sema_init (ACE_sema_t *s,
01714                    u_int count,
01715                    int type,
01716                    const wchar_t *name,
01717                    void *arg,
01718                    int max,
01719                    LPSECURITY_ATTRIBUTES sa)
01720 {
01721 # if defined (ACE_HAS_WTHREADS)
01722 #   if ! defined (ACE_USES_WINCE_SEMA_SIMULATION)
01723   ACE_UNUSED_ARG (type);
01724   ACE_UNUSED_ARG (arg);
01725   // Create the semaphore with its value initialized to <count> and
01726   // its maximum value initialized to <max>.
01727   SECURITY_ATTRIBUTES sa_buffer;
01728   SECURITY_DESCRIPTOR sd_buffer;
01729   *s = ::CreateSemaphoreW
01730     (ACE_OS::default_win32_security_attributes_r (sa, &sa_buffer, &sd_buffer),
01731      count,
01732      max,
01733      name);
01734 
01735   if (*s == 0)
01736     ACE_FAIL_RETURN (-1);
01737   /* NOTREACHED */
01738   else
01739     return 0;
01740 #   else /* ACE_USES_WINCE_SEMA_SIMULATION */
01741   int result = -1;
01742 
01743   // Initialize internal object for semaphore simulation.
01744   // Grab the lock as soon as possible when we initializing
01745   // the semaphore count.  Notice that we initialize the
01746   // event object as "manually reset" so we can amortize the
01747   // cost for singling/reseting the event.
01748   // @@ I changed the mutex type to thread_mutex.  Notice that this
01749   // is basically a CriticalSection object and doesn't not has
01750   // any security attribute whatsoever.  However, since this
01751   // semaphore implementation only works within a process, there
01752   // shouldn't any security issue at all.
01753   if (ACE_OS::thread_mutex_init (&s->lock_, type, name, (ACE_mutexattr_t *)arg) == 0
01754       && ACE_OS::event_init (&s->count_nonzero_, 1,
01755                              count > 0, type, name, arg, sa) == 0
01756       && ACE_OS::thread_mutex_lock (&s->lock_) == 0)
01757     {
01758       s->count_ = count;
01759 
01760       if (ACE_OS::thread_mutex_unlock (&s->lock_) == 0)
01761         result = 0;
01762     }
01763 
01764   // Destroy the internal objects if we didn't initialize
01765   // either of them successfully.  Don't bother to check
01766   // for errors.
01767   if (result == -1)
01768     {
01769       ACE_OS::thread_mutex_destroy (&s->lock_);
01770       ACE_OS::event_destroy (&s->count_nonzero_);
01771     }
01772   return result;
01773 #   endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01774 # else /* ACE_HAS_WTHREADS */
01775   // Just call the normal char version.
01776   return ACE_OS::sema_init (s, count, type, ACE_Wide_To_Ascii (name).char_rep (), arg, max, sa);
01777 # endif /* ACE_HAS_WTHREADS */
01778 }
01779 #endif /* ACE_HAS_WCHAR */
01780 
01781 ACE_INLINE int
01782 ACE_OS::sema_post (ACE_sema_t *s)
01783 {
01784   ACE_OS_TRACE ("ACE_OS::sema_post");
01785 # if defined (ACE_HAS_POSIX_SEM)
01786 #   if defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
01787   ACE_OSCALL_RETURN (::sem_post (s->sema_), int, -1);
01788 #   else
01789   int result = -1;
01790 
01791   if (ACE_OS::mutex_lock (&s->lock_) == 0)
01792     {
01793       if (::sem_post (s->sema_) == 0)
01794         result = ACE_OS::cond_signal (&s->count_nonzero_);
01795 
01796       ACE_OS::mutex_unlock (&s->lock_);
01797     }
01798   return result;
01799 #   endif /* ACE_HAS_POSIX_SEM_TIMEOUT || ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION */
01800 # elif defined (ACE_USES_FIFO_SEM)
01801   char    c = 1;
01802   if (ACE_OS::write (s->fd_[1], &c, sizeof (char)) == sizeof (char))
01803     return (0);
01804   return (-1);
01805 # elif defined (ACE_HAS_THREADS)
01806 #   if defined (ACE_HAS_STHREADS)
01807   int result;
01808   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_post (s), result), int, -1);
01809 #   elif defined (ACE_HAS_PTHREADS)
01810   int result = -1;
01811 
01812   if (ACE_OS::mutex_lock (&s->lock_) == 0)
01813     {
01814       // Always allow a waiter to continue if there is one.
01815       if (s->waiters_ > 0)
01816         result = ACE_OS::cond_signal (&s->count_nonzero_);
01817       else
01818         result = 0;
01819 
01820       s->count_++;
01821       ACE_OS::mutex_unlock (&s->lock_);
01822     }
01823   return result;
01824 #   elif defined (ACE_HAS_WTHREADS)
01825 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
01826   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, 1, 0),
01827                                           ace_result_),
01828                         int, -1);
01829 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
01830   int result = -1;
01831 
01832   // Since we are simulating semaphores, we need to update semaphore
01833   // count manually.  Grab the lock to prevent race condition first.
01834   if (ACE_OS::thread_mutex_lock (&s->lock_) == 0)
01835     {
01836       // Check the original state of event object.  Single the event
01837       // object in transition from semaphore not available to
01838       // semaphore available.
01839       if (s->count_++ <= 0)
01840         result = ACE_OS::event_signal (&s->count_nonzero_);
01841       else
01842         result = 0;
01843 
01844       ACE_OS::thread_mutex_unlock (&s->lock_);
01845     }
01846   return result;
01847 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01848 #   elif defined (ACE_VXWORKS)
01849   ACE_OSCALL_RETURN (::semGive (s->sema_), int, -1);
01850 #   endif /* ACE_HAS_STHREADS */
01851 # else
01852   ACE_UNUSED_ARG (s);
01853   ACE_NOTSUP_RETURN (-1);
01854 # endif /* ACE_HAS_POSIX_SEM */
01855 }
01856 
01857 ACE_INLINE int
01858 ACE_OS::sema_post (ACE_sema_t *s, u_int release_count)
01859 {
01860 #if defined (ACE_WIN32) && !defined (ACE_USES_WINCE_SEMA_SIMULATION)
01861   // Win32 supports this natively.
01862   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseSemaphore (*s, release_count, 0),
01863                                           ace_result_), int, -1);
01864 #else
01865   // On POSIX platforms we need to emulate this ourselves.
01866   // @@ We can optimize on this implementation.  However,
01867   // the semaphore promitive on Win32 doesn't allow one
01868   // to increase a semaphore to more than the count it was
01869   // first initialized.  Posix and solaris don't seem to have
01870   // this restriction.  Should we impose the restriction in
01871   // our semaphore simulation?
01872   for (size_t i = 0; i < release_count; i++)
01873     if (ACE_OS::sema_post (s) == -1)
01874       return -1;
01875 
01876   return 0;
01877 #endif /* ACE_WIN32 */
01878 }
01879 
01880 ACE_INLINE int
01881 ACE_OS::sema_trywait (ACE_sema_t *s)
01882 {
01883   ACE_OS_TRACE ("ACE_OS::sema_trywait");
01884 # if defined (ACE_HAS_POSIX_SEM)
01885   // POSIX semaphores set errno to EAGAIN if trywait fails
01886   ACE_OSCALL_RETURN (::sem_trywait (s->sema_), int, -1);
01887 # elif defined (ACE_USES_FIFO_SEM)
01888   char  c;
01889   int     rc, flags;
01890 
01891   /* turn on nonblocking for s->fd_[0] */
01892   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0)
01893     return (-1);
01894   flags |= O_NONBLOCK;
01895   if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0)
01896     return (-1);
01897 
01898   // read sets errno to EAGAIN if no input
01899   rc = ACE_OS::read (s->fd_[0], &c, sizeof (char));
01900 
01901   /* turn off nonblocking for fd_[0] */
01902   if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) >= 0)
01903   {
01904     flags &= ~O_NONBLOCK;
01905     ACE_OS::fcntl (s->fd_[0], F_SETFL, flags);
01906   }
01907 
01908   return rc == 1 ? 0 : (-1);
01909 # elif defined (ACE_HAS_THREADS)
01910 #   if defined (ACE_HAS_STHREADS)
01911   // STHREADS semaphores set errno to EBUSY if trywait fails.
01912   int result;
01913   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_trywait (s),
01914                                        result),
01915                      int, -1);
01916 #   elif defined (ACE_HAS_PTHREADS)
01917 
01918   int result = -1;
01919 
01920   if (ACE_OS::mutex_lock (&s->lock_) == 0)
01921     {
01922       if (s->count_ > 0)
01923         {
01924           --s->count_;
01925           result = 0;
01926         }
01927       else
01928         errno = EBUSY;
01929 
01930       ACE_OS::mutex_unlock (&s->lock_);
01931     }
01932   return result;
01933 #   elif defined (ACE_HAS_WTHREADS)
01934 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
01935   DWORD result = ::WaitForSingleObject (*s, 0);
01936 
01937   if (result == WAIT_OBJECT_0)
01938     return 0;
01939   else
01940     {
01941       if (result == WAIT_TIMEOUT)
01942         errno = EBUSY;
01943       else
01944         ACE_OS::set_errno_to_last_error ();
01945       // This is a hack, we need to find an appropriate mapping...
01946       return -1;
01947     }
01948 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
01949   // Check the status of semaphore first.  Return immediately
01950   // if the semaphore is not available and avoid grabing the
01951   // lock.
01952   DWORD result = ::WaitForSingleObject (s->count_nonzero_, 0);
01953 
01954   if (result == WAIT_OBJECT_0)  // Proceed when it is available.
01955     {
01956       ACE_OS::thread_mutex_lock (&s->lock_);
01957 
01958       // Need to double check if the semaphore is still available.
01959       // The double checking scheme will slightly affect the
01960       // efficiency if most of the time semaphores are not blocked.
01961       result = ::WaitForSingleObject (s->count_nonzero_, 0);
01962       if (result == WAIT_OBJECT_0)
01963         {
01964           // Adjust the semaphore count.  Only update the event
01965           // object status when the state changed.
01966           s->count_--;
01967           if (s->count_ <= 0)
01968             ACE_OS::event_reset (&s->count_nonzero_);
01969           result = 0;
01970         }
01971 
01972       ACE_OS::thread_mutex_unlock (&s->lock_);
01973     }
01974 
01975   // Translate error message to errno used by ACE.
01976   if (result == WAIT_TIMEOUT)
01977     errno = EBUSY;
01978   else
01979     ACE_OS::set_errno_to_last_error ();
01980   // This is taken from the hack above. ;)
01981   return -1;
01982 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01983 #   elif defined (ACE_VXWORKS)
01984   if (::semTake (s->sema_, NO_WAIT) == ERROR)
01985     if (errno == S_objLib_OBJ_UNAVAILABLE)
01986       {
01987         // couldn't get the semaphore
01988         errno = EBUSY;
01989         return -1;
01990       }
01991     else
01992       // error
01993       return -1;
01994   else
01995     // got the semaphore
01996     return 0;
01997 #   endif /* ACE_HAS_STHREADS */
01998 # else
01999   ACE_UNUSED_ARG (s);
02000   ACE_NOTSUP_RETURN (-1);
02001 # endif /* ACE_HAS_POSIX_SEM */
02002 }
02003 
02004 ACE_INLINE int
02005 ACE_OS::sema_wait (ACE_sema_t *s)
02006 {
02007   ACE_OS_TRACE ("ACE_OS::sema_wait");
02008 # if defined (ACE_HAS_POSIX_SEM)
02009   ACE_OSCALL_RETURN (::sem_wait (s->sema_), int, -1);
02010 # elif defined (ACE_USES_FIFO_SEM)
02011   char c;
02012   if (ACE_OS::read (s->fd_[0], &c, sizeof (char)) == 1)
02013     return (0);
02014   return (-1);
02015 # elif defined (ACE_HAS_THREADS)
02016 #   if defined (ACE_HAS_STHREADS)
02017   int result;
02018   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sema_wait (s), result), int, -1);
02019 #   elif defined (ACE_HAS_PTHREADS)
02020   int result = 0;
02021 
02022   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
02023 
02024   if (ACE_OS::mutex_lock (&s->lock_) != 0)
02025     result = -1;
02026   else
02027     {
02028       // Keep track of the number of waiters so that we can signal
02029       // them properly in <ACE_OS::sema_post>.
02030       s->waiters_++;
02031 
02032       // Wait until the semaphore count is > 0.
02033       while (s->count_ == 0)
02034         if (ACE_OS::cond_wait (&s->count_nonzero_,
02035                                &s->lock_) == -1)
02036           {
02037             result = -2; // -2 means that we need to release the mutex.
02038             break;
02039           }
02040 
02041       --s->waiters_;
02042     }
02043 
02044   if (result == 0)
02045     --s->count_;
02046 
02047   if (result != -1)
02048     ACE_OS::mutex_unlock (&s->lock_);
02049   ACE_PTHREAD_CLEANUP_POP (0);
02050   return result < 0 ? -1 : result;
02051 
02052 #   elif defined (ACE_HAS_WTHREADS)
02053 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
02054   switch (::WaitForSingleObject (*s, INFINITE))
02055     {
02056     case WAIT_OBJECT_0:
02057       return 0;
02058     default:
02059       // This is a hack, we need to find an appropriate mapping...
02060       ACE_OS::set_errno_to_last_error ();
02061       return -1;
02062     }
02063   /* NOTREACHED */
02064 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
02065   // Timed wait.
02066   int result = -1;
02067   for (;;)
02068     // Check if the semaphore is avialable or not and wait forever.
02069     // Don't bother to grab the lock if it is not available (to avoid
02070     // deadlock.)
02071     switch (::WaitForSingleObject (s->count_nonzero_, INFINITE))
02072       {
02073       case WAIT_OBJECT_0:
02074         ACE_OS::thread_mutex_lock (&s->lock_);
02075 
02076         // Need to double check if the semaphore is still available.
02077         // This time, we shouldn't wait at all.
02078         if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0)
02079           {
02080             // Decrease the internal counter.  Only update the event
02081             // object's status when the state changed.
02082             s->count_--;
02083             if (s->count_ <= 0)
02084               ACE_OS::event_reset (&s->count_nonzero_);
02085             result = 0;
02086           }
02087 
02088         ACE_OS::thread_mutex_unlock (&s->lock_);
02089         // if we didn't get a hold on the semaphore, the result won't
02090         // be 0 and thus, we'll start from the beginning again.
02091         if (result == 0)
02092           return 0;
02093         break;
02094 
02095       default:
02096         // Since we wait indefinitely, anything other than
02097         // WAIT_OBJECT_O indicates an error.
02098         ACE_OS::set_errno_to_last_error ();
02099         // This is taken from the hack above. ;)
02100         return -1;
02101       }
02102   /* NOTREACHED */
02103 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
02104 #   elif defined (ACE_VXWORKS)
02105   ACE_OSCALL_RETURN (::semTake (s->sema_, WAIT_FOREVER), int, -1);
02106 #   endif /* ACE_HAS_STHREADS */
02107 # else
02108   ACE_UNUSED_ARG (s);
02109   ACE_NOTSUP_RETURN (-1);
02110 # endif /* ACE_HAS_POSIX_SEM */
02111 }
02112 
02113 ACE_INLINE int
02114 ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv)
02115 {
02116   ACE_OS_TRACE ("ACE_OS::sema_wait");
02117 # if defined (ACE_HAS_POSIX_SEM)
02118 #   if defined (ACE_HAS_POSIX_SEM_TIMEOUT)
02119   int rc;
02120   timespec_t ts;
02121   ts = tv; // Calls ACE_Time_Value::operator timespec_t().
02122   ACE_OSCALL (::sem_timedwait (s->sema_, &ts), int, -1, rc);
02123   if (rc == -1 && errno == ETIMEDOUT)
02124     errno = ETIME;  /* POSIX returns ETIMEDOUT but we need ETIME */
02125   return rc;
02126 #   elif !defined (ACE_DISABLE_POSIX_SEM_TIMEOUT_EMULATION)
02127   int result = 0;
02128   bool expired = false;
02129   ACE_Errno_Guard error (errno);
02130 
02131   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
02132 
02133   if (ACE_OS::mutex_lock (&s->lock_) != 0)
02134     result = -2;
02135   else
02136     {
02137       bool finished = true;
02138       do
02139       {
02140         result = ACE_OS::sema_trywait (s);
02141         if (result == -1 && errno == EAGAIN)
02142           expired = ACE_OS::gettimeofday () > tv;
02143         else
02144           expired = false;
02145 
02146         finished = result != -1 || expired ||
02147                    (result == -1 && errno != EAGAIN);
02148         if (!finished)
02149           {
02150             if (ACE_OS::cond_timedwait (&s->count_nonzero_,
02151                                         &s->lock_,
02152                                         &tv) == -1)
02153               {
02154                 error = errno;
02155                 result = -1;
02156                 break;
02157               }
02158           }
02159       } while (!finished);
02160 
02161       if (expired)
02162         error = ETIME;
02163 
02164 #     if defined (ACE_LACKS_COND_TIMEDWAIT_RESET)
02165       tv = ACE_OS::gettimeofday ();
02166 #     endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */
02167     }
02168 
02169   if (result != -2)
02170     ACE_OS::mutex_unlock (&s->lock_);
02171   ACE_PTHREAD_CLEANUP_POP (0);
02172   return result < 0 ? -1 : result;
02173 #   else /* No native sem_timedwait(), and emulation disabled */
02174   ACE_UNUSED_ARG (s);
02175   ACE_UNUSED_ARG (tv);
02176   ACE_NOTSUP_RETURN (-1);
02177 #   endif /* ACE_HAS_POSIX_SEM_TIMEOUT */
02178 # elif defined (ACE_USES_FIFO_SEM)
02179   int rc;
02180   ACE_Time_Value now = ACE_OS::gettimeofday ();
02181 
02182   while (tv > now)
02183     {
02184       ACE_Time_Value timeout = tv;
02185       timeout -= now;
02186 
02187       ACE_Handle_Set  fds_;
02188 
02189       fds_.set_bit (s->fd_[0]);
02190       if ((rc = ACE_OS::select (ACE_Handle_Set::MAXSIZE, fds_, 0, 0, timeout)) != 1)
02191         {
02192           if (rc == 0 || errno != EAGAIN)
02193           {
02194             if (rc == 0)
02195               errno = ETIME;
02196             return (-1);
02197           }
02198         }
02199 
02200       // try to read the signal *but* do *not* block
02201       if (rc == 1 && ACE_OS::sema_trywait (s) == 0)
02202         return (0);
02203 
02204       // we were woken for input but someone beat us to it
02205       // so we wait again if there is still time
02206       now = ACE_OS::gettimeofday ();
02207     }
02208 
02209   // make sure errno is set right
02210   errno = ETIME;
02211 
02212   return (-1);
02213 # elif defined (ACE_HAS_THREADS)
02214 #   if defined (ACE_HAS_STHREADS)
02215   ACE_UNUSED_ARG (s);
02216   ACE_UNUSED_ARG (tv);
02217   ACE_NOTSUP_RETURN (-1);
02218 #   elif defined (ACE_HAS_PTHREADS)
02219   int result = 0;
02220   ACE_Errno_Guard error (errno);
02221 
02222   ACE_PTHREAD_CLEANUP_PUSH (&s->lock_);
02223 
02224   if (ACE_OS::mutex_lock (&s->lock_) != 0)
02225     result = -1;
02226   else
02227     {
02228       // Keep track of the number of waiters so that we can signal
02229       // them properly in <ACE_OS::sema_post>.
02230       s->waiters_++;
02231 
02232       // Wait until the semaphore count is > 0 or until we time out.
02233       while (s->count_ == 0)
02234         if (ACE_OS::cond_timedwait (&s->count_nonzero_,
02235                                     &s->lock_,
02236                                     &tv) == -1)
02237           {
02238             error = errno;
02239             result = -2; // -2 means that we need to release the mutex.
02240             break;
02241           }
02242 
02243       --s->waiters_;
02244     }
02245 
02246   if (result == 0)
02247     {
02248 #     if defined (ACE_LACKS_COND_TIMEDWAIT_RESET)
02249       tv = ACE_OS::gettimeofday ();
02250 #     endif /* ACE_LACKS_COND_TIMEDWAIT_RESET */
02251       --s->count_;
02252     }
02253 
02254   if (result != -1)
02255     ACE_OS::mutex_unlock (&s->lock_);
02256   ACE_PTHREAD_CLEANUP_POP (0);
02257   return result < 0 ? -1 : result;
02258 #   elif defined (ACE_HAS_WTHREADS)
02259 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
02260   int msec_timeout;
02261 
02262   if (tv.sec () == 0 && tv.usec () == 0)
02263     msec_timeout = 0; // Do a "poll."
02264   else
02265     {
02266       // Note that we must convert between absolute time (which is
02267       // passed as a parameter) and relative time (which is what
02268       // <WaitForSingleObjects> expects).
02269       ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ());
02270 
02271       // Watchout for situations where a context switch has caused the
02272       // current time to be > the timeout.
02273       if (relative_time < ACE_Time_Value::zero)
02274         msec_timeout = 0;
02275       else
02276         msec_timeout = relative_time.msec ();
02277     }
02278 
02279   switch (::WaitForSingleObject (*s, msec_timeout))
02280     {
02281     case WAIT_OBJECT_0:
02282       tv = ACE_OS::gettimeofday ();     // Update time to when acquired
02283       return 0;
02284     case WAIT_TIMEOUT:
02285       errno = ETIME;
02286       return -1;
02287     default:
02288       // This is a hack, we need to find an appropriate mapping...
02289       ACE_OS::set_errno_to_last_error ();
02290       return -1;
02291     }
02292   /* NOTREACHED */
02293 #     else /* ACE_USES_WINCE_SEMA_SIMULATION */
02294   // Note that in this mode, the acquire is done in two steps, and
02295   // we may get signaled but cannot grab the semaphore before
02296   // timeout.  In that case, we'll need to restart the process with
02297   // updated timeout value.
02298 
02299   // tv is an absolute time, but we need relative to work with the Windows
02300   // API. Also, some users have become accustomed to using a 0 time value
02301   // as a shortcut for "now", which works on non-Windows because 0 is
02302   // always earlier than now. However, the need to convert to relative time
02303   // means we need to watch out for this case.
02304   ACE_Time_Value end_time = tv;
02305   if (tv == ACE_Time_Value::zero)
02306     end_time = ACE_OS::gettimeofday ();
02307   ACE_Time_Value relative_time = end_time - ACE_OS::gettimeofday ();
02308   int result = -1;
02309 
02310   // While we are not timeout yet. >= 0 will let this go through once
02311   // and if not able to get the object, it should hit WAIT_TIMEOUT
02312   // right away.
02313   while (relative_time >= ACE_Time_Value::zero)
02314     {
02315       // Wait for our turn to get the object.
02316       switch (::WaitForSingleObject (s->count_nonzero_, relative_time.msec ()))
02317         {
02318         case WAIT_OBJECT_0:
02319           ACE_OS::thread_mutex_lock (&s->lock_);
02320 
02321           // Need to double check if the semaphore is still available.
02322           // We can only do a "try lock" styled wait here to avoid
02323           // blocking threads that want to signal the semaphore.
02324           if (::WaitForSingleObject (s->count_nonzero_, 0) == WAIT_OBJECT_0)
02325             {
02326               // As before, only reset the object when the semaphore
02327               // is no longer available.
02328               s->count_--;
02329               if (s->count_ <= 0)
02330                 ACE_OS::event_reset (&s->count_nonzero_);
02331               result = 0;
02332             }
02333 
02334           ACE_OS::thread_mutex_unlock (&s->lock_);
02335 
02336           // Only return when we successfully get the semaphore.
02337           if (result == 0)
02338             {
02339               tv = ACE_OS::gettimeofday ();     // Update to time acquired
02340               return 0;
02341             }
02342           break;
02343 
02344           // We have timed out.
02345         case WAIT_TIMEOUT:
02346           errno = ETIME;
02347           return -1;
02348 
02349           // What?
02350         default:
02351           ACE_OS::set_errno_to_last_error ();
02352           // This is taken from the hack above. ;)
02353           return -1;
02354         };
02355 
02356       // Haven't been able to get the semaphore yet, update the
02357       // timeout value to reflect the remaining time we want to wait.
02358       relative_time = end_time - ACE_OS::gettimeofday ();
02359     }
02360 
02361   // We have timed out.
02362   errno = ETIME;
02363   return -1;
02364 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
02365 #   elif defined (ACE_VXWORKS)
02366   // Note that we must convert between absolute time (which is
02367   // passed as a parameter) and relative time (which is what
02368   // the system call expects).
02369   ACE_Time_Value relative_time (tv - ACE_OS::gettimeofday ());
02370 
02371   int ticks_per_sec = ::sysClkRateGet ();
02372 
02373   int ticks = relative_time.sec () * ticks_per_sec +
02374               relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
02375   if (::semTake (s->sema_, ticks) == ERROR)
02376     {
02377       if (errno == S_objLib_OBJ_TIMEOUT)
02378         // Convert the VxWorks errno to one that's common for to ACE
02379         // platforms.
02380         errno = ETIME;
02381       else if (errno == S_objLib_OBJ_UNAVAILABLE)
02382         errno = EBUSY;
02383       return -1;
02384     }
02385   else
02386     {
02387       tv = ACE_OS::gettimeofday ();  // Update to time acquired
02388       return 0;
02389     }
02390 #   endif /* ACE_HAS_STHREADS */
02391 # else
02392   ACE_UNUSED_ARG (s);
02393   ACE_UNUSED_ARG (tv);
02394   ACE_NOTSUP_RETURN (-1);
02395 # endif /* ACE_HAS_POSIX_SEM */
02396 }
02397 
02398 ACE_INLINE int
02399 ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value *tv)
02400 {
02401   return tv == 0 ? ACE_OS::sema_wait (s) : ACE_OS::sema_wait (s, *tv);
02402 }
02403 
02404 ACE_INLINE int
02405 ACE_OS::semctl (int int_id, int semnum, int cmd, semun value)
02406 {
02407   ACE_OS_TRACE ("ACE_OS::semctl");
02408 #if defined (ACE_HAS_SYSV_IPC)
02409   ACE_OSCALL_RETURN (::semctl (int_id, semnum, cmd, value), int, -1);
02410 #else
02411   ACE_UNUSED_ARG (int_id);
02412   ACE_UNUSED_ARG (semnum);
02413   ACE_UNUSED_ARG (cmd);
02414   ACE_UNUSED_ARG (value);
02415 
02416   ACE_NOTSUP_RETURN (-1);
02417 #endif /* ACE_HAS_SYSV_IPC */
02418 }
02419 
02420 ACE_INLINE int
02421 ACE_OS::semget (key_t key, int nsems, int flags)
02422 {
02423   ACE_OS_TRACE ("ACE_OS::semget");
02424 #if defined (ACE_HAS_SYSV_IPC)
02425   ACE_OSCALL_RETURN (::semget (key, nsems, flags), int, -1);
02426 #else
02427   ACE_UNUSED_ARG (key);
02428   ACE_UNUSED_ARG (nsems);
02429   ACE_UNUSED_ARG (flags);
02430 
02431   ACE_NOTSUP_RETURN (-1);
02432 #endif /* ACE_HAS_SYSV_IPC */
02433 }
02434 
02435 ACE_INLINE int
02436 ACE_OS::semop (int int_id, struct sembuf *sops, size_t nsops)
02437 {
02438   ACE_OS_TRACE ("ACE_OS::semop");
02439 #if defined (ACE_HAS_SYSV_IPC)
02440   ACE_OSCALL_RETURN (::semop (int_id, sops, nsops), int, -1);
02441 #else
02442   ACE_UNUSED_ARG (int_id);
02443   ACE_UNUSED_ARG (sops);
02444   ACE_UNUSED_ARG (nsops);
02445 
02446   ACE_NOTSUP_RETURN (-1);
02447 #endif /* ACE_HAS_SYSV_IPC */
02448 }
02449 
02450 ACE_INLINE int
02451 ACE_OS::sigtimedwait (const sigset_t *sset,
02452                       siginfo_t *info,
02453                       const ACE_Time_Value *timeout)
02454 {
02455   ACE_OS_TRACE ("ACE_OS::sigtimedwait");
02456 #if defined (ACE_HAS_SIGTIMEDWAIT)
02457   timespec_t ts;
02458   timespec_t *tsp;
02459 
02460   if (timeout != 0)
02461     {
02462       ts = *timeout; // Calls ACE_Time_Value::operator timespec_t().
02463       tsp = &ts;
02464     }
02465   else
02466     tsp = 0;
02467 
02468   ACE_OSCALL_RETURN (::sigtimedwait (sset, info, tsp),
02469                      int, -1);
02470 #else
02471     ACE_UNUSED_ARG (sset);
02472     ACE_UNUSED_ARG (info);
02473     ACE_UNUSED_ARG (timeout);
02474     ACE_NOTSUP_RETURN (-1);
02475 #endif /* ACE_HAS_SIGTIMEDWAIT */
02476 }
02477 
02478 ACE_INLINE int
02479 ACE_OS::sigwait (sigset_t *sset, int *sig)
02480 {
02481   ACE_OS_TRACE ("ACE_OS::sigwait");
02482   int local_sig;
02483   if (sig == 0)
02484     sig = &local_sig;
02485 #if defined (ACE_HAS_THREADS)
02486 # if (defined (__FreeBSD__) && (__FreeBSD__ < 3))
02487     ACE_UNUSED_ARG (sset);
02488     ACE_NOTSUP_RETURN (-1);
02489 # elif defined (ACE_HAS_STHREADS)
02490    # if (_POSIX_C_SOURCE - 0 >= 199506L) || defined (_POSIX_PTHREAD_SEMANTICS)
02491      errno = ::sigwait (sset, sig);
02492      return errno == 0  ?  *sig  :  -1;
02493    #else
02494      *sig = ::sigwait (sset);
02495      return *sig;
02496    #endif /* _POSIX_C_SOURCE - 0 >= 199506L || _POSIX_PTHREAD_SEMANTICS */
02497 # elif defined (ACE_HAS_PTHREADS)
02498   // LynxOS and Digital UNIX have their own hoops to jump through.
02499 #   if defined (__Lynx__)
02500     // Second arg is a void **, which we don't need (the selected
02501     // signal number is returned).
02502     *sig = ::sigwait (sset, 0);
02503     return *sig;
02504 #   elif defined (DIGITAL_UNIX)  &&  defined (__DECCXX_VER)
02505       // DEC cxx (but not g++) needs this direct call to its internal
02506       // sigwait ().  This allows us to #undef sigwait, so that we can
02507       // have ACE_OS::sigwait.  cxx gets confused by ACE_OS::sigwait
02508       // if sigwait is _not_ #undef'ed.
02509       errno = ::_Psigwait (sset, sig);
02510       return errno == 0  ?  *sig  :  -1;
02511 #   else /* ! __Lynx __ && ! (DIGITAL_UNIX && __DECCXX_VER) */
02512 #     if defined (CYGWIN32)
02513         // Cygwin has sigwait definition, but it is not implemented
02514         ACE_UNUSED_ARG (sset);
02515         ACE_NOTSUP_RETURN (-1);
02516 #     elif defined (ACE_TANDEM_T1248_PTHREADS)
02517         errno = ::spt_sigwait (sset, sig);
02518         return errno == 0  ?  *sig  :  -1;
02519 #     else   /* this is draft 7 or std */
02520         errno = ::sigwait (sset, sig);
02521         return errno == 0  ?  *sig  :  -1;
02522 #     endif /* CYGWIN32 */
02523 #   endif /* ! __Lynx__ && ! (DIGITAL_UNIX && __DECCXX_VER) */
02524 # elif defined (ACE_HAS_WTHREADS)
02525     ACE_UNUSED_ARG (sset);
02526     ACE_NOTSUP_RETURN (-1);
02527 # elif defined (ACE_VXWORKS)
02528     // Second arg is a struct siginfo *, which we don't need (the
02529     // selected signal number is returned).  Third arg is timeout:  0
02530     // means forever.
02531     *sig = ::sigtimedwait (sset, 0, 0);
02532     return *sig;
02533 # endif /* __FreeBSD__ */
02534 #else
02535     ACE_UNUSED_ARG (sset);
02536     ACE_UNUSED_ARG (sig);
02537     ACE_NOTSUP_RETURN (-1);
02538 #endif /* ACE_HAS_THREADS */
02539 }
02540 
02541 ACE_INLINE int
02542 ACE_OS::sigwaitinfo (const sigset_t *sset,
02543                      siginfo_t *info)
02544 {
02545   ACE_OS_TRACE ("ACE_OS::sigwaitinfo");
02546   // If this platform has sigtimedwait, it should have sigwaitinfo as well.
02547   // If this isn't true somewhere, let me know and I'll fix this.
02548   // -Steve Huston <shuston@riverace.com>.
02549 #if defined (ACE_HAS_SIGTIMEDWAIT)
02550   ACE_OSCALL_RETURN (::sigwaitinfo (sset, info), int, -1);
02551 #else
02552   ACE_UNUSED_ARG (sset);
02553   ACE_UNUSED_ARG (info);
02554   ACE_NOTSUP_RETURN (-1);
02555 #endif /* ACE_HAS_SIGTIMEDWAIT */
02556 }
02557 
02558 ACE_INLINE int
02559 ACE_OS::thr_cancel (ACE_thread_t thr_id)
02560 {
02561   ACE_OS_TRACE ("ACE_OS::thr_cancel");
02562 #if defined (ACE_HAS_THREADS)
02563 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
02564   int result;
02565   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_cancel (thr_id),
02566                                         result),
02567                       int, -1);
02568 # elif defined (ACE_HAS_VXTHREADS)
02569   ACE_OSCALL_RETURN (::taskDelete (thr_id), int, -1);
02570 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
02571   ACE_UNUSED_ARG (thr_id);
02572   ACE_NOTSUP_RETURN (-1);
02573 # endif /* ACE_HAS_PTHREADS */
02574 #else
02575   ACE_UNUSED_ARG (thr_id);
02576   ACE_NOTSUP_RETURN (-1);
02577 #endif /* ACE_HAS_THREADS */
02578 }
02579 
02580 ACE_INLINE int
02581 ACE_OS::thr_cmp (ACE_hthread_t t1, ACE_hthread_t t2)
02582 {
02583 #if defined (ACE_HAS_PTHREADS)
02584 # if defined (pthread_equal)
02585   // If it's a macro we can't say "pthread_equal"...
02586   return pthread_equal (t1, t2);
02587 # else
02588   return pthread_equal (t1, t2);
02589 # endif /* pthread_equal */
02590 #else /* For STHREADS, WTHREADS, and VXWORKS ... */
02591   // Hum, Do we need to treat WTHREAD differently?
02592   // levine 13 oct 98 % Probably, ACE_hthread_t is a HANDLE.
02593   return t1 == t2;
02594 #endif /* ACE_HAS_PTHREADS */
02595 }
02596 
02597 ACE_INLINE int
02598 ACE_OS::thr_continue (ACE_hthread_t target_thread)
02599 {
02600   ACE_OS_TRACE ("ACE_OS::thr_continue");
02601 #if defined (ACE_HAS_THREADS)
02602 # if defined (ACE_HAS_STHREADS)
02603   int result;
02604   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_continue (target_thread), result), int, -1);
02605 # elif defined (ACE_HAS_PTHREADS)
02606 #  if defined (ACE_HAS_PTHREAD_CONTINUE)
02607   int result;
02608   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue (target_thread),
02609                                        result),
02610                      int, -1);
02611 #  elif defined (ACE_HAS_PTHREAD_CONTINUE_NP)
02612   int result;
02613   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_continue_np (target_thread),
02614                                        result),
02615                      int, -1);
02616 #  elif defined (ACE_HAS_PTHREAD_RESUME_NP)
02617   int result;
02618   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_resume_np (target_thread),
02619                                        result),
02620                      int, -1);
02621 #  else
02622   ACE_UNUSED_ARG (target_thread);
02623   ACE_NOTSUP_RETURN (-1);
02624 #  endif /* ACE_HAS_PTHREAD_CONTINUE */
02625 # elif defined (ACE_HAS_WTHREADS)
02626   DWORD result = ::ResumeThread (target_thread);
02627   if (result == ACE_SYSCALL_FAILED)
02628     ACE_FAIL_RETURN (-1);
02629   else
02630     return 0;
02631 # elif defined (ACE_HAS_VXTHREADS)
02632   ACE_OSCALL_RETURN (::taskResume (target_thread), int, -1);
02633 # endif /* ACE_HAS_STHREADS */
02634 #else
02635   ACE_UNUSED_ARG (target_thread);
02636   ACE_NOTSUP_RETURN (-1);
02637 #endif /* ACE_HAS_THREADS */
02638 }
02639 
02640 ACE_INLINE int
02641 ACE_OS::thr_getconcurrency (void)
02642 {
02643   ACE_OS_TRACE ("ACE_OS::thr_getconcurrency");
02644 #if defined (ACE_HAS_THREADS)
02645 # if defined (ACE_HAS_STHREADS)
02646   return ::thr_getconcurrency ();
02647 # elif defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_GETCONCURRENCY)
02648   return pthread_getconcurrency ();
02649 # else
02650   ACE_NOTSUP_RETURN (-1);
02651 # endif /* ACE_HAS_STHREADS */
02652 #else
02653   ACE_NOTSUP_RETURN (-1);
02654 #endif /* ACE_HAS_THREADS */
02655 }
02656 
02657 ACE_INLINE int
02658 ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority, int &policy)
02659 {
02660   ACE_OS_TRACE ("ACE_OS::thr_getprio");
02661   ACE_UNUSED_ARG (policy);
02662 #if defined (ACE_HAS_THREADS)
02663 # if (defined (ACE_HAS_PTHREADS) && \
02664      (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
02665 
02666   struct sched_param param;
02667   int result;
02668 
02669   ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
02670                                 result), int,
02671               -1, result);
02672   priority = param.sched_priority;
02673   return result;
02674 # elif defined (ACE_HAS_STHREADS)
02675   int result;
02676   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getprio (ht_id, &priority), result), int, -1);
02677 # elif defined (ACE_HAS_WTHREADS) && !defined (ACE_HAS_WINCE)
02678   ACE_Errno_Guard error (errno);
02679 
02680   priority = ::GetThreadPriority (ht_id);
02681 
02682 #   if defined (ACE_HAS_PHARLAP)
02683 #     if defined (ACE_PHARLAP_LABVIEW_RT)
02684   policy = ACE_SCHED_FIFO;
02685 #     else
02686   DWORD timeslice = ::EtsGetTimeSlice ();
02687   policy = timeslice == 0 ? ACE_SCHED_OTHER : ACE_SCHED_FIFO;
02688 #     endif /* ACE_PHARLAP_LABVIEW_RT */
02689 #   else
02690   DWORD priority_class = ::GetPriorityClass (::GetCurrentProcess ());
02691   if (priority_class == 0 && (error = ::GetLastError ()) != NO_ERROR)
02692     ACE_FAIL_RETURN (-1);
02693 
02694   policy =
02695     (priority_class ==
02696      REALTIME_PRIORITY_CLASS) ? ACE_SCHED_FIFO : ACE_SCHED_OTHER;
02697 #   endif /* ACE_HAS_PHARLAP */
02698 
02699   return 0;
02700 # elif defined (ACE_HAS_VXTHREADS)
02701   ACE_OSCALL_RETURN (::taskPriorityGet (ht_id, &priority), int, -1);
02702 # else
02703   ACE_UNUSED_ARG (ht_id);
02704   ACE_UNUSED_ARG (priority);
02705   ACE_NOTSUP_RETURN (-1);
02706 # endif /* ACE_HAS_STHREADS */
02707 #else
02708   ACE_UNUSED_ARG (ht_id);
02709   ACE_UNUSED_ARG (priority);
02710   ACE_NOTSUP_RETURN (-1);
02711 #endif /* ACE_HAS_THREADS */
02712 }
02713 
02714 ACE_INLINE int
02715 ACE_OS::thr_getprio (ACE_hthread_t ht_id, int &priority)
02716 {
02717   ACE_OS_TRACE ("ACE_OS::thr_getprio");
02718   int policy = 0;
02719   return ACE_OS::thr_getprio (ht_id, priority, policy);
02720 }
02721 
02722 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
02723 ACE_INLINE int
02724 ACE_OS::thr_getspecific_native (ACE_OS_thread_key_t key, void **data)
02725 {
02726 //  ACE_OS_TRACE ("ACE_OS::thr_getspecific_native");
02727 # if defined (ACE_HAS_PTHREADS)
02728     *data = pthread_getspecific (key);
02729     return 0;
02730 # elif defined (ACE_HAS_STHREADS)
02731     int result;
02732     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_getspecific (key, data), result), int, -1);
02733 # elif defined (ACE_HAS_WTHREADS)
02734   *data = ::TlsGetValue (key);
02735   if (*data == 0 && ::GetLastError () != NO_ERROR)
02736     {
02737       ACE_OS::set_errno_to_last_error ();
02738       return -1;
02739     }
02740   else
02741     return 0;
02742 # else /* ACE_HAS_PTHREADS etc.*/
02743   ACE_UNUSED_ARG (key);
02744   ACE_UNUSED_ARG (data);
02745   ACE_NOTSUP_RETURN (-1);
02746 # endif /* ACE_HAS_PTHREADS etc.*/
02747 }
02748 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
02749 
02750 ACE_INLINE int
02751 ACE_OS::thr_getspecific (ACE_thread_key_t key, void **data)
02752 {
02753 //   ACE_OS_TRACE ("ACE_OS::thr_getspecific");
02754 #if defined (ACE_HAS_THREADS)
02755 # if defined (ACE_HAS_TSS_EMULATION)
02756     if (ACE_TSS_Emulation::is_key (key) == 0)
02757       {
02758         errno = EINVAL;
02759         data = 0;
02760         return -1;
02761       }
02762     else
02763       {
02764         *data = ACE_TSS_Emulation::ts_object (key);
02765         return 0;
02766       }
02767 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
02768   return ACE_OS::thr_getspecific_native (key, data);
02769 #else
02770   ACE_UNUSED_ARG (key);
02771   ACE_UNUSED_ARG (data);
02772   ACE_NOTSUP_RETURN (-1);
02773 # endif /* ACE_HAS_TSS_EMULATION */
02774 #else
02775   ACE_UNUSED_ARG (key);
02776   ACE_UNUSED_ARG (data);
02777   ACE_NOTSUP_RETURN (-1);
02778 #endif /* ACE_HAS_THREADS */
02779 }
02780 
02781 #if !defined (ACE_HAS_VXTHREADS)
02782 ACE_INLINE int
02783 ACE_OS::thr_join (ACE_hthread_t thr_handle,
02784                   ACE_THR_FUNC_RETURN *status)
02785 {
02786   ACE_OS_TRACE ("ACE_OS::thr_join");
02787 #if defined (ACE_HAS_THREADS)
02788 # if defined (ACE_HAS_STHREADS)
02789   int result;
02790   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (thr_handle, 0, status), result),
02791                      int, -1);
02792 # elif defined (ACE_HAS_PTHREADS)
02793   int result;
02794   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (thr_handle, status), result),
02795                      int, -1);
02796 # elif defined (ACE_HAS_WTHREADS)
02797   ACE_THR_FUNC_RETURN local_status = 0;
02798 
02799   // Make sure that status is non-NULL.
02800   if (status == 0)
02801     status = &local_status;
02802 
02803   if (::WaitForSingleObject (thr_handle, INFINITE) == WAIT_OBJECT_0
02804       && ::GetExitCodeThread (thr_handle, status) != FALSE)
02805     {
02806       ::CloseHandle (thr_handle);
02807       return 0;
02808     }
02809   ACE_FAIL_RETURN (-1);
02810   /* NOTREACHED */
02811 # else
02812   ACE_UNUSED_ARG (thr_handle);
02813   ACE_UNUSED_ARG (status);
02814   ACE_NOTSUP_RETURN (-1);
02815 # endif /* ACE_HAS_STHREADS */
02816 #else
02817   ACE_UNUSED_ARG (thr_handle);
02818   ACE_UNUSED_ARG (status);
02819   ACE_NOTSUP_RETURN (-1);
02820 #endif /* ACE_HAS_THREADS */
02821 }
02822 
02823 ACE_INLINE int
02824 ACE_OS::thr_join (ACE_thread_t waiter_id,
02825                   ACE_thread_t *thr_id,
02826                   ACE_THR_FUNC_RETURN *status)
02827 {
02828   ACE_OS_TRACE ("ACE_OS::thr_join");
02829 #if defined (ACE_HAS_THREADS)
02830 # if defined (ACE_HAS_STHREADS)
02831   int result;
02832   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_join (waiter_id, thr_id, status), result),
02833                      int, -1);
02834 # elif defined (ACE_HAS_PTHREADS)
02835   ACE_UNUSED_ARG (thr_id);
02836   int result;
02837   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_join (waiter_id, status), result),
02838                      int, -1);
02839 # elif defined (ACE_HAS_WTHREADS)
02840   ACE_UNUSED_ARG (waiter_id);
02841   ACE_UNUSED_ARG (thr_id);
02842   ACE_UNUSED_ARG (status);
02843 
02844   // This could be implemented if the DLL-Main function or the
02845   // task exit base class some log the threads which have exited
02846   ACE_NOTSUP_RETURN (-1);
02847 # endif /* ACE_HAS_STHREADS */
02848 #else
02849   ACE_UNUSED_ARG (waiter_id);
02850   ACE_UNUSED_ARG (thr_id);
02851   ACE_UNUSED_ARG (status);
02852   ACE_NOTSUP_RETURN (-1);
02853 #endif /* ACE_HAS_THREADS */
02854 }
02855 #endif /* !VXWORKS */
02856 
02857 ACE_INLINE int
02858 ACE_OS::thr_kill (ACE_thread_t thr_id, int signum)
02859 {
02860   ACE_OS_TRACE ("ACE_OS::thr_kill");
02861 #if defined (ACE_HAS_THREADS)
02862 # if defined (ACE_HAS_PTHREADS)
02863 #   if defined (ACE_LACKS_PTHREAD_KILL)
02864   ACE_UNUSED_ARG (signum);
02865   ACE_UNUSED_ARG (thr_id);
02866   ACE_NOTSUP_RETURN (-1);
02867 #   else
02868   int result;
02869   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_kill (thr_id, signum),
02870                                        result),
02871                      int, -1);
02872 #   endif /* ACE_LACKS_PTHREAD_KILL */
02873 # elif defined (ACE_HAS_STHREADS)
02874   int result;
02875   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_kill (thr_id, signum),
02876                                        result),
02877                      int, -1);
02878 # elif defined (ACE_HAS_VXTHREADS)
02879   //FUZZ: disable check_for_lack_ACE_OS
02880   ACE_OSCALL_RETURN (::kill (thr_id, signum), int, -1);
02881   //FUZZ: enable check_for_lack_ACE_OS
02882 # else
02883   ACE_UNUSED_ARG (thr_id);
02884   ACE_UNUSED_ARG (signum);
02885   ACE_NOTSUP_RETURN (-1);
02886 # endif /* ACE_HAS_STHREADS */
02887 #else
02888   ACE_UNUSED_ARG (thr_id);
02889   ACE_UNUSED_ARG (signum);
02890   ACE_NOTSUP_RETURN (-1);
02891 #endif /* ACE_HAS_THREADS */
02892 }
02893 
02894 ACE_INLINE size_t
02895 ACE_OS::thr_min_stack (void)
02896 {
02897   ACE_OS_TRACE ("ACE_OS::thr_min_stack");
02898 #if defined (ACE_HAS_THREADS)
02899 # if defined (ACE_HAS_STHREADS)
02900 #   if defined (ACE_HAS_THR_MINSTACK)
02901   // Tandem did some weirdo mangling of STHREAD names...
02902   return ::thr_minstack ();
02903 #   else
02904   return ::thr_min_stack ();
02905 #   endif /* !ACE_HAS_THR_MINSTACK */
02906 # elif defined (ACE_HAS_PTHREADS)
02907 #   if defined (_SC_THREAD_STACK_MIN)
02908   return (size_t) ACE_OS::sysconf (_SC_THREAD_STACK_MIN);
02909 #   elif defined (PTHREAD_STACK_MIN)
02910   return PTHREAD_STACK_MIN;
02911 #   else
02912   ACE_NOTSUP_RETURN (0);
02913 #   endif /* _SC_THREAD_STACK_MIN */
02914 # elif defined (ACE_HAS_WTHREADS)
02915   ACE_NOTSUP_RETURN (0);
02916 # elif defined (ACE_HAS_VXTHREADS)
02917   TASK_DESC taskDesc;
02918   STATUS status;
02919 
02920   ACE_thread_t tid = ACE_OS::thr_self ();
02921 
02922   ACE_OSCALL (ACE_ADAPT_RETVAL (::taskInfoGet (tid, &taskDesc),
02923                                 status),
02924               STATUS, -1, status);
02925   return status == OK ? taskDesc.td_stackSize : 0;
02926 # else /* Should not happen... */
02927   ACE_NOTSUP_RETURN (0);
02928 # endif /* ACE_HAS_STHREADS */
02929 #else
02930   ACE_NOTSUP_RETURN (0);
02931 #endif /* ACE_HAS_THREADS */
02932 }
02933 
02934 ACE_INLINE ACE_thread_t
02935 ACE_OS::thr_self (void)
02936 {
02937   // ACE_OS_TRACE ("ACE_OS::thr_self");
02938 #if defined (ACE_HAS_THREADS)
02939 # if defined (ACE_HAS_PTHREADS)
02940   // Note, don't use "::" here since the following call is often a macro.
02941   return pthread_self ();
02942 # elif defined (ACE_HAS_STHREADS)
02943   ACE_OSCALL_RETURN (::thr_self (), int, -1);
02944 # elif defined (ACE_HAS_WTHREADS)
02945   return ::GetCurrentThreadId ();
02946 # elif defined (ACE_HAS_VXTHREADS)
02947   return ::taskIdSelf ();
02948 # endif /* ACE_HAS_STHREADS */
02949 #else
02950   return 1; // Might as well make it the first thread ;-)
02951 #endif /* ACE_HAS_THREADS */
02952 }
02953 
02954 ACE_INLINE const char*
02955 ACE_OS::thr_name (void)
02956 {
02957 #if defined (ACE_HAS_THREADS)
02958 #if defined (ACE_HAS_VXTHREADS)
02959   return ::taskName (ACE_OS::thr_self ());
02960 #else
02961   ACE_NOTSUP_RETURN (0);
02962 #endif
02963 #else
02964   ACE_NOTSUP_RETURN (0);
02965 #endif
02966 }
02967 
02968 ACE_INLINE void
02969 ACE_OS::thr_self (ACE_hthread_t &self)
02970 {
02971   ACE_OS_TRACE ("ACE_OS::thr_self");
02972 #if defined (ACE_HAS_THREADS)
02973 # if defined (ACE_HAS_PTHREADS)
02974   // Note, don't use "::" here since the following call is often a macro.
02975   self = pthread_self ();
02976 # elif defined (ACE_HAS_THREAD_SELF)
02977   self = ::thread_self ();
02978 # elif defined (ACE_HAS_STHREADS)
02979   self = ::thr_self ();
02980 # elif defined (ACE_HAS_WTHREADS)
02981   self = ::GetCurrentThread ();
02982 # elif defined (ACE_HAS_VXTHREADS)
02983   self = ::taskIdSelf ();
02984 # endif /* ACE_HAS_STHREADS */
02985 #else
02986   self = 1; // Might as well make it the main thread ;-)
02987 #endif /* ACE_HAS_THREADS */
02988 }
02989 
02990 ACE_INLINE int
02991 ACE_OS::thr_setcancelstate (int new_state, int *old_state)
02992 {
02993   ACE_OS_TRACE ("ACE_OS::thr_setcancelstate");
02994 #if defined (ACE_HAS_THREADS)
02995 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
02996   int result;
02997   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setcancelstate (new_state,
02998                                                                old_state),
02999                                        result),
03000                      int, -1);
03001 # elif defined (ACE_HAS_STHREADS)
03002   ACE_UNUSED_ARG (new_state);
03003   ACE_UNUSED_ARG (old_state);
03004   ACE_NOTSUP_RETURN (-1);
03005 # elif defined (ACE_HAS_WTHREADS)
03006   ACE_UNUSED_ARG (new_state);
03007   ACE_UNUSED_ARG (old_state);
03008   ACE_NOTSUP_RETURN (-1);
03009 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
03010   ACE_UNUSED_ARG (new_state);
03011   ACE_UNUSED_ARG (old_state);
03012   ACE_NOTSUP_RETURN (-1);
03013 # endif /* ACE_HAS_PTHREADS */
03014 #else
03015   ACE_UNUSED_ARG (new_state);
03016   ACE_UNUSED_ARG (old_state);
03017   ACE_NOTSUP_RETURN (-1);
03018 #endif /* ACE_HAS_THREADS */
03019 }
03020 
03021 ACE_INLINE int
03022 ACE_OS::thr_setcanceltype (int new_type, int *old_type)
03023 {
03024   ACE_OS_TRACE ("ACE_OS::thr_setcanceltype");
03025 #if defined (ACE_HAS_THREADS)
03026 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
03027   int result;
03028   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setcanceltype (new_type,
03029                                                               old_type),
03030                                        result),
03031                      int, -1);
03032 # else /* Could be ACE_HAS_PTHREADS && ACE_LACKS_PTHREAD_CANCEL */
03033   ACE_UNUSED_ARG (new_type);
03034   ACE_UNUSED_ARG (old_type);
03035   ACE_NOTSUP_RETURN (-1);
03036 # endif /* ACE_HAS_PTHREADS */
03037 #else
03038   ACE_UNUSED_ARG (new_type);
03039   ACE_UNUSED_ARG (old_type);
03040   ACE_NOTSUP_RETURN (-1);
03041 #endif /* ACE_HAS_THREADS */
03042 }
03043 
03044 ACE_INLINE int
03045 ACE_OS::thr_setconcurrency (int hint)
03046 {
03047   ACE_OS_TRACE ("ACE_OS::thr_setconcurrency");
03048 #if defined (ACE_HAS_THREADS)
03049 # if defined (ACE_HAS_STHREADS)
03050   int result;
03051   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setconcurrency (hint),
03052                                        result),
03053                      int, -1);
03054 # elif defined (ACE_HAS_PTHREADS) && defined (ACE_HAS_PTHREAD_SETCONCURRENCY)
03055   int result;
03056   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setconcurrency (hint),
03057                                        result),
03058                      int, -1);
03059 # else
03060   ACE_UNUSED_ARG (hint);
03061   ACE_NOTSUP_RETURN (-1);
03062 # endif /* ACE_HAS_STHREADS */
03063 #else
03064   ACE_UNUSED_ARG (hint);
03065   ACE_NOTSUP_RETURN (-1);
03066 #endif /* ACE_HAS_THREADS */
03067 }
03068 
03069 ACE_INLINE int
03070 ACE_OS::thr_setprio (ACE_hthread_t ht_id, int priority, int policy)
03071 {
03072   ACE_OS_TRACE ("ACE_OS::thr_setprio");
03073   ACE_UNUSED_ARG (policy);
03074 #if defined (ACE_HAS_THREADS)
03075 # if (defined (ACE_HAS_PTHREADS) && \
03076       (!defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)))
03077 
03078   int result;
03079   struct sched_param param;
03080   ACE_OS::memset ((void *) &param, 0, sizeof param);
03081 
03082   // If <policy> is -1, we don't want to use it for
03083   // pthread_setschedparam().  Instead, obtain policy from
03084   // pthread_getschedparam().
03085   if (policy == -1)
03086     {
03087       ACE_OSCALL (ACE_ADAPT_RETVAL (pthread_getschedparam (ht_id, &policy, &param),
03088                                     result),
03089                   int, -1, result);
03090       if (result == -1)
03091         return result;
03092     }
03093 
03094   param.sched_priority = priority;
03095 
03096   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setschedparam (ht_id,
03097                                                               policy,
03098                                                               &param),
03099                                        result),
03100                      int, -1);
03101 # elif defined (ACE_HAS_STHREADS)
03102   int result;
03103   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setprio (ht_id, priority),
03104                                        result),
03105                      int, -1);
03106 # elif defined (ACE_HAS_WTHREADS)
03107   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetThreadPriority (ht_id, priority),
03108                                           ace_result_),
03109                         int, -1);
03110 # elif defined (ACE_HAS_VXTHREADS)
03111   ACE_OSCALL_RETURN (::taskPrioritySet (ht_id, priority), int, -1);
03112 # else
03113   // For example, platforms that support Pthreads but LACK_SETSCHED.
03114   ACE_UNUSED_ARG (ht_id);
03115   ACE_UNUSED_ARG (priority);
03116   ACE_NOTSUP_RETURN (-1);
03117 # endif /* ACE_HAS_STHREADS */
03118 #else
03119   ACE_UNUSED_ARG (ht_id);
03120   ACE_UNUSED_ARG (priority);
03121   ACE_NOTSUP_RETURN (-1);
03122 #endif /* ACE_HAS_THREADS */
03123 }
03124 
03125 ACE_INLINE int
03126 ACE_OS::thr_sigsetmask (int how,
03127                         const sigset_t *nsm,
03128                         sigset_t *osm)
03129 {
03130   ACE_OS_TRACE ("ACE_OS::thr_sigsetmask");
03131 #if defined (ACE_HAS_THREADS)
03132 # if defined (ACE_LACKS_PTHREAD_THR_SIGSETMASK)
03133   // DCE threads and Solaris 2.4 have no such function.
03134   ACE_UNUSED_ARG (osm);
03135   ACE_UNUSED_ARG (nsm);
03136   ACE_UNUSED_ARG (how);
03137 
03138   ACE_NOTSUP_RETURN (-1);
03139 # elif defined (ACE_HAS_SIGTHREADMASK)
03140   int result;
03141   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sigthreadmask (how, nsm, osm),
03142                                        result), int, -1);
03143 # elif defined (ACE_HAS_STHREADS)
03144   int result;
03145   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_sigsetmask (how, nsm, osm),
03146                                        result),
03147                      int, -1);
03148 # elif defined (ACE_HAS_PTHREADS)
03149 #   if !defined (ACE_LACKS_PTHREAD_SIGMASK)
03150   int result;
03151   //FUZZ: disable check_for_lack_ACE_OS
03152   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_sigmask (how, nsm, osm),
03153                                        result), int, -1);
03154   //FUZZ: enable check_for_lack_ACE_OS
03155 #   endif /* !ACE_LACKS_PTHREAD_SIGMASK */
03156 
03157 #if 0
03158   /* Don't know if any platform actually needs this... */
03159   // as far as I can tell, this is now pthread_sigaction() -- jwr
03160   int result;
03161   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_sigaction (how, nsm, osm),
03162                                        result), int, -1);
03163 #endif /* 0 */
03164 
03165 # elif defined (ACE_HAS_WTHREADS)
03166   ACE_UNUSED_ARG (osm);
03167   ACE_UNUSED_ARG (nsm);
03168   ACE_UNUSED_ARG (how);
03169 
03170   ACE_NOTSUP_RETURN (-1);
03171 # elif defined (ACE_VXWORKS)
03172   int old_mask = 0;
03173   switch (how)
03174     {
03175     case SIG_BLOCK:
03176     case SIG_UNBLOCK:
03177       {
03178         // get the old mask
03179         old_mask = ::sigsetmask (*nsm);
03180         // create a new mask:  the following assumes that sigset_t is 4 bytes,
03181         // which it is on VxWorks 5.2, so bit operations are done simply . . .
03182         ::sigsetmask (how == SIG_BLOCK ? (old_mask |= *nsm) : (old_mask &= ~*nsm));
03183         if (osm)
03184           *osm = old_mask;
03185         break;
03186       }
03187     case SIG_SETMASK:
03188       old_mask = ::sigsetmask (*nsm);
03189       if (osm)
03190         *osm = old_mask;
03191       break;
03192     default:
03193       return -1;
03194     }
03195 
03196   return 0;
03197 # else /* Should not happen. */
03198   ACE_UNUSED_ARG (how);
03199   ACE_UNUSED_ARG (nsm);
03200   ACE_UNUSED_ARG (osm);
03201   ACE_NOTSUP_RETURN (-1);
03202 # endif /* ACE_LACKS_PTHREAD_THR_SIGSETMASK */
03203 #else
03204   ACE_UNUSED_ARG (how);
03205   ACE_UNUSED_ARG (nsm);
03206   ACE_UNUSED_ARG (osm);
03207   ACE_NOTSUP_RETURN (-1);
03208 #endif /* ACE_HAS_THREADS */
03209 }
03210 
03211 ACE_INLINE int
03212 ACE_OS::thr_suspend (ACE_hthread_t target_thread)
03213 {
03214   ACE_OS_TRACE ("ACE_OS::thr_suspend");
03215 #if defined (ACE_HAS_THREADS)
03216 # if defined (ACE_HAS_STHREADS)
03217   int result;
03218   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_suspend (target_thread), result), int, -1);
03219 # elif defined (ACE_HAS_PTHREADS)
03220 #  if defined (ACE_HAS_PTHREAD_SUSPEND)
03221   int result;
03222   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend (target_thread),
03223                                        result),
03224                      int, -1);
03225 #  elif defined (ACE_HAS_PTHREAD_SUSPEND_NP)
03226   int result;
03227   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_suspend_np (target_thread),
03228                                        result),
03229                      int, -1);
03230 #  else
03231   ACE_UNUSED_ARG (target_thread);
03232   ACE_NOTSUP_RETURN (-1);
03233 #  endif /* ACE_HAS_PTHREAD_SUSPEND */
03234 # elif defined (ACE_HAS_WTHREADS)
03235   if (::SuspendThread (target_thread) != ACE_SYSCALL_FAILED)
03236     return 0;
03237   else
03238     ACE_FAIL_RETURN (-1);
03239   /* NOTREACHED */
03240 # elif defined (ACE_HAS_VXTHREADS)
03241   ACE_OSCALL_RETURN (::taskSuspend (target_thread), int, -1);
03242 # endif /* ACE_HAS_STHREADS */
03243 #else
03244   ACE_UNUSED_ARG (target_thread);
03245   ACE_NOTSUP_RETURN (-1);
03246 #endif /* ACE_HAS_THREADS */
03247 }
03248 
03249 ACE_INLINE void
03250 ACE_OS::thr_testcancel (void)
03251 {
03252   ACE_OS_TRACE ("ACE_OS::thr_testcancel");
03253 #if defined (ACE_HAS_THREADS)
03254 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_CANCEL)
03255   pthread_testcancel ();
03256 # elif defined (ACE_HAS_STHREADS)
03257 # elif defined (ACE_HAS_WTHREADS)
03258 # elif defined (ACE_HAS_VXTHREADS)
03259 # else
03260   // no-op:  can't use ACE_NOTSUP_RETURN because there is no return value
03261 # endif /* ACE_HAS_PTHREADS */
03262 #else
03263 #endif /* ACE_HAS_THREADS */
03264 }
03265 
03266 ACE_INLINE void
03267 ACE_OS::thr_yield (void)
03268 {
03269   ACE_OS_TRACE ("ACE_OS::thr_yield");
03270 #if defined (ACE_HAS_THREADS)
03271 # if defined (ACE_HAS_PTHREADS)
03272   ::sched_yield ();
03273 # elif defined (ACE_HAS_STHREADS)
03274   ::thr_yield ();
03275 # elif defined (ACE_HAS_WTHREADS)
03276   ::Sleep (0);
03277 # elif defined (ACE_HAS_VXTHREADS)
03278   // An argument of 0 to ::taskDelay doesn't appear to yield the
03279   // current thread.
03280   // Now, it does seem to work.  The context_switch_time test
03281   // works fine with task_delay set to 0.
03282   ::taskDelay (0);
03283 # endif /* ACE_HAS_STHREADS */
03284 #else
03285   ;
03286 #endif /* ACE_HAS_THREADS */
03287 }
03288 
03289 ACE_INLINE int
03290 ACE_OS::thread_mutex_destroy (ACE_thread_mutex_t *m)
03291 {
03292   ACE_OS_TRACE ("ACE_OS::thread_mutex_destroy");
03293 #if defined (ACE_HAS_THREADS)
03294 # if defined (ACE_HAS_WTHREADS)
03295   ::DeleteCriticalSection (m);
03296   return 0;
03297 # else
03298   return ACE_OS::mutex_destroy (m);
03299 # endif /* ACE_HAS_WTHREADS */
03300 #else
03301   ACE_UNUSED_ARG (m);
03302   ACE_NOTSUP_RETURN (-1);
03303 
03304 #endif /* ACE_HAS_THREADS */
03305 }
03306 
03307 ACE_INLINE int
03308 ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
03309                            int lock_type,
03310                            const char *name,
03311                            ACE_mutexattr_t *arg)
03312 {
03313   // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
03314 #if defined (ACE_HAS_THREADS)
03315 # if defined (ACE_HAS_WTHREADS)
03316   ACE_UNUSED_ARG (lock_type);
03317   ACE_UNUSED_ARG (name);
03318   ACE_UNUSED_ARG (arg);
03319 
03320   ACE_SEH_TRY
03321     {
03322       ::InitializeCriticalSection (m);
03323     }
03324   ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
03325     {
03326       errno = ENOMEM;
03327       return -1;
03328     }
03329   return 0;
03330 
03331 # elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS)
03332   // Force the use of USYNC_THREAD!
03333   return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
03334 # elif defined (ACE_HAS_VXTHREADS)
03335   return mutex_init (m, lock_type, name, arg);
03336 
03337 # endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */
03338 
03339 #else
03340   ACE_UNUSED_ARG (m);
03341   ACE_UNUSED_ARG (lock_type);
03342   ACE_UNUSED_ARG (name);
03343   ACE_UNUSED_ARG (arg);
03344   ACE_NOTSUP_RETURN (-1);
03345 
03346 #endif /* ACE_HAS_THREADS */
03347 }
03348 
03349 #if defined (ACE_HAS_WCHAR)
03350 ACE_INLINE int
03351 ACE_OS::thread_mutex_init (ACE_thread_mutex_t *m,
03352                            int lock_type,
03353                            const wchar_t *name,
03354                            ACE_mutexattr_t *arg)
03355 {
03356   // ACE_OS_TRACE ("ACE_OS::thread_mutex_init");
03357 #if defined (ACE_HAS_THREADS)
03358 # if defined (ACE_HAS_WTHREADS)
03359   ACE_UNUSED_ARG (lock_type);
03360   ACE_UNUSED_ARG (name);
03361   ACE_UNUSED_ARG (arg);
03362 
03363   ACE_SEH_TRY
03364     {
03365       ::InitializeCriticalSection (m);
03366     }
03367   ACE_SEH_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
03368     {
03369       errno = ENOMEM;
03370       return -1;
03371     }
03372   return 0;
03373 
03374 # elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS)
03375   // Force the use of USYNC_THREAD!
03376   return ACE_OS::mutex_init (m, USYNC_THREAD, name, arg, 0, lock_type);
03377 # elif defined (ACE_HAS_VXTHREADS)
03378   return mutex_init (m, lock_type, name, arg);
03379 # endif /* ACE_HAS_STHREADS || ACE_HAS_PTHREADS */
03380 #else
03381   ACE_UNUSED_ARG (m);
03382   ACE_UNUSED_ARG (lock_type);
03383   ACE_UNUSED_ARG (name);
03384   ACE_UNUSED_ARG (arg);
03385   ACE_NOTSUP_RETURN (-1);
03386 
03387 #endif /* ACE_HAS_THREADS */
03388 }
03389 #endif /* ACE_HAS_WCHAR */
03390 
03391 ACE_INLINE int
03392 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m)
03393 {
03394   // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
03395 #if defined (ACE_HAS_THREADS)
03396 # if defined (ACE_HAS_WTHREADS)
03397   ::EnterCriticalSection (m);
03398   return 0;
03399 # else
03400   return ACE_OS::mutex_lock (m);
03401 # endif /* ACE_HAS_WTHREADS */
03402 #else
03403   ACE_UNUSED_ARG (m);
03404   ACE_NOTSUP_RETURN (-1);
03405 #endif /* ACE_HAS_THREADS */
03406 }
03407 
03408 ACE_INLINE int
03409 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
03410                            const ACE_Time_Value &timeout)
03411 {
03412   // ACE_OS_TRACE ("ACE_OS::thread_mutex_lock");
03413 
03414   // For all platforms, except MS Windows, this method is equivalent
03415   // to calling ACE_OS::mutex_lock() since ACE_thread_mutex_t and
03416   // ACE_mutex_t are the same type.  However, those typedefs evaluate
03417   // to different types on MS Windows.  The "thread mutex"
03418   // implementation in ACE for MS Windows cannot readily support
03419   // timeouts due to a lack of timeout features for this type of MS
03420   // Windows synchronization mechanism.
03421 
03422 #if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_WTHREADS)
03423   return ACE_OS::mutex_lock (m, timeout);
03424 #else
03425   ACE_UNUSED_ARG (m);
03426   ACE_UNUSED_ARG (timeout);
03427   ACE_NOTSUP_RETURN (-1);
03428 #endif /* ACE_HAS_THREADS */
03429 }
03430 
03431 ACE_INLINE int
03432 ACE_OS::thread_mutex_lock (ACE_thread_mutex_t *m,
03433                            const ACE_Time_Value *timeout)
03434 {
03435   return timeout == 0
03436     ? ACE_OS::thread_mutex_lock (m)
03437     : ACE_OS::thread_mutex_lock (m, *timeout);
03438 }
03439 
03440 ACE_INLINE int
03441 ACE_OS::thread_mutex_trylock (ACE_thread_mutex_t *m)
03442 {
03443   ACE_OS_TRACE ("ACE_OS::thread_mutex_trylock");
03444 
03445 #if defined (ACE_HAS_THREADS)
03446 # if defined (ACE_HAS_WTHREADS)
03447 #   if defined (ACE_HAS_WIN32_TRYLOCK)
03448   BOOL result = ::TryEnterCriticalSection (m);
03449   if (result == TRUE)
03450     return 0;
03451   else
03452     {
03453       errno = EBUSY;
03454       return -1;
03455     }
03456 #   else
03457   ACE_UNUSED_ARG (m);
03458   ACE_NOTSUP_RETURN (-1);
03459 #   endif /* ACE_HAS_WIN32_TRYLOCK */
03460 # elif defined (ACE_HAS_STHREADS) || defined (ACE_HAS_PTHREADS) || defined (ACE_VXWORKS)
03461   return ACE_OS::mutex_trylock (m);
03462 #endif /* Threads variety case */
03463 
03464 #else
03465   ACE_UNUSED_ARG (m);
03466   ACE_NOTSUP_RETURN (-1);
03467 #endif /* ACE_HAS_THREADS */
03468 }
03469 
03470 ACE_INLINE int
03471 ACE_OS::thread_mutex_unlock (ACE_thread_mutex_t *m)
03472 {
03473   ACE_OS_TRACE ("ACE_OS::thread_mutex_unlock");
03474 #if defined (ACE_HAS_THREADS)
03475 # if defined (ACE_HAS_WTHREADS)
03476   ::LeaveCriticalSection (m);
03477   return 0;
03478 # else
03479   return ACE_OS::mutex_unlock (m);
03480 # endif /* ACE_HAS_WTHREADS */
03481 #else
03482   ACE_UNUSED_ARG (m);
03483   ACE_NOTSUP_RETURN (-1);
03484 #endif /* ACE_HAS_THREADS */
03485 }
03486 
03487 /*****************************************************************************/
03488 
03489 # if defined (ACE_IS_SPLITTING)
03490 #   define ACE_SPECIAL_INLINE
03491 # else
03492 #   define ACE_SPECIAL_INLINE ACE_INLINE
03493 //#   define ACE_SPECIAL_INLINE inline
03494 # endif
03495 
03496 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
03497 
03498 ACE_INLINE
03499 int
03500 ACE_OS_Thread_Mutex_Guard::acquire (void)
03501 {
03502   return owner_ = ACE_OS::thread_mutex_lock (&lock_);
03503 }
03504 
03505 ACE_INLINE
03506 int
03507 ACE_OS_Thread_Mutex_Guard::release (void)
03508 {
03509   if (owner_ == -1)
03510     return 0;
03511   else
03512     {
03513       owner_ = -1;
03514       return ACE_OS::thread_mutex_unlock (&lock_);
03515     }
03516 }
03517 
03518 ACE_INLINE
03519 ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m)
03520   : lock_ (m), owner_ (-1)
03521 {
03522   if (!ACE_OS_Object_Manager::starting_up ())
03523     acquire ();
03524 }
03525 
03526 ACE_INLINE
03527 ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard ()
03528 {
03529   release ();
03530 }
03531 
03532 /*****************************************************************************/
03533 
03534 ACE_INLINE
03535 int
03536 ACE_OS_Recursive_Thread_Mutex_Guard::acquire (void)
03537 {
03538   return owner_ = ACE_OS::recursive_mutex_lock (&lock_);
03539 }
03540 
03541 ACE_INLINE
03542 int
03543 ACE_OS_Recursive_Thread_Mutex_Guard::release (void)
03544 {
03545   if (owner_ == -1)
03546     return 0;
03547   else
03548     {
03549       owner_ = -1;
03550       return ACE_OS::recursive_mutex_unlock (&lock_);
03551     }
03552 }
03553 
03554 ACE_INLINE
03555 ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard (
03556   ACE_recursive_thread_mutex_t &m)
03557    : lock_ (m),
03558      owner_ (-1)
03559 {
03560   if (!ACE_OS_Object_Manager::starting_up ())
03561     acquire ();
03562 }
03563 
03564 ACE_INLINE
03565 ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard ()
03566 {
03567   release ();
03568 }
03569 
03570 #endif /* ACE_MT_SAFE && ACE_MT_SAFE != 0 */
03571 
03572 
03573 /*****************************************************************************/
03574 
03575 ACE_INLINE
03576 ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id,
03577                               ACE_hthread_t thread_handle)
03578   : thread_id_ (thread_id),
03579     thread_handle_ (thread_handle)
03580 {
03581 }
03582 
03583 ACE_INLINE
03584 ACE_Thread_ID::ACE_Thread_ID (const ACE_Thread_ID &id)
03585   : thread_id_ (id.thread_id_),
03586     thread_handle_ (id.thread_handle_)
03587 {
03588 }
03589 
03590 ACE_INLINE
03591 ACE_Thread_ID::ACE_Thread_ID (void)
03592   : thread_id_ (ACE_OS::thr_self ())
03593 {
03594   ACE_OS::thr_self (thread_handle_);
03595 }
03596 
03597 ACE_INLINE
03598 ACE_thread_t
03599 ACE_Thread_ID::id (void) const
03600 {
03601   return this->thread_id_;
03602 }
03603 
03604 ACE_INLINE void
03605 ACE_Thread_ID::id (ACE_thread_t thread_id)
03606 {
03607   this->thread_id_ = thread_id;
03608 }
03609 
03610 ACE_INLINE ACE_hthread_t
03611 ACE_Thread_ID::handle (void) const
03612 {
03613   return this->thread_handle_;
03614 }
03615 
03616 ACE_INLINE void
03617 ACE_Thread_ID::handle (ACE_hthread_t thread_handle)
03618 {
03619   this->thread_handle_ = thread_handle;
03620 }
03621 
03622 ACE_INLINE bool
03623 ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const
03624 {
03625   return
03626     ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_)
03627     && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_);
03628 }
03629 
03630 ACE_INLINE bool
03631 ACE_Thread_ID::operator!= (const ACE_Thread_ID &rhs) const
03632 {
03633   return !(*this == rhs);
03634 }
03635 
03636 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:41 2010 for ACE by  doxygen 1.4.7