OS_NS_Thread.inl

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

Generated on Sun Jan 27 12:05:33 2008 for ACE by doxygen 1.3.6