OS_NS_Thread.inl

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

Generated on Thu Nov 9 09:41:58 2006 for ACE by doxygen 1.3.6