OS_NS_Thread.cpp

Go to the documentation of this file.
00001 #include "ace/OS_NS_Thread.h"
00002 
00003 ACE_RCSID (ace,
00004            OS_NS_Thread,
00005            "OS_NS_Thread.cpp,v 1.79 2006/06/07 08:23:48 jwillemsen Exp")
00006 
00007 #if !defined (ACE_HAS_INLINED_OSCALLS)
00008 # include "ace/OS_NS_Thread.inl"
00009 #endif /* ACE_HAS_INLINED_OS_CALLS */
00010 
00011 #include "ace/OS_NS_stdio.h"
00012 #include "ace/Sched_Params.h"
00013 #include "ace/OS_Memory.h"
00014 #include "ace/OS_Thread_Adapter.h"
00015 #include "ace/Min_Max.h"
00016 #include "ace/Object_Manager_Base.h"
00017 #include "ace/OS_NS_errno.h"
00018 #include "ace/OS_NS_ctype.h"
00019 #include "ace/Log_Msg.h" // for ACE_ASSERT
00020 // This is necessary to work around nasty problems with MVS C++.
00021 #include "ace/Auto_Ptr.h"
00022 #include "ace/Thread_Mutex.h"
00023 #include "ace/Condition_T.h"
00024 #include "ace/Guard_T.h"
00025 
00026 extern "C" void
00027 ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args)
00028 {
00029   ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::mutex_lock_cleanup (args);
00030 }
00031 
00032 
00033 #if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
00034 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
00035        (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID)
00036 #elif defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
00037 
00038 struct __IBMCPP__thread_params {
00039   __IBMCPP__thread_params(ACE_THR_C_FUNC e, LPVOID a)
00040     :entry_point(e),args(a) {}
00041   ACE_THR_C_FUNC entry_point;
00042   LPVOID args;
00043 };
00044 
00045 # pragma handler(initThread)
00046 extern "C" DWORD __stdcall __IBMCPP__initThread(void *arg)
00047 {
00048   // Must reset 387 since using CreateThread
00049   _fpreset();
00050 
00051   // Dispatch user function...
00052   auto_ptr<__IBMCPP__thread_params> parms((__IBMCPP__thread_params *)arg);
00053   (*parms->entry_point)(parms->args);
00054   _endthread();
00055   return 0;
00056 }
00057 
00058 HANDLE WINAPI __IBMCPP__beginthreadex(void *stack,
00059                                       DWORD stacksize,
00060                                       ACE_THR_C_FUNC entry_point,
00061                                       LPVOID args,
00062                                       DWORD flags,
00063                                       LPDWORD thr_id)
00064 {
00065   return  CreateThread(0,
00066                        stacksize,
00067                        (LPTHREAD_START_ROUTINE)__IBMCPP__initThread,
00068                        new __IBMCPP__thread_params(entry_point, args),
00069                        flags,
00070                        thr_id);
00071 }
00072 
00073 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
00074              __IBMCPP__beginthreadex(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID)
00075 
00076 #elif defined (ACE_HAS_WINCE) && defined (UNDER_CE) && (UNDER_CE >= 211)
00077 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
00078       CreateThread (0, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & CREATE_SUSPENDED, (unsigned long *) THR_ID)
00079 #elif defined(ACE_HAS_WTHREADS)
00080   // Green Hills compiler gets confused when __stdcall is imbedded in
00081   // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
00082   // instead.
00083   typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*);
00084 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
00085       ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
00086 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
00087 
00088 /*****************************************************************************/
00089 
00090 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00091 
00092 void
00093 ACE_Thread_ID::to_string (char *thr_string) const
00094 {
00095   char format[128]; // Converted format string
00096   char *fp = 0;     // Current format pointer
00097   fp = format;
00098   *fp++ = '%';   // Copy in the %
00099 
00100 #if defined (ACE_WIN32)
00101   ACE_OS::strcpy (fp, "u");
00102   ACE_OS::sprintf (thr_string,
00103                    format,
00104                    static_cast <unsigned> (thread_id_));
00105 #elif defined (ACE_AIX_VERS) && (ACE_AIX_VERS <= 402)
00106                   // AIX's pthread_t (ACE_hthread_t) is a pointer, and it's
00107                   // a little ugly to send that through a %u format.  So,
00108                   // get the kernel thread ID (tid_t) via thread_self() and
00109                   // display that instead.
00110                   // This isn't conditionalized on ACE_HAS_THREAD_SELF because
00111                   // 1. AIX 4.2 doesn't have that def anymore (it messes up
00112                   //    other things)
00113                   // 2. OSF/1 V3.2 has that def, and I'm not sure what affect
00114                   //   this would have on that.
00115                   // -Steve Huston, 19-Aug-97
00116                   ACE_OS::strcpy (fp, "u");
00117                   ACE_OS::sprintf (thr_string, format, thread_id_);
00118 #elif defined (DIGITAL_UNIX)
00119                   ACE_OS::strcpy (fp, "u");
00120                   ACE_OS::sprintf (thr_string, format,
00121 #  if defined (ACE_HAS_THREADS)
00122                                    thread_id_
00123 #  else
00124                                    thread_id_
00125 #  endif /* ACE_HAS_THREADS */
00126                                           );
00127 #else
00128 
00129 #  if defined (ACE_MVS) || defined (ACE_TANDEM_T1248_PTHREADS)
00130                   // MVS's pthread_t is a struct... yuck. So use the ACE 5.0
00131                   // code for it.
00132                   ACE_OS::strcpy (fp, "u");
00133                   ACE_OS::sprintf (thr_string, format, thread_handle_);
00134 #  else
00135                   // Yes, this is an ugly C-style cast, but the
00136                   // correct C++ cast is different depending on
00137                   // whether the t_id is an integral type or a pointer
00138                   // type. FreeBSD uses a pointer type, but doesn't
00139                   // have a _np function to get an integral type, like
00140                   // the OSes above.
00141                   ACE_OS::strcpy (fp, "lu");
00142                   ACE_OS::sprintf (thr_string,
00143                                    format,
00144                                    (unsigned long) thread_handle_);
00145 #  endif /* ACE_MVS || ACE_TANDEM_T1248_PTHREADS */
00146 
00147 #endif /* ACE_WIN32 */
00148 }
00149 
00150 /*****************************************************************************/
00151 
00152 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
00153 
00154 #if defined (ACE_HAS_TSS_EMULATION)
00155 u_int ACE_TSS_Emulation::total_keys_ = 0;
00156 
00157 ACE_TSS_Keys* ACE_TSS_Emulation::tss_keys_used_ = 0;
00158 
00159 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
00160 ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]
00161  = { 0 };
00162 
00163 #  if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
00164 
00165 int ACE_TSS_Emulation::key_created_ = 0;
00166 
00167 ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_;
00168 
00169 /* static */
00170 #    if defined (ACE_HAS_THR_C_FUNC)
00171 extern "C"
00172 void
00173 ACE_TSS_Emulation_cleanup (void *ptr)
00174 {
00175    ACE_UNUSED_ARG (ptr);
00176    // Really this must be used for ACE_TSS_Emulation code to make the TSS
00177    // cleanup
00178 }
00179 #    else
00180 void
00181 ACE_TSS_Emulation_cleanup (void *ptr)
00182 {
00183    ACE_UNUSED_ARG (ptr);
00184    // Really this must be used for ACE_TSS_Emulation code to make the TSS
00185    // cleanup
00186 }
00187 #    endif /* ACE_HAS_THR_C_FUNC */
00188 
00189 void **
00190 ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created)
00191 {
00192   // TSS Singleton implementation.
00193 
00194   // Create the one native TSS key, if necessary.
00195   if (key_created_ == 0)
00196     {
00197       // Double-checked lock . . .
00198       ACE_TSS_BASE_GUARD
00199 
00200       if (key_created_ == 0)
00201         {
00202           ACE_NO_HEAP_CHECK;
00203           if (ACE_OS::thr_keycreate_native (&native_tss_key_,
00204                                      &ACE_TSS_Emulation_cleanup) != 0)
00205             {
00206               ACE_ASSERT (0);
00207               return 0; // Major problems, this should *never* happen!
00208             }
00209           key_created_ = 1;
00210         }
00211     }
00212 
00213   void **old_ts_storage = 0;
00214 
00215   // Get the tss_storage from thread-OS specific storage.
00216   if (ACE_OS::thr_getspecific_native (native_tss_key_,
00217                                (void **) &old_ts_storage) == -1)
00218     {
00219       ACE_ASSERT (false);
00220       return 0; // This should not happen!
00221     }
00222 
00223   // Check to see if this is the first time in for this thread.
00224   // This block can also be entered after a fork () in the child process,
00225   // at least on Pthreads Draft 4 platforms.
00226   if (old_ts_storage == 0)
00227     {
00228       if (ts_created)
00229         *ts_created = 1u;
00230 
00231       // Use the ts_storage passed as argument, if non-zero.  It is
00232       // possible that this has been implemented in the stack. At the
00233       // moment, this is unknown.  The cleanup must not do nothing.
00234       // If ts_storage is zero, allocate (and eventually leak) the
00235       // storage array.
00236       if (ts_storage == 0)
00237         {
00238           ACE_NO_HEAP_CHECK;
00239 
00240           ACE_NEW_RETURN (ts_storage,
00241                           void*[ACE_TSS_THREAD_KEYS_MAX],
00242                           0);
00243 
00244           // Zero the entire TSS array.  Do it manually instead of
00245           // using memset, for optimum speed.  Though, memset may be
00246           // faster :-)
00247           void **tss_base_p = ts_storage;
00248 
00249           for (u_int i = 0;
00250                i < ACE_TSS_THREAD_KEYS_MAX;
00251                ++i)
00252             *tss_base_p++ = 0;
00253         }
00254 
00255        // Store the pointer in thread-specific storage.  It gets
00256        // deleted via the ACE_TSS_Emulation_cleanup function when the
00257        // thread terminates.
00258        if (ACE_OS::thr_setspecific_native (native_tss_key_,
00259                                     (void *) ts_storage) != 0)
00260           {
00261             ACE_ASSERT (false);
00262             return 0; // This should not happen!
00263           }
00264     }
00265   else
00266     if (ts_created)
00267       ts_created = 0;
00268 
00269   return ts_storage  ?  ts_storage  :  old_ts_storage;
00270 }
00271 #  endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
00272 
00273 u_int
00274 ACE_TSS_Emulation::total_keys ()
00275 {
00276   ACE_OS_Recursive_Thread_Mutex_Guard (
00277     *static_cast <ACE_recursive_thread_mutex_t *>
00278                       (ACE_OS_Object_Manager::preallocated_object[
00279                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
00280 
00281   return total_keys_;
00282 }
00283 
00284 int
00285 ACE_TSS_Emulation::next_key (ACE_thread_key_t &key)
00286 {
00287   ACE_OS_Recursive_Thread_Mutex_Guard (
00288     *static_cast <ACE_recursive_thread_mutex_t *>
00289                       (ACE_OS_Object_Manager::preallocated_object[
00290                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
00291 
00292   // Initialize the tss_keys_used_ pointer on first use.
00293   if (tss_keys_used_ == 0)
00294     {
00295       ACE_NEW_RETURN (tss_keys_used_, ACE_TSS_Keys, -1);
00296     }
00297 
00298   if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX)
00299     {
00300        u_int counter = 0;
00301        // Loop through all possible keys and check whether a key is free
00302        for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++)
00303          {
00304             ACE_thread_key_t localkey;
00305 #  if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
00306               ACE_OS::memset (&localkey, 0, sizeof (ACE_thread_key_t));
00307               ACE_OS::memcpy (&localkey, &counter_, sizeof (u_int));
00308 #  else
00309               localkey = counter;
00310 #  endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
00311             // If the key is not set as used, we can give out this key, if not
00312             // we have to search further
00313             if (tss_keys_used_->is_set(localkey) == 0)
00314             {
00315                tss_keys_used_->test_and_set(localkey);
00316                key = localkey;
00317                break;
00318             }
00319          }
00320 
00321       ++total_keys_;
00322       return 0;
00323     }
00324   else
00325     {
00326       key = ACE_OS::NULL_key;
00327       return -1;
00328     }
00329 }
00330 
00331 int
00332 ACE_TSS_Emulation::release_key (ACE_thread_key_t key)
00333 {
00334   ACE_OS_Recursive_Thread_Mutex_Guard (
00335     *static_cast <ACE_recursive_thread_mutex_t *>
00336                       (ACE_OS_Object_Manager::preallocated_object[
00337                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
00338 
00339   if (tss_keys_used_ != 0 &&
00340       tss_keys_used_->test_and_clear (key) == 0)
00341   {
00342     --total_keys_;
00343     return 0;
00344   }
00345   return 1;
00346 }
00347 
00348 int
00349 ACE_TSS_Emulation::is_key (ACE_thread_key_t key)
00350 {
00351   ACE_OS_Recursive_Thread_Mutex_Guard (
00352     *static_cast <ACE_recursive_thread_mutex_t *>
00353                       (ACE_OS_Object_Manager::preallocated_object[
00354                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
00355 
00356   if (tss_keys_used_ != 0 &&
00357       tss_keys_used_->is_set (key) == 1)
00358   {
00359     return 1;
00360   }
00361   return 0;
00362 }
00363 
00364 void *
00365 ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX])
00366 {
00367 #    if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
00368         // On VxWorks, in particular, don't check to see if the field
00369         // is 0.  It isn't always, specifically, when a program is run
00370         // directly by the shell (without spawning a new task) after
00371         // another program has been run.
00372 
00373   u_int ts_created = 0;
00374   tss_base (ts_storage, &ts_created);
00375   if (ts_created)
00376     {
00377 #    else  /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
00378       tss_base () = ts_storage;
00379 #    endif
00380 
00381       // Zero the entire TSS array.  Do it manually instead of using
00382       // memset, for optimum speed.  Though, memset may be faster :-)
00383       void **tss_base_p = tss_base ();
00384       for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
00385         {
00386           *tss_base_p = 0;
00387         }
00388 
00389       return tss_base ();
00390 #    if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
00391     }
00392   else
00393     {
00394       return 0;
00395     }
00396 #    endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
00397 }
00398 
00399 void
00400 ACE_TSS_Emulation::tss_close ()
00401 {
00402 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
00403   ACE_OS::thr_keyfree_native (native_tss_key_);
00404 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
00405 }
00406 
00407 #endif /* ACE_HAS_TSS_EMULATION */
00408 
00409 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
00410 
00411 /*****************************************************************************/
00412 
00413 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
00414 
00415 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
00416 // the single file of template instantiations.
00417 
00418 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id)
00419   : tid_(id)
00420 {
00421   ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
00422 }
00423 
00424 ACE_TSS_Ref::ACE_TSS_Ref (void)
00425 {
00426   ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
00427 }
00428 
00429 // Check for equality.
00430 bool
00431 ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const
00432 {
00433   ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
00434 
00435   return this->tid_ == info.tid_;
00436 }
00437 
00438 // Check for inequality.
00439 ACE_SPECIAL_INLINE
00440 bool
00441 ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
00442 {
00443   ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
00444 
00445   return !(*this == tss_ref);
00446 }
00447 
00448 // moved class ACE_TSS_Info declaration
00449 // to OS.h so it can be visible to the
00450 // single file of template instantiations
00451 
00452 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
00453                             ACE_TSS_Info::Destructor dest)
00454   : key_ (key),
00455     destructor_ (dest),
00456     thread_count_ (-1)
00457 {
00458   ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
00459 }
00460 
00461 ACE_TSS_Info::ACE_TSS_Info (void)
00462   : key_ (ACE_OS::NULL_key),
00463     destructor_ (0),
00464     thread_count_ (-1)
00465 {
00466   ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
00467 }
00468 
00469 # if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
00470 static inline bool operator== (const ACE_thread_key_t &lhs,
00471                                const ACE_thread_key_t &rhs)
00472 {
00473   return ! ACE_OS::memcmp (&lhs, &rhs, sizeof (ACE_thread_key_t));
00474 }
00475 
00476 static inline bool operator!= (const ACE_thread_key_t &lhs,
00477                                const ACE_thread_key_t &rhs)
00478 {
00479   return ! (lhs == rhs);
00480 }
00481 # endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
00482 
00483 // Check for equality.
00484 bool
00485 ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const
00486 {
00487   ACE_OS_TRACE ("ACE_TSS_Info::operator==");
00488 
00489   return this->key_ == info.key_;
00490 }
00491 
00492 // Check for inequality.
00493 bool
00494 ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const
00495 {
00496   ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
00497 
00498   return !(*this == info);
00499 }
00500 
00501 void
00502 ACE_TSS_Info::dump (void)
00503 {
00504 # if defined (ACE_HAS_DUMP)
00505   //  ACE_OS_TRACE ("ACE_TSS_Info::dump");
00506 
00507 #   if 0
00508   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00509   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("key_ = %u\n"), this->key_));
00510   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("destructor_ = %u\n"), this->destructor_));
00511   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00512 #   endif /* 0 */
00513 # endif /* ACE_HAS_DUMP */
00514 }
00515 
00516 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
00517 // to the single file of template instantiations.
00518 
00519 ACE_TSS_Keys::ACE_TSS_Keys (void)
00520 {
00521   for (u_int i = 0; i < ACE_WORDS; ++i)
00522     {
00523       key_bit_words_[i] = 0;
00524     }
00525 }
00526 
00527 ACE_SPECIAL_INLINE
00528 void
00529 ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit)
00530 {
00531   word = key / ACE_BITS_PER_WORD;
00532   bit = key % ACE_BITS_PER_WORD;
00533 }
00534 
00535 int
00536 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key)
00537 {
00538   ACE_KEY_INDEX (key_index, key);
00539   u_int word, bit;
00540   find (key_index, word, bit);
00541 
00542   if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
00543     {
00544       return 1;
00545     }
00546   else
00547     {
00548       ACE_SET_BITS (key_bit_words_[word], 1 << bit);
00549       return 0;
00550     }
00551 }
00552 
00553 int
00554 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key)
00555 {
00556   ACE_KEY_INDEX (key_index, key);
00557   u_int word, bit;
00558   find (key_index, word, bit);
00559 
00560   if (word < ACE_WORDS && ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
00561     {
00562       ACE_CLR_BITS (key_bit_words_[word], 1 << bit);
00563       return 0;
00564     }
00565   else
00566     {
00567       return 1;
00568     }
00569 }
00570 
00571 int
00572 ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
00573 {
00574   ACE_KEY_INDEX (key_index, key);
00575   u_int word, bit;
00576   find (key_index, word, bit);
00577 
00578   return word < ACE_WORDS ? ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit) : 0;
00579 }
00580 
00581 /**
00582  * @class ACE_TSS_Cleanup
00583  * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
00584  */
00585 class ACE_TSS_Cleanup
00586 {
00587 public:
00588   /// Register a newly-allocated key
00589   /// @param key the key to be monitored
00590   /// @param destructor the function to call to delete objects stored via this key
00591   int insert (ACE_thread_key_t key, void (*destructor)(void *));
00592 
00593   /// Mark a key as being used by this thread.
00594   void thread_use_key (ACE_thread_key_t key);
00595 
00596   /// This thread is no longer using this key
00597   /// call destructor if appropriate
00598   int thread_detach_key (ACE_thread_key_t key);
00599 
00600   /// This key is no longer used
00601   ///   Release key if use count == 0
00602   ///   fail if use_count != 0;
00603   /// @param key the key to be released
00604   int free_key (ACE_thread_key_t key);
00605 
00606   /// Cleanup the thread-specific objects.  Does _NOT_ exit the thread.
00607   /// For each used key perform the same actions as free_key.
00608   void thread_exit (void);
00609 
00610 private:
00611   void dump (void);
00612 
00613   /// Release a key used by this thread
00614   /// @param info reference to the info for this key
00615   /// @param destructor out arg to receive destructor function ptr
00616   /// @param tss_obj out arg to receive pointer to deletable object
00617   void thread_release (
00618           ACE_TSS_Info &info,
00619           ACE_TSS_Info::Destructor & destructor,
00620           void *& tss_obj);
00621 
00622   /// remove key if it's unused (thread_count == 0)
00623   /// @param info reference to the info for this key
00624   int remove_key (ACE_TSS_Info &info);
00625 
00626   /// Find the TSS keys (if any) for this thread.
00627   /// @param thread_keys reference to pointer to be filled in by this function.
00628   /// @return false if keys don't exist.
00629   bool find_tss_keys (ACE_TSS_Keys *& thread_keys) const;
00630 
00631   /// Accessor for this threads ACE_TSS_Keys instance.
00632   /// Creates the keys if necessary.
00633   ACE_TSS_Keys *tss_keys ();
00634 
00635   /// Ensure singleton.
00636   ACE_TSS_Cleanup (void);
00637   ~ACE_TSS_Cleanup (void);
00638 
00639   /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
00640   friend class TSS_Cleanup_Instance;
00641 
00642 private:
00643   // Array of <ACE_TSS_Info> objects.
00644   typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS];
00645   typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR;
00646 
00647   /// Table of <ACE_TSS_Info>'s.
00648   ACE_TSS_TABLE table_;
00649 
00650   /// Key for the thread-specific ACE_TSS_Keys
00651   /// Used by find_tss_keys() or tss_keys() to find the
00652   /// bit array that records whether each TSS key is in
00653   /// use by this thread.
00654   ACE_thread_key_t in_use_;
00655 };
00656 
00657 
00658 /*****************************************************************************/
00659 /**
00660  * @class TSS_Cleanup_Instance
00661  * @A class to manage an instance pointer to ACE_TSS_Cleanup.
00662  * Note: that the double checked locking pattern doesn't allow
00663  * safe deletion.
00664  * Callers who wish to access the singleton ACE_TSS_Cleanup must
00665  * do so by instantiating a TSS_Cleanup_Instance, calling the valid
00666  * method to be sure the ACE_TSS_Cleanup is available, then using
00667  * the TSS_Cleanup_Instance as a pointer to the instance.
00668  * Construction argument to the TSS_Cleanup_Instance determines how
00669  * it is to be used:
00670  *   CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
00671  *   USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
00672  *   DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
00673  *   delete it when the TSS_Cleanup_Instance goes out of scope.
00674  */
00675 
00676 class TSS_Cleanup_Instance
00677 {
00678 public:
00679   enum Purpose
00680   {
00681     CREATE,
00682     USE,
00683     DESTROY
00684   };
00685   TSS_Cleanup_Instance (Purpose purpose = USE);
00686   ~TSS_Cleanup_Instance();
00687 
00688   bool valid();
00689   ACE_TSS_Cleanup * operator ->();
00690 
00691 private:
00692 
00693   ACE_TSS_Cleanup * operator *();
00694 
00695 private:
00696   static unsigned int reference_count_;
00697   static ACE_TSS_Cleanup * instance_;
00698   static ACE_Thread_Mutex* mutex_;
00699   static ACE_Thread_Condition<ACE_Thread_Mutex>* condition_;
00700 
00701 private:
00702   ACE_TSS_Cleanup * ptr_;
00703   unsigned short flags_;
00704   enum
00705   {
00706     FLAG_DELETING = 1,
00707     FLAG_VALID_CHECKED = 2
00708   };
00709 };
00710 
00711 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose)
00712   : ptr_(0)
00713   , flags_(0)
00714 {
00715   // During static construction or construction of the ACE_Object_Manager,
00716   // there can be only one thread in this constructor at any one time, so
00717   // it's safe to check for a zero mutex_.  If it's zero, we create a new
00718   // mutex and condition variable.
00719   if (mutex_ == 0)
00720     {
00721       ACE_NEW (mutex_, ACE_Thread_Mutex ());
00722       ACE_NEW (condition_, ACE_Thread_Condition<ACE_Thread_Mutex> (*mutex_));
00723     }
00724 
00725   ACE_Guard<ACE_Thread_Mutex> guard(*mutex_);
00726 
00727   if (purpose == CREATE)
00728   {
00729     if (instance_ == 0)
00730     {
00731       instance_ = new ACE_TSS_Cleanup();
00732     }
00733     ptr_ = instance_;
00734     ++reference_count_;
00735   }
00736   else if(purpose == DESTROY)
00737   {
00738     if (instance_ != 0)
00739     {
00740       ptr_ = instance_;
00741       instance_ = 0;
00742       ACE_SET_BITS(flags_, FLAG_DELETING);
00743       while (reference_count_ > 0)
00744       {
00745         condition_->wait();
00746       }
00747     }
00748   }
00749   else // must be normal use
00750   {
00751     ACE_ASSERT(purpose == USE);
00752     if (instance_ != 0)
00753       {
00754         ptr_ = instance_;
00755         ++reference_count_;
00756       }
00757   }
00758 }
00759 
00760 TSS_Cleanup_Instance::~TSS_Cleanup_Instance (void)
00761 {
00762   // Variable to hold the mutex_ to delete outside the scope of the
00763   // guard.
00764   ACE_Thread_Mutex *del_mutex = 0;
00765 
00766   // scope the guard
00767   {
00768     ACE_Guard<ACE_Thread_Mutex> guard (*mutex_);
00769     if (ptr_ != 0)
00770       {
00771         if (ACE_BIT_ENABLED (flags_, FLAG_DELETING))
00772           {
00773             ACE_ASSERT(instance_ == 0);
00774             ACE_ASSERT(reference_count_ == 0);
00775             delete ptr_;
00776             del_mutex = mutex_ ;
00777             mutex_ = 0;
00778           }
00779         else
00780           {
00781             ACE_ASSERT (reference_count_ > 0);
00782             --reference_count_;
00783             if (reference_count_ == 0 && instance_ == NULL)
00784               condition_->signal ();
00785           }
00786       }
00787   }// end of guard scope
00788 
00789   if (del_mutex != 0)
00790     {
00791       delete condition_;
00792       condition_ = 0;
00793       delete del_mutex;
00794     }
00795 }
00796 
00797 bool
00798 TSS_Cleanup_Instance::valid()
00799 {
00800   ACE_SET_BITS(flags_, FLAG_VALID_CHECKED);
00801   return (this->instance_ != NULL);
00802 }
00803 
00804 ACE_TSS_Cleanup *
00805 TSS_Cleanup_Instance::operator *()
00806 {
00807   ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
00808   return instance_;
00809 }
00810 
00811 ACE_TSS_Cleanup *
00812 TSS_Cleanup_Instance::operator ->()
00813 {
00814   ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
00815   return instance_;
00816 }
00817 
00818 // = Static object initialization.
00819 unsigned int TSS_Cleanup_Instance::reference_count_ = 0;
00820 ACE_TSS_Cleanup * TSS_Cleanup_Instance::instance_ = 0;
00821 ACE_Thread_Mutex* TSS_Cleanup_Instance::mutex_ = 0;
00822 ACE_Thread_Condition<ACE_Thread_Mutex>* TSS_Cleanup_Instance::condition_ = 0;
00823 
00824 ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void)
00825 {
00826 }
00827 
00828 void
00829 ACE_TSS_Cleanup::thread_exit (void)
00830 {
00831   ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
00832   // variables to hold the destructors
00833   // and pointers to the object to be destructed
00834   // the actual destruction is deferred until the guard is released
00835   ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
00836   void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
00837   // count of items to be destroyed
00838   unsigned int d_count = 0;
00839 
00840   // scope the guard
00841   {
00842     ACE_TSS_CLEANUP_GUARD
00843 
00844     // if not initialized or already cleaned up
00845     ACE_TSS_Keys *this_thread_keys = 0;
00846     if (! find_tss_keys (this_thread_keys) )
00847       {
00848         return;
00849       }
00850 
00851     // Minor hack: Iterating in reverse order means the LOG buffer which is
00852     // accidentally allocated first will be accidentally deallocated (almost)
00853     // last -- in case someone logs something from the other destructors.
00854     // applications should not count on this behavior because platforms which
00855     // do not use ACE_TSS_Cleanup may delete objects in other orders.
00856     unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
00857     while( key_index > 0)
00858       {
00859         --key_index;
00860         ACE_TSS_Info & info = this->table_[key_index];
00861         // if this key is in use by this thread
00862         if (info.key_in_use () && this_thread_keys->is_set(info.key_))
00863           {
00864             // defer deleting the in-use key until all others have been deleted
00865             if(info.key_ != this->in_use_)
00866               {
00867                 destructor[d_count] = 0;
00868                 tss_obj[d_count] = 0;
00869                 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
00870                 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
00871                   {
00872                     ++d_count;
00873                   }
00874               }
00875           }
00876       }
00877 
00878     // remove the in_use bit vector last
00879     ACE_KEY_INDEX (use_index, this->in_use_);
00880     ACE_TSS_Info & info = this->table_[use_index];
00881     destructor[d_count] = 0;
00882     tss_obj[d_count] = 0;
00883     this->thread_release (info, destructor[d_count], tss_obj[d_count]);
00884     if (destructor[d_count] != 0 &&  tss_obj[d_count] != 0)
00885       {
00886         ++d_count;
00887       }
00888 #if defined (ACE_HAS_TSS_EMULATION)
00889     ACE_TSS_Emulation::ts_object (this->in_use_) = 0;
00890 #else // defined (ACE_HAS_TSS_EMULATION)
00891     ACE_OS::thr_setspecific_native (info.key_, 0);
00892 #endif // defined (ACE_HAS_TSS_EMULATION)
00893 
00894   } // end of guard scope
00895   for (unsigned int d_index = 0; d_index < d_count; ++d_index)
00896     {
00897       (*destructor[d_index])(tss_obj[d_index]);
00898     }
00899 }
00900 
00901 extern "C" void
00902 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
00903 {
00904   delete static_cast <ACE_TSS_Keys *> (tss_keys);
00905 }
00906 
00907 ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
00908   : in_use_ (ACE_OS::NULL_key)
00909 {
00910   ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
00911 }
00912 
00913 int
00914 ACE_TSS_Cleanup::insert (ACE_thread_key_t key,
00915                          void (*destructor)(void *))
00916 {
00917   ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
00918   ACE_TSS_CLEANUP_GUARD
00919 
00920   ACE_KEY_INDEX (key_index, key);
00921   ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
00922   if (key_index < ACE_DEFAULT_THREAD_KEYS)
00923     {
00924       ACE_ASSERT (table_[key_index].thread_count_ == -1);
00925       table_[key_index] = ACE_TSS_Info (key, destructor);
00926       table_[key_index].thread_count_ = 0; // inserting it does not use it
00927                                            // but it does "allocate" it
00928       return 0;
00929     }
00930   else
00931     {
00932       return -1;
00933     }
00934 }
00935 
00936 int
00937 ACE_TSS_Cleanup::free_key (ACE_thread_key_t key)
00938 {
00939   ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
00940   ACE_TSS_CLEANUP_GUARD
00941   ACE_KEY_INDEX (key_index, key);
00942   if (key_index < ACE_DEFAULT_THREAD_KEYS)
00943     {
00944       return remove_key (this->table_ [key_index]);
00945     }
00946   return -1;
00947 }
00948 
00949 int
00950 ACE_TSS_Cleanup::remove_key (ACE_TSS_Info &info)
00951 {
00952   // assume CLEANUP_GUARD is held by caller
00953   ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
00954 
00955 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
00956       // When this is done, any existing TSS objects controlled by this key are leaked
00957       // There is no "right thing" to do in this case
00958 
00959   // only remove it if all threads are done with it
00960   if (info.thread_count_ != 0)
00961     {
00962       return -1;
00963     }
00964 #endif // 0
00965 
00966 #if !defined (ACE_HAS_TSS_EMULATION)
00967   ACE_OS_thread_key_t temp_key = info.key_;
00968   ACE_OS::thr_keyfree_native (temp_key);
00969 #endif /* !ACE_HAS_TSS_EMULATION */
00970   if (info.key_ == this->in_use_)
00971     {
00972       this->in_use_ = ACE_OS::NULL_key;
00973     }
00974   info.key_in_use (0);
00975   info.destructor_ = 0;
00976   return 0;
00977 }
00978 
00979 int
00980 ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key)
00981 {
00982   // variables to hold the destructor and the object to be destructed
00983   // the actual call is deferred until the guard is released
00984   ACE_TSS_Info::Destructor destructor = 0;
00985   void * tss_obj = 0;
00986 
00987   // scope the guard
00988   {
00989     ACE_TSS_CLEANUP_GUARD
00990 
00991     ACE_KEY_INDEX (key_index, key);
00992     ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0])
00993         && this->table_[key_index].key_ == key);
00994     ACE_TSS_Info &info = this->table_ [key_index];
00995 
00996     // sanity check
00997     if (!info.key_in_use ())
00998       {
00999         return -1;
01000       }
01001 
01002     this->thread_release (info, destructor, tss_obj);
01003   } // end of scope for the Guard
01004   // if there's a destructor and an object to be destroyed
01005   if (destructor != 0 && tss_obj != 0)
01006     {
01007       (*destructor) (tss_obj);
01008     }
01009   return 0;
01010 }
01011 
01012 void
01013 ACE_TSS_Cleanup::thread_release (
01014         ACE_TSS_Info &info,
01015         ACE_TSS_Info::Destructor & destructor,
01016         void *& tss_obj)
01017 {
01018   // assume guard is held by caller
01019   // Find the TSS keys (if any) for this thread
01020   // do not create them if they don't exist
01021   ACE_TSS_Keys * thread_keys = 0;
01022   if (find_tss_keys (thread_keys))
01023     {
01024         // if this key is in use by this thread
01025       if (thread_keys->test_and_clear(info.key_) == 0)
01026       {
01027         // save destructor & pointer to tss object
01028         // until after the guard is released
01029         destructor = info.destructor_;
01030         ACE_OS::thr_getspecific (info.key_, &tss_obj);
01031         ACE_ASSERT (info.thread_count_ > 0);
01032         --info.thread_count_;
01033       }
01034     }
01035 }
01036 
01037 void
01038 ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key)
01039 {
01040   // If the key's ACE_TSS_Info in-use bit for this thread is not set,
01041   // set it and increment the key's thread_count_.
01042   if (! tss_keys ()->test_and_set (key))
01043     {
01044       ACE_TSS_CLEANUP_GUARD
01045 
01046       // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
01047       ACE_KEY_INDEX (key_index, key);
01048       ACE_TSS_Info &key_info = this->table_ [key_index];
01049 
01050       ACE_ASSERT (key_info.key_in_use ());
01051       ++key_info.thread_count_;
01052     }
01053 }
01054 
01055 void
01056 ACE_TSS_Cleanup::dump (void)
01057 {
01058 # if defined (ACE_HAS_DUMP)
01059   // Iterate through all the thread-specific items and dump them all.
01060 
01061   ACE_TSS_TABLE_ITERATOR key_info = table_;
01062   for (unsigned int i = 0;
01063        i < ACE_DEFAULT_THREAD_KEYS;
01064        ++key_info, ++i)
01065     key_info->dump ();
01066 # endif /* ACE_HAS_DUMP */
01067 }
01068 
01069 bool
01070 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys *& tss_keys) const
01071 {
01072   if (this->in_use_ == ACE_OS::NULL_key)
01073     return false;
01074   if (ACE_OS::thr_getspecific (in_use_,
01075           reinterpret_cast<void **> (&tss_keys)) == -1)
01076     {
01077       ACE_ASSERT (false);
01078       return false; // This should not happen!
01079     }
01080   return tss_keys != 0;
01081 }
01082 
01083 ACE_TSS_Keys *
01084 ACE_TSS_Cleanup::tss_keys ()
01085 {
01086   if (this->in_use_ == ACE_OS::NULL_key)
01087     {
01088       ACE_TSS_CLEANUP_GUARD
01089       // Double-check;
01090       if (in_use_ == ACE_OS::NULL_key)
01091         {
01092           // Initialize in_use_ with a new key.
01093           if (ACE_OS::thr_keycreate (&in_use_,
01094                                      &ACE_TSS_Cleanup_keys_destroyer))
01095             {
01096               ACE_ASSERT (false);
01097               return 0; // Major problems, this should *never* happen!
01098             }
01099         }
01100     }
01101 
01102   ACE_TSS_Keys *ts_keys = 0;
01103   if (ACE_OS::thr_getspecific (in_use_,
01104                                reinterpret_cast <void **> (&ts_keys)) == -1)
01105     {
01106       ACE_ASSERT (false);
01107       return 0; // This should not happen!
01108     }
01109 
01110   if (ts_keys == 0)
01111     {
01112       ACE_NEW_RETURN (ts_keys,
01113                       ACE_TSS_Keys,
01114                       0);
01115       // Store the dynamically allocated pointer in thread-specific
01116       // storage.
01117       if (ACE_OS::thr_setspecific (in_use_,
01118                                    reinterpret_cast <void *> (ts_keys)) == -1)
01119         {
01120           ACE_ASSERT (false);
01121           delete ts_keys;
01122           return 0; // Major problems, this should *never* happen!
01123         }
01124     }
01125 
01126   return ts_keys;
01127 }
01128 
01129 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
01130 
01131 /*****************************************************************************/
01132 
01133 // = Static initialization.
01134 
01135 // This is necessary to deal with POSIX pthreads insanity.  This
01136 // guarantees that we've got a "zero'd" thread id even when
01137 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
01138 // as structures...  Under no circumstances should these be given
01139 // initial values.
01140 // Note: these three objects require static construction.
01141 ACE_thread_t ACE_OS::NULL_thread;
01142 ACE_hthread_t ACE_OS::NULL_hthread;
01143 #if defined (ACE_HAS_TSS_EMULATION)
01144   ACE_thread_key_t ACE_OS::NULL_key = static_cast <ACE_thread_key_t> (-1);
01145 #else  /* ! ACE_HAS_TSS_EMULATION */
01146   ACE_thread_key_t ACE_OS::NULL_key;
01147 #endif /* ! ACE_HAS_TSS_EMULATION */
01148 
01149 /*****************************************************************************/
01150 
01151 void
01152 ACE_OS::cleanup_tss (const u_int main_thread)
01153 {
01154 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
01155   { // scope the cleanup instance
01156     // Call TSS destructors for current thread.
01157     TSS_Cleanup_Instance cleanup;
01158     if (cleanup.valid ())
01159       {
01160         cleanup->thread_exit ();
01161       }
01162   }
01163 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
01164 
01165   if (main_thread)
01166     {
01167 #if !defined (ACE_HAS_TSS_EMULATION)  &&  !defined (ACE_HAS_MINIMAL_ACE_OS)
01168       // Just close the ACE_Log_Msg for the current (which should be
01169       // main) thread.  We don't have TSS emulation; if there's native
01170       // TSS, it should call its destructors when the main thread
01171       // exits.
01172       ACE_Base_Thread_Adapter::close_log_msg ();
01173 #endif /* ! ACE_HAS_TSS_EMULATION  &&  ! ACE_HAS_MINIMAL_ACE_OS */
01174 
01175 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
01176       // Finally, free up the ACE_TSS_Cleanup instance.  This method gets
01177       // called by the ACE_Object_Manager.
01178       TSS_Cleanup_Instance cleanup(TSS_Cleanup_Instance::DESTROY);
01179       if (cleanup.valid ())
01180       {
01181         ; // the pointer deletes the Cleanup when it goes out of scope
01182       }
01183 
01184 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
01185 
01186 #if defined (ACE_HAS_TSS_EMULATION)
01187       ACE_TSS_Emulation::tss_close ();
01188 #endif /* ACE_HAS_TSS_EMULATION */
01189     }
01190 }
01191 
01192 /*****************************************************************************/
01193 // CONDITIONS BEGIN
01194 /*****************************************************************************/
01195 
01196 #if defined (ACE_LACKS_COND_T)
01197 // NOTE: The ACE_OS::cond_* functions for some non-Unix platforms are
01198 // defined here either because they're too big to be inlined, or
01199 // to avoid use before definition if they were inline.
01200 
01201 // @@ The following functions could be inlined if i could figure where
01202 // to put it among the #ifdefs!
01203 int
01204 ACE_OS::condattr_init (ACE_condattr_t &attributes,
01205                        int type)
01206 {
01207   attributes.type = type;
01208   return 0;
01209 }
01210 
01211 int
01212 ACE_OS::condattr_destroy (ACE_condattr_t &)
01213 {
01214   return 0;
01215 }
01216 
01217 int
01218 ACE_OS::cond_broadcast (ACE_cond_t *cv)
01219 {
01220   ACE_OS_TRACE ("ACE_OS::cond_broadcast");
01221 # if defined (ACE_HAS_THREADS)
01222   // The <external_mutex> must be locked before this call is made.
01223 
01224   // This is needed to ensure that <waiters_> and <was_broadcast_> are
01225   // consistent relative to each other.
01226   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01227   int have_waiters = 0;
01228 
01229   if (cv->waiters_ > 0)
01230     {
01231       // We are broadcasting, even if there is just one waiter...
01232       // Record the fact that we are broadcasting.  This helps the
01233       // cond_wait() method know how to optimize itself.  Be sure to
01234       // set this with the <waiters_lock_> held.
01235       cv->was_broadcast_ = 1;
01236       have_waiters = 1;
01237     }
01238   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01239   int result = 0;
01240   if (have_waiters)
01241     {
01242       // Wake up all the waiters.
01243       if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1)
01244         result = -1;
01245       // Wait for all the awakened threads to acquire their part of
01246       // the counting semaphore.
01247 #   if defined (ACE_VXWORKS)
01248       else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1)
01249 #   else
01250       else if (ACE_OS::event_wait (&cv->waiters_done_) == -1)
01251 #   endif /* ACE_VXWORKS */
01252         result = -1;
01253       // This is okay, even without the <waiters_lock_> held because
01254       // no other waiter threads can wake up to access it.
01255       cv->was_broadcast_ = 0;
01256     }
01257   return result;
01258 # else
01259   ACE_UNUSED_ARG (cv);
01260   ACE_NOTSUP_RETURN (-1);
01261 # endif /* ACE_HAS_THREADS */
01262 }
01263 
01264 int
01265 ACE_OS::cond_destroy (ACE_cond_t *cv)
01266 {
01267   ACE_OS_TRACE ("ACE_OS::cond_destroy");
01268 # if defined (ACE_HAS_THREADS)
01269 #   if defined (ACE_HAS_WTHREADS)
01270   ACE_OS::event_destroy (&cv->waiters_done_);
01271 #   elif defined (ACE_VXWORKS)
01272   ACE_OS::sema_destroy (&cv->waiters_done_);
01273 #   endif /* ACE_VXWORKS */
01274   ACE_OS::thread_mutex_destroy (&cv->waiters_lock_);
01275   return ACE_OS::sema_destroy (&cv->sema_);
01276 # else
01277   ACE_UNUSED_ARG (cv);
01278   ACE_NOTSUP_RETURN (-1);
01279 # endif /* ACE_HAS_THREADS */
01280 }
01281 
01282 int
01283 ACE_OS::cond_init (ACE_cond_t *cv,
01284                    ACE_condattr_t &attributes,
01285                    const char *name, void *arg)
01286 {
01287   return
01288     ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
01289 }
01290 
01291 # if defined (ACE_HAS_WCHAR)
01292 int
01293 ACE_OS::cond_init (ACE_cond_t *cv,
01294                    ACE_condattr_t &attributes,
01295                    const wchar_t *name, void *arg)
01296 {
01297   return
01298     ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
01299 }
01300 # endif /* ACE_HAS_WCHAR */
01301 
01302 int
01303 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
01304 {
01305   ACE_OS_TRACE ("ACE_OS::cond_init");
01306 # if defined (ACE_HAS_THREADS)
01307   cv->waiters_ = 0;
01308   cv->was_broadcast_ = 0;
01309 
01310   int result = 0;
01311   if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
01312     result = -1;
01313   else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
01314     result = -1;
01315 #   if defined (ACE_VXWORKS)
01316   else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
01317 #   else
01318   else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
01319 #   endif /* ACE_VXWORKS */
01320     result = -1;
01321   return result;
01322 # else
01323   ACE_UNUSED_ARG (cv);
01324   ACE_UNUSED_ARG (type);
01325   ACE_UNUSED_ARG (name);
01326   ACE_UNUSED_ARG (arg);
01327   ACE_NOTSUP_RETURN (-1);
01328 # endif /* ACE_HAS_THREADS */
01329 }
01330 
01331 # if defined (ACE_HAS_WCHAR)
01332 int
01333 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
01334 {
01335   ACE_OS_TRACE ("ACE_OS::cond_init");
01336 #   if defined (ACE_HAS_THREADS)
01337   cv->waiters_ = 0;
01338   cv->was_broadcast_ = 0;
01339 
01340   int result = 0;
01341   if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
01342     result = -1;
01343   else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
01344     result = -1;
01345 #     if defined (ACE_VXWORKS)
01346   else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
01347 #     else
01348   else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
01349 #     endif /* ACE_VXWORKS */
01350     result = -1;
01351   return result;
01352 #   else
01353   ACE_UNUSED_ARG (cv);
01354   ACE_UNUSED_ARG (type);
01355   ACE_UNUSED_ARG (name);
01356   ACE_UNUSED_ARG (arg);
01357   ACE_NOTSUP_RETURN (-1);
01358 #   endif /* ACE_HAS_THREADS */
01359 }
01360 # endif /* ACE_HAS_WCHAR */
01361 
01362 int
01363 ACE_OS::cond_signal (ACE_cond_t *cv)
01364 {
01365   ACE_OS_TRACE ("ACE_OS::cond_signal");
01366 # if defined (ACE_HAS_THREADS)
01367   // If there aren't any waiters, then this is a no-op.  Note that
01368   // this function *must* be called with the <external_mutex> held
01369   // since other wise there is a race condition that can lead to the
01370   // lost wakeup bug...  This is needed to ensure that the <waiters_>
01371   // value is not in an inconsistent internal state while being
01372   // updated by another thread.
01373   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01374   int have_waiters = cv->waiters_ > 0;
01375   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01376 
01377   if (have_waiters != 0)
01378     return ACE_OS::sema_post (&cv->sema_);
01379   else
01380     return 0; // No-op
01381 # else
01382   ACE_UNUSED_ARG (cv);
01383   ACE_NOTSUP_RETURN (-1);
01384 # endif /* ACE_HAS_THREADS */
01385 }
01386 
01387 int
01388 ACE_OS::cond_wait (ACE_cond_t *cv,
01389                    ACE_mutex_t *external_mutex)
01390 {
01391   ACE_OS_TRACE ("ACE_OS::cond_wait");
01392 # if defined (ACE_HAS_THREADS)
01393   // Prevent race conditions on the <waiters_> count.
01394   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01395   cv->waiters_++;
01396   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01397 
01398   int result = 0;
01399 
01400 #   if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
01401   if (external_mutex->type_ == USYNC_PROCESS)
01402     // This call will automatically release the mutex and wait on the semaphore.
01403     ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_,
01404                                                             cv->sema_, INFINITE, FALSE),
01405                                      result),
01406                    int, -1, result);
01407   else
01408 #   endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
01409     {
01410       // We keep the lock held just long enough to increment the count of
01411       // waiters by one.  Note that we can't keep it held across the call
01412       // to ACE_OS::sema_wait() since that will deadlock other calls to
01413       // ACE_OS::cond_signal().
01414       if (ACE_OS::mutex_unlock (external_mutex) != 0)
01415         return -1;
01416 
01417       // Wait to be awakened by a ACE_OS::cond_signal() or
01418       // ACE_OS::cond_broadcast().
01419       result = ACE_OS::sema_wait (&cv->sema_);
01420     }
01421 
01422   // Reacquire lock to avoid race conditions on the <waiters_> count.
01423   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01424 
01425   // We're ready to return, so there's one less waiter.
01426   cv->waiters_--;
01427 
01428   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
01429 
01430   // Release the lock so that other collaborating threads can make
01431   // progress.
01432   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01433 
01434   if (result == -1)
01435     // Bad things happened, so let's just return below.
01436     /* NOOP */;
01437 #   if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
01438   else if (external_mutex->type_ == USYNC_PROCESS)
01439     {
01440       if (last_waiter)
01441 
01442         // This call atomically signals the <waiters_done_> event and
01443         // waits until it can acquire the mutex.  This is important to
01444         // prevent unfairness.
01445         ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
01446                                                                 external_mutex->proc_mutex_,
01447                                                                 INFINITE, FALSE),
01448                                          result),
01449                        int, -1, result);
01450       else
01451         // We must always regain the <external_mutex>, even when
01452         // errors occur because that's the guarantee that we give to
01453         // our callers.
01454         ACE_OS::mutex_lock (external_mutex);
01455 
01456       return result;
01457       /* NOTREACHED */
01458     }
01459 #   endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
01460   // If we're the last waiter thread during this particular broadcast
01461   // then let all the other threads proceed.
01462   else if (last_waiter)
01463 #   if defined (ACE_VXWORKS)
01464     ACE_OS::sema_post (&cv->waiters_done_);
01465 #   else
01466     ACE_OS::event_signal (&cv->waiters_done_);
01467 #   endif /* ACE_VXWORKS */
01468 
01469   // We must always regain the <external_mutex>, even when errors
01470   // occur because that's the guarantee that we give to our callers.
01471   ACE_OS::mutex_lock (external_mutex);
01472 
01473   return result;
01474 # else
01475   ACE_UNUSED_ARG (cv);
01476   ACE_UNUSED_ARG (external_mutex);
01477   ACE_NOTSUP_RETURN (-1);
01478 # endif /* ACE_HAS_THREADS */
01479 }
01480 
01481 int
01482 ACE_OS::cond_timedwait (ACE_cond_t *cv,
01483                         ACE_mutex_t *external_mutex,
01484                         ACE_Time_Value *timeout)
01485 {
01486   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
01487 # if defined (ACE_HAS_THREADS)
01488   // Handle the easy case first.
01489   if (timeout == 0)
01490     return ACE_OS::cond_wait (cv, external_mutex);
01491 #   if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS)
01492 
01493   // Prevent race conditions on the <waiters_> count.
01494   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01495   cv->waiters_++;
01496   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01497 
01498   int result = 0;
01499   ACE_Errno_Guard error (errno, 0);
01500   int msec_timeout;
01501 
01502   if (timeout->sec () == 0 && timeout->usec () == 0)
01503     msec_timeout = 0; // Do a "poll."
01504   else
01505     {
01506       // Note that we must convert between absolute time (which is
01507       // passed as a parameter) and relative time (which is what
01508       // WaitForSingleObjects() expects).
01509       ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
01510 
01511       // Watchout for situations where a context switch has caused the
01512       // current time to be > the timeout.
01513       if (relative_time < ACE_Time_Value::zero)
01514         msec_timeout = 0;
01515       else
01516         msec_timeout = relative_time.msec ();
01517     }
01518 
01519 #     if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
01520   if (external_mutex->type_ == USYNC_PROCESS)
01521     // This call will automatically release the mutex and wait on the
01522     // semaphore.
01523     result = ::SignalObjectAndWait (external_mutex->proc_mutex_,
01524                                     cv->sema_,
01525                                     msec_timeout,
01526                                     FALSE);
01527   else
01528 #     endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
01529     {
01530       // We keep the lock held just long enough to increment the count
01531       // of waiters by one.  Note that we can't keep it held across
01532       // the call to WaitForSingleObject since that will deadlock
01533       // other calls to ACE_OS::cond_signal().
01534       if (ACE_OS::mutex_unlock (external_mutex) != 0)
01535         return -1;
01536 
01537       // Wait to be awakened by a ACE_OS::signal() or
01538       // ACE_OS::broadcast().
01539 #     if defined (ACE_WIN32)
01540 #       if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
01541       result = ::WaitForSingleObject (cv->sema_, msec_timeout);
01542 #       else /* ACE_USES_WINCE_SEMA_SIMULATION */
01543       // Can't use Win32 API on our simulated semaphores.
01544       result = ACE_OS::sema_wait (&cv->sema_,
01545                                   timeout);
01546 #       endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01547 #     elif defined (ACE_VXWORKS)
01548       // Inline the call to ACE_OS::sema_wait () because it takes an
01549       // ACE_Time_Value argument.  Avoid the cost of that conversion . . .
01550       int ticks_per_sec = ::sysClkRateGet ();
01551       int ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS;
01552       result = ::semTake (cv->sema_.sema_, ticks);
01553 #     endif /* ACE_WIN32 || VXWORKS */
01554     }
01555 
01556   // Reacquire lock to avoid race conditions.
01557   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01558   cv->waiters_--;
01559 
01560   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
01561 
01562   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01563 
01564 #     if defined (ACE_WIN32)
01565   if (result != WAIT_OBJECT_0)
01566     {
01567       switch (result)
01568         {
01569         case WAIT_TIMEOUT:
01570           error = ETIME;
01571           break;
01572         default:
01573           error = ::GetLastError ();
01574           break;
01575         }
01576       result = -1;
01577     }
01578 #     elif defined (ACE_VXWORKS)
01579   if (result == ERROR)
01580     {
01581       switch (errno)
01582         {
01583         case S_objLib_OBJ_TIMEOUT:
01584           error = ETIME;
01585           break;
01586         case S_objLib_OBJ_UNAVAILABLE:
01587           if (msec_timeout == 0)
01588             error = ETIME;
01589           break;
01590         default:
01591           error = errno;
01592           break;
01593         }
01594       result = -1;
01595     }
01596 #     endif /* ACE_WIN32 || VXWORKS */
01597 #     if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
01598   if (external_mutex->type_ == USYNC_PROCESS)
01599     {
01600       if (last_waiter)
01601         // This call atomically signals the <waiters_done_> event and
01602         // waits until it can acquire the mutex.  This is important to
01603         // prevent unfairness.
01604         ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
01605                                                                 external_mutex->proc_mutex_,
01606                                                                 INFINITE, FALSE),
01607                                          result),
01608                        int, -1, result);
01609       else
01610         // We must always regain the <external_Mutex>, even when
01611         // errors occur because that's the guarantee that we give to
01612         // our callers.
01613         ACE_OS::mutex_lock (external_mutex);
01614 
01615       return result;
01616       /* NOTREACHED */
01617     }
01618 #     endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
01619   // Note that this *must* be an "if" statement rather than an "else
01620   // if" statement since the caller may have timed out and hence the
01621   // result would have been -1 above.
01622   if (last_waiter)
01623     // Release the signaler/broadcaster if we're the last waiter.
01624 #     if defined (ACE_WIN32)
01625     ACE_OS::event_signal (&cv->waiters_done_);
01626 #     else
01627     ACE_OS::sema_post (&cv->waiters_done_);
01628 #     endif /* ACE_WIN32 */
01629 
01630   // We must always regain the <external_mutex>, even when errors
01631   // occur because that's the guarantee that we give to our callers.
01632   ACE_OS::mutex_lock (external_mutex);
01633 
01634   return result;
01635 #   endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
01636 # else
01637   ACE_UNUSED_ARG (cv);
01638   ACE_UNUSED_ARG (external_mutex);
01639   ACE_UNUSED_ARG (timeout);
01640   ACE_NOTSUP_RETURN (-1);
01641 # endif /* ACE_HAS_THREADS */
01642 }
01643 
01644 # if defined (ACE_HAS_WTHREADS)
01645 int
01646 ACE_OS::cond_timedwait (ACE_cond_t *cv,
01647                         ACE_thread_mutex_t *external_mutex,
01648                         ACE_Time_Value *timeout)
01649 {
01650   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
01651 #   if defined (ACE_HAS_THREADS)
01652   // Handle the easy case first.
01653   if (timeout == 0)
01654     return ACE_OS::cond_wait (cv, external_mutex);
01655 
01656   // Prevent race conditions on the <waiters_> count.
01657   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01658   cv->waiters_++;
01659   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01660 
01661   int result = 0;
01662   int error = 0;
01663   int msec_timeout;
01664 
01665   if (timeout->sec () == 0 && timeout->usec () == 0)
01666     msec_timeout = 0; // Do a "poll."
01667   else
01668     {
01669       // Note that we must convert between absolute time (which is
01670       // passed as a parameter) and relative time (which is what
01671       // WaitForSingleObjects() expects).
01672       ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
01673 
01674       // Watchout for situations where a context switch has caused the
01675       // current time to be > the timeout.
01676       if (relative_time < ACE_Time_Value::zero)
01677         msec_timeout = 0;
01678       else
01679         msec_timeout = relative_time.msec ();
01680     }
01681 
01682   // We keep the lock held just long enough to increment the count of
01683   // waiters by one.  Note that we can't keep it held across the call
01684   // to WaitForSingleObject since that will deadlock other calls to
01685   // ACE_OS::cond_signal().
01686   if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
01687     return -1;
01688 
01689   // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
01690 #     if defined (ACE_USES_WINCE_SEMA_SIMULATION)
01691   // Can't use Win32 API on simulated semaphores.
01692   result = ACE_OS::sema_wait (&cv->sema_,
01693                               timeout);
01694 
01695   if (result == -1 && errno == ETIME)
01696     result = WAIT_TIMEOUT;
01697 #     else
01698   result = ::WaitForSingleObject (cv->sema_, msec_timeout);
01699 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01700 
01701   // Reacquire lock to avoid race conditions.
01702   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01703 
01704   cv->waiters_--;
01705 
01706   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
01707 
01708   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01709 
01710   if (result != WAIT_OBJECT_0)
01711     {
01712       switch (result)
01713         {
01714         case WAIT_TIMEOUT:
01715           error = ETIME;
01716           break;
01717         default:
01718           error = ::GetLastError ();
01719           break;
01720         }
01721       result = -1;
01722     }
01723 
01724   if (last_waiter)
01725     // Release the signaler/broadcaster if we're the last waiter.
01726     ACE_OS::event_signal (&cv->waiters_done_);
01727 
01728   // We must always regain the <external_mutex>, even when errors
01729   // occur because that's the guarantee that we give to our callers.
01730   ACE_OS::thread_mutex_lock (external_mutex);
01731   errno = error;
01732   return result;
01733 #   else
01734   ACE_NOTSUP_RETURN (-1);
01735 #   endif /* ACE_HAS_THREADS */
01736 }
01737 
01738 int
01739 ACE_OS::cond_wait (ACE_cond_t *cv,
01740                    ACE_thread_mutex_t *external_mutex)
01741 {
01742   ACE_OS_TRACE ("ACE_OS::cond_wait");
01743 #   if defined (ACE_HAS_THREADS)
01744   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01745   cv->waiters_++;
01746   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01747 
01748   int result = 0;
01749   int error = 0;
01750 
01751   // We keep the lock held just long enough to increment the count of
01752   // waiters by one.  Note that we can't keep it held across the call
01753   // to ACE_OS::sema_wait() since that will deadlock other calls to
01754   // ACE_OS::cond_signal().
01755   if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
01756     return -1;
01757 
01758   // Wait to be awakened by a ACE_OS::cond_signal() or
01759   // ACE_OS::cond_broadcast().
01760 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
01761   result = ::WaitForSingleObject (cv->sema_, INFINITE);
01762 #     else
01763   // Can't use Win32 API on simulated semaphores.
01764   result = ACE_OS::sema_wait (&cv->sema_);
01765 
01766   if (result != WAIT_OBJECT_0 && errno == ETIME)
01767     result = WAIT_TIMEOUT;
01768 
01769 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
01770 
01771   // Reacquire lock to avoid race conditions.
01772   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
01773 
01774   cv->waiters_--;
01775 
01776   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
01777 
01778   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
01779 
01780   if (result != WAIT_OBJECT_0)
01781     {
01782       switch (result)
01783         {
01784         case WAIT_TIMEOUT:
01785           error = ETIME;
01786           break;
01787         default:
01788           error = ::GetLastError ();
01789           break;
01790         }
01791     }
01792   else if (last_waiter)
01793     // Release the signaler/broadcaster if we're the last waiter.
01794     ACE_OS::event_signal (&cv->waiters_done_);
01795 
01796   // We must always regain the <external_mutex>, even when errors
01797   // occur because that's the guarantee that we give to our callers.
01798   ACE_OS::thread_mutex_lock (external_mutex);
01799 
01800   // Reset errno in case mutex_lock() also fails...
01801   errno = error;
01802   return result;
01803 #   else
01804   ACE_NOTSUP_RETURN (-1);
01805 #   endif /* ACE_HAS_THREADS */
01806 }
01807 # endif /* ACE_HAS_WTHREADS */
01808 #else
01809 int
01810 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
01811 {
01812   ACE_condattr_t attributes;
01813   if (ACE_OS::condattr_init (attributes, type) == 0
01814       && ACE_OS::cond_init (cv, attributes, name, arg) == 0)
01815     {
01816       (void) ACE_OS::condattr_destroy (attributes);
01817       return 0;
01818     }
01819   return -1;
01820 }
01821 #endif /* ACE_LACKS_COND_T */
01822 
01823 /*****************************************************************************/
01824 // CONDITIONS END
01825 /*****************************************************************************/
01826 
01827 /*****************************************************************************/
01828 // MUTEXES BEGIN
01829 /*****************************************************************************/
01830 
01831 int
01832 ACE_OS::mutex_init (ACE_mutex_t *m,
01833                     int lock_scope,
01834                     const char *name,
01835                     ACE_mutexattr_t *attributes,
01836                     LPSECURITY_ATTRIBUTES sa,
01837                     int lock_type)
01838 {
01839   // ACE_OS_TRACE ("ACE_OS::mutex_init");
01840 #if defined (ACE_HAS_THREADS)
01841 # if defined (ACE_HAS_PTHREADS)
01842   ACE_UNUSED_ARG (name);
01843   ACE_UNUSED_ARG (sa);
01844 
01845 # if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
01846   /* Tests show that VxWorks 6.x pthread lib does not only
01847    * require zeroing of mutex/condition objects to function correctly
01848    * but also of the attribute objects.
01849    */
01850   pthread_mutexattr_t l_attributes = {0};
01851 # else
01852   pthread_mutexattr_t l_attributes;
01853 # endif
01854 
01855   if (attributes == 0)
01856     attributes = &l_attributes;
01857   int result = 0;
01858   int attr_init = 0;  // have we initialized the local attributes.
01859 
01860   // Only do these initializations if the <attributes> parameter
01861   // wasn't originally set.
01862   if (attributes == &l_attributes)
01863   {
01864 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
01865       if (::pthread_mutexattr_create (attributes) == 0)
01866 #   elif defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD)
01867       if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0)
01868 #   else /* draft 6 */
01869       if (::pthread_mutexattr_init (attributes) == 0)
01870 #   endif /* ACE_HAS_PTHREADS_DRAFT4 */
01871 {
01872   result = 0;
01873   attr_init = 1; // we have initialized these attributes
01874 }
01875       else
01876         result = -1;        // ACE_ADAPT_RETVAL used it for intermediate status
01877   }
01878 
01879   if (result == 0 && lock_scope != 0)
01880 {
01881 #   if defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD)
01882 #     if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
01883       (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes,
01884                                                                lock_scope),
01885                                result);
01886 #     endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
01887 #   else /* Pthreads draft 6 */
01888 #     if !defined (ACE_LACKS_MUTEXATTR_PSHARED)
01889       if (::pthread_mutexattr_setpshared (attributes, lock_scope) != 0)
01890         result = -1;
01891 #     endif /* ACE_LACKS_MUTEXATTR_PSHARED */
01892 #   endif /* ACE_HAS_PTHREADS_DRAFT7 || ACE_HAS_PTHREADS_STD */
01893 }
01894 
01895   if (result == 0 && lock_type != 0)
01896 {
01897 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
01898 #     if defined (ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP)
01899       if (::pthread_mutexattr_setkind_np (attributes, lock_type) != 0)
01900         result = -1;
01901 #     endif /* ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP */
01902 #   elif defined (ACE_HAS_RECURSIVE_MUTEXES)
01903       (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes,
01904                                                             lock_type),
01905                                result);
01906 #   endif /* ACE_HAS_PTHREADS_DRAFT4 */
01907 }
01908 
01909   if (result == 0)
01910 {
01911 #   if defined (ACE_VXWORKS)&& (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
01912       /* VxWorks 6.x API reference states:
01913        * If the memory for the mutex variable object has been allocated
01914        *   dynamically, it is a good policy to always zero out the
01915        *   block of memory so as to avoid spurious EBUSY return code
01916        *   when calling this routine.
01917        * Tests shows this to be necessary.
01918        */
01919       ACE_OS::memset (m, 0, sizeof (*m));
01920 #   endif
01921 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
01922       if (::pthread_mutex_init (m, *attributes) == 0)
01923 #   elif defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD)
01924       if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0)
01925 #   else
01926       if (::pthread_mutex_init (m, attributes) == 0)
01927 #   endif /* ACE_HAS_PTHREADS_DRAFT4 */
01928         result = 0;
01929       else
01930         result = -1;        // ACE_ADAPT_RETVAL used it for intermediate status
01931 }
01932 
01933   // Only do the deletions if the <attributes> parameter wasn't
01934   // originally set.
01935   if (attributes == &l_attributes && attr_init)
01936 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
01937   ::pthread_mutexattr_delete (&l_attributes);
01938 #   else
01939   ::pthread_mutexattr_destroy (&l_attributes);
01940 #   endif /* ACE_HAS_PTHREADS_DRAFT4 */
01941 
01942   return result;
01943 # elif defined (ACE_HAS_STHREADS)
01944   ACE_UNUSED_ARG (name);
01945   ACE_UNUSED_ARG (sa);
01946   ACE_UNUSED_ARG (lock_type);
01947   int result;
01948   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m,
01949                      lock_scope,
01950                      attributes),
01951   result),
01952   int, -1);
01953 # elif defined (ACE_HAS_WTHREADS)
01954   m->type_ = lock_scope;
01955 
01956   SECURITY_ATTRIBUTES sa_buffer;
01957   SECURITY_DESCRIPTOR sd_buffer;
01958   switch (lock_scope)
01959 {
01960   case USYNC_PROCESS:
01961 #   if defined (ACE_HAS_WINCE)
01962       // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
01963       m->proc_mutex_ =
01964   ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
01965                           (sa, &sa_buffer, &sd_buffer),
01966                         FALSE,
01967                         ACE_Ascii_To_Wide (name).wchar_rep ());
01968 #   else /* ACE_HAS_WINCE */
01969       m->proc_mutex_ =
01970   ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
01971                           (sa, &sa_buffer, &sd_buffer),
01972                         FALSE,
01973                         name);
01974 #   endif /* ACE_HAS_WINCE */
01975       if (m->proc_mutex_ == 0)
01976         ACE_FAIL_RETURN (-1);
01977       else
01978       {
01979           // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
01980         ACE_OS::set_errno_to_last_error ();
01981         return 0;
01982       }
01983   case USYNC_THREAD:
01984     return ACE_OS::thread_mutex_init (&m->thr_mutex_,
01985                                        lock_type,
01986                                        name,
01987                                        attributes);
01988   default:
01989     errno = EINVAL;
01990     return -1;
01991 }
01992   /* NOTREACHED */
01993 
01994 # elif defined (ACE_VXWORKS)
01995   ACE_UNUSED_ARG (name);
01996   ACE_UNUSED_ARG (attributes);
01997   ACE_UNUSED_ARG (sa);
01998   ACE_UNUSED_ARG (lock_type);
01999 
02000   return (*m = ::semMCreate (lock_scope)) == 0 ? -1 : 0;
02001 # endif /* ACE_HAS_PTHREADS */
02002 #else
02003   ACE_UNUSED_ARG (m);
02004   ACE_UNUSED_ARG (lock_scope);
02005   ACE_UNUSED_ARG (name);
02006   ACE_UNUSED_ARG (attributes);
02007   ACE_UNUSED_ARG (sa);
02008   ACE_UNUSED_ARG (lock_type);
02009   ACE_NOTSUP_RETURN (-1);
02010 #endif /* ACE_HAS_THREADS */
02011 }
02012 
02013 int
02014 ACE_OS::mutex_destroy (ACE_mutex_t *m)
02015 {
02016   ACE_OS_TRACE ("ACE_OS::mutex_destroy");
02017 #if defined (ACE_HAS_THREADS)
02018 # if defined (ACE_HAS_PTHREADS)
02019 #   if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6))
02020   ACE_OSCALL_RETURN (::pthread_mutex_destroy (m), int, -1);
02021 #   else
02022   int result;
02023   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m),
02024                      result), int, -1);
02025 #   endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6*/
02026 # elif defined (ACE_HAS_STHREADS)
02027   int result;
02028   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), result), int, -1);
02029 # elif defined (ACE_HAS_WTHREADS)
02030   switch (m->type_)
02031 {
02032   case USYNC_PROCESS:
02033     ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_),
02034                           ace_result_),
02035     int, -1);
02036   case USYNC_THREAD:
02037     return ACE_OS::thread_mutex_destroy (&m->thr_mutex_);
02038   default:
02039     errno = EINVAL;
02040     return -1;
02041 }
02042   /* NOTREACHED */
02043 # elif defined (ACE_VXWORKS)
02044   return ::semDelete (*m) == OK ? 0 : -1;
02045 # endif /* Threads variety case */
02046 #else
02047   ACE_UNUSED_ARG (m);
02048   ACE_NOTSUP_RETURN (-1);
02049 #endif /* ACE_HAS_THREADS */
02050 }
02051 
02052 #if defined (ACE_HAS_WCHAR)
02053 int
02054 ACE_OS::mutex_init (ACE_mutex_t *m,
02055                     int lock_scope,
02056                     const wchar_t *name,
02057                     ACE_mutexattr_t *attributes,
02058                     LPSECURITY_ATTRIBUTES sa,
02059                     int lock_type)
02060 {
02061 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
02062   m->type_ = lock_scope;
02063   SECURITY_ATTRIBUTES sa_buffer;
02064   SECURITY_DESCRIPTOR sd_buffer;
02065   switch (lock_scope)
02066   {
02067     case USYNC_PROCESS:
02068       m->proc_mutex_ =
02069       ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
02070           (sa, &sa_buffer, &sd_buffer),
02071       FALSE,
02072       name);
02073       if (m->proc_mutex_ == 0)
02074         ACE_FAIL_RETURN (-1);
02075       else
02076         return 0;
02077     case USYNC_THREAD:
02078       return ACE_OS::thread_mutex_init (&m->thr_mutex_,
02079                                          lock_type,
02080                                          name,
02081                                          attributes);
02082   }
02083 
02084   errno = EINVAL;
02085   return -1;
02086 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
02087   return ACE_OS::mutex_init (m,
02088                              lock_scope,
02089                              ACE_Wide_To_Ascii (name).char_rep (),
02090                              attributes,
02091                              sa,
02092                              lock_type);
02093 #endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
02094 }
02095 #endif /* ACE_HAS_WCHAR */
02096 
02097 int
02098 ACE_OS::mutex_lock (ACE_mutex_t *m)
02099 {
02100   // ACE_OS_TRACE ("ACE_OS::mutex_lock");
02101 #if defined (ACE_HAS_THREADS)
02102 # if defined (ACE_HAS_PTHREADS)
02103   // Note, don't use "::" here since the following call is often a macro.
02104 #   if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6))
02105   ACE_OSCALL_RETURN (pthread_mutex_lock (m), int, -1);
02106 #   else
02107   int result;
02108   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), result),
02109                      int, -1);
02110 #   endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */
02111 # elif defined (ACE_HAS_STHREADS)
02112   int result;
02113   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), result), int, -1);
02114 # elif defined (ACE_HAS_WTHREADS)
02115   switch (m->type_)
02116 {
02117   case USYNC_PROCESS:
02118     switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
02119       {
02120         //
02121         // Timeout can't occur, so don't bother checking...
02122         //
02123       case WAIT_OBJECT_0:
02124       case WAIT_ABANDONED:
02125         // We will ignore abandonments in this method
02126         // Note that we still hold the lock
02127         return 0;
02128       default:
02129         // This is a hack, we need to find an appropriate mapping...
02130         ACE_OS::set_errno_to_last_error ();
02131         return -1;
02132       }
02133   case USYNC_THREAD:
02134     return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
02135   default:
02136     errno = EINVAL;
02137     return -1;
02138 }
02139   /* NOTREACHED */
02140 # elif defined (ACE_VXWORKS)
02141   return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1;
02142 # endif /* Threads variety case */
02143 #else
02144   ACE_UNUSED_ARG (m);
02145   ACE_NOTSUP_RETURN (-1);
02146 #endif /* ACE_HAS_THREADS */
02147 }
02148 
02149 int
02150 ACE_OS::mutex_lock (ACE_mutex_t *m,
02151                     int &abandoned)
02152 {
02153   ACE_OS_TRACE ("ACE_OS::mutex_lock");
02154 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
02155   abandoned = 0;
02156   switch (m->type_)
02157   {
02158     case USYNC_PROCESS:
02159       switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
02160       {
02161         //
02162           // Timeout can't occur, so don't bother checking...
02163         //
02164         case WAIT_OBJECT_0:
02165           return 0;
02166         case WAIT_ABANDONED:
02167           abandoned = 1;
02168           return 0;  // something goofed, but we hold the lock ...
02169         default:
02170           // This is a hack, we need to find an appropriate mapping...
02171           ACE_OS::set_errno_to_last_error ();
02172           return -1;
02173       }
02174     case USYNC_THREAD:
02175       return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
02176     default:
02177       errno = EINVAL;
02178       return -1;
02179   }
02180   /* NOTREACHED */
02181 #else
02182   ACE_UNUSED_ARG (m);
02183   ACE_UNUSED_ARG (abandoned);
02184   ACE_NOTSUP_RETURN (-1);
02185 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
02186 }
02187 
02188 int
02189 ACE_OS::mutex_lock (ACE_mutex_t *m,
02190                     const ACE_Time_Value &timeout)
02191 {
02192 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
02193 
02194 #  if defined (ACE_HAS_PTHREADS)
02195   int result;
02196 
02197   // "timeout" should be an absolute time.
02198 
02199   timespec_t ts = timeout;  // Calls ACE_Time_Value::operator timespec_t().
02200 
02201   // Note that the mutex should not be a recursive one, i.e., it
02202   // should only be a standard mutex or an error checking mutex.
02203 
02204   ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, -1, result);
02205 
02206   // We need to adjust this to make the errno values consistent.
02207   if (result == -1 && errno == ETIMEDOUT)
02208     errno = ETIME;
02209   return result;
02210 
02211 #  elif defined (ACE_HAS_WTHREADS)
02212   // Note that we must convert between absolute time (which is passed
02213   // as a parameter) and relative time (which is what the system call
02214   // expects).
02215   ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ());
02216 
02217   switch (m->type_)
02218   {
02219     case USYNC_PROCESS:
02220       switch (::WaitForSingleObject (m->proc_mutex_,
02221                 relative_time.msec ()))
02222       {
02223         case WAIT_OBJECT_0:
02224         case WAIT_ABANDONED:
02225           // We will ignore abandonments in this method
02226           // Note that we still hold the lock
02227           return 0;
02228         case WAIT_TIMEOUT:
02229           errno = ETIME;
02230           return -1;
02231         default:
02232           // This is a hack, we need to find an appropriate mapping...
02233           ACE_OS::set_errno_to_last_error ();
02234           return -1;
02235       }
02236     case USYNC_THREAD:
02237       ACE_NOTSUP_RETURN (-1);
02238     default:
02239       errno = EINVAL;
02240       return -1;
02241   }
02242   /* NOTREACHED */
02243 
02244 #  elif defined (ACE_VXWORKS)
02245 
02246   // Note that we must convert between absolute time (which is passed
02247   // as a parameter) and relative time (which is what the system call
02248   // expects).
02249   ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ());
02250 
02251   int ticks_per_sec = ::sysClkRateGet ();
02252 
02253   int ticks = relative_time.sec() * ticks_per_sec +
02254       relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
02255   if (::semTake (*m, ticks) == ERROR)
02256   {
02257     if (errno == S_objLib_OBJ_TIMEOUT)
02258         // Convert the VxWorks errno to one that's common for to ACE
02259         // platforms.
02260       errno = ETIME;
02261     else if (errno == S_objLib_OBJ_UNAVAILABLE)
02262       errno = EBUSY;
02263     return -1;
02264   }
02265   else
02266     return 0;
02267 #  endif /* ACE_HAS_PTHREADS */
02268 
02269 #else
02270   ACE_UNUSED_ARG (m);
02271   ACE_UNUSED_ARG (timeout);
02272   ACE_NOTSUP_RETURN (-1);
02273 #endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
02274 }
02275 
02276 int
02277 ACE_OS::mutex_trylock (ACE_mutex_t *m)
02278 {
02279   ACE_OS_TRACE ("ACE_OS::mutex_trylock");
02280 #if defined (ACE_HAS_THREADS)
02281 # if defined (ACE_HAS_PTHREADS)
02282   // Note, don't use "::" here since the following call is often a macro.
02283 #   if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6))
02284   int status = pthread_mutex_trylock (m);
02285   if (status == 1)
02286     status = 0;
02287   else if (status == 0) {
02288     status = -1;
02289     errno = EBUSY;
02290   }
02291   return status;
02292 #   else
02293   int result;
02294   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), result),
02295                      int, -1);
02296 #   endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */
02297 # elif defined (ACE_HAS_STHREADS)
02298   int result;
02299   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), result), int, -1);
02300 # elif defined (ACE_HAS_WTHREADS)
02301   switch (m->type_)
02302 {
02303   case USYNC_PROCESS:
02304   {
02305         // Try for 0 milliseconds - i.e. nonblocking.
02306     switch (::WaitForSingleObject (m->proc_mutex_, 0))
02307     {
02308       case WAIT_OBJECT_0:
02309         return 0;
02310       case WAIT_ABANDONED:
02311             // We will ignore abandonments in this method.  Note that
02312             // we still hold the lock.
02313         return 0;
02314       case WAIT_TIMEOUT:
02315         errno = EBUSY;
02316         return -1;
02317       default:
02318         ACE_OS::set_errno_to_last_error ();
02319         return -1;
02320     }
02321   }
02322   case USYNC_THREAD:
02323     return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
02324   default:
02325     errno = EINVAL;
02326     return -1;
02327 }
02328   /* NOTREACHED */
02329 # elif defined (ACE_VXWORKS)
02330   if (::semTake (*m, NO_WAIT) == ERROR)
02331     if (errno == S_objLib_OBJ_UNAVAILABLE)
02332 {
02333         // couldn't get the semaphore
02334   errno = EBUSY;
02335   return -1;
02336 }
02337     else
02338       // error
02339       return -1;
02340     else
02341     // got the semaphore
02342       return 0;
02343 # endif /* Threads variety case */
02344 #else
02345   ACE_UNUSED_ARG (m);
02346   ACE_NOTSUP_RETURN (-1);
02347 #endif /* ACE_HAS_THREADS */
02348 }
02349 
02350 int
02351 ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned)
02352 {
02353 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
02354   abandoned = 0;
02355   switch (m->type_)
02356   {
02357     case USYNC_PROCESS:
02358     {
02359         // Try for 0 milliseconds - i.e. nonblocking.
02360       switch (::WaitForSingleObject (m->proc_mutex_, 0))
02361       {
02362         case WAIT_OBJECT_0:
02363           return 0;
02364         case WAIT_ABANDONED:
02365           abandoned = 1;
02366           return 0;  // something goofed, but we hold the lock ...
02367         case WAIT_TIMEOUT:
02368           errno = EBUSY;
02369           return -1;
02370         default:
02371           ACE_OS::set_errno_to_last_error ();
02372           return -1;
02373       }
02374     }
02375     case USYNC_THREAD:
02376       return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
02377     default:
02378       errno = EINVAL;
02379       return -1;
02380   }
02381   /* NOTREACHED */
02382 #else
02383   ACE_UNUSED_ARG (m);
02384   ACE_UNUSED_ARG (abandoned);
02385   ACE_NOTSUP_RETURN (-1);
02386 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
02387 }
02388 
02389 int
02390 ACE_OS::mutex_unlock (ACE_mutex_t *m)
02391 {
02392   ACE_OS_TRACE ("ACE_OS::mutex_unlock");
02393 #if defined (ACE_HAS_THREADS)
02394 # if defined (ACE_HAS_PTHREADS)
02395   // Note, don't use "::" here since the following call is often a macro.
02396 #   if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6))
02397   ACE_OSCALL_RETURN (pthread_mutex_unlock (m), int, -1);
02398 #   else
02399   int result;
02400   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), result),
02401                      int, -1);
02402 #   endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */
02403 # elif defined (ACE_HAS_STHREADS)
02404   int result;
02405   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), result), int, -1);
02406 # elif defined (ACE_HAS_WTHREADS)
02407   switch (m->type_)
02408 {
02409   case USYNC_PROCESS:
02410     ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_),
02411                           ace_result_),
02412     int, -1);
02413   case USYNC_THREAD:
02414     return ACE_OS::thread_mutex_unlock (&m->thr_mutex_);
02415   default:
02416     errno = EINVAL;
02417     return -1;
02418 }
02419   /* NOTREACHED */
02420 # elif defined (ACE_VXWORKS)
02421   return ::semGive (*m) == OK ? 0 : -1;
02422 # endif /* Threads variety case */
02423 #else
02424   ACE_UNUSED_ARG (m);
02425   ACE_NOTSUP_RETURN (-1);
02426 #endif /* ACE_HAS_THREADS */
02427 }
02428 
02429 void
02430 ACE_OS::mutex_lock_cleanup (void *mutex)
02431 {
02432   ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
02433 #if defined (ACE_HAS_THREADS)
02434 # if defined (ACE_HAS_PTHREADS)
02435   ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex;
02436   ACE_OS::mutex_unlock (p_lock);
02437 # else
02438   ACE_UNUSED_ARG (mutex);
02439 # endif /* ACE_HAS_PTHREADS */
02440 #else
02441   ACE_UNUSED_ARG (mutex);
02442 #endif /* ACE_HAS_THREADS */
02443 }
02444 
02445 /*****************************************************************************/
02446 // MUTEXES END
02447 /*****************************************************************************/
02448 
02449 /*****************************************************************************/
02450 // EVENTS BEGIN
02451 /*****************************************************************************/
02452 
02453 int
02454 ACE_OS::event_destroy (ACE_event_t *event)
02455 {
02456 #if defined (ACE_WIN32)
02457   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1);
02458 #elif defined (ACE_HAS_THREADS)
02459   if (event->eventdata_)
02460 {
02461       // mutex_destroy()/cond_destroy() are called in a loop if the object
02462       // is BUSY.  This avoids conditions where we fail to destroy these
02463       // objects because at time of destroy they were just being used in
02464       // another thread possibly causing deadlocks later on if they keep
02465       // being used after we're gone.
02466 
02467   if (event->eventdata_->type_ == USYNC_PROCESS)
02468   {
02469     if (event->name_)
02470     {
02471       // Only destroy the event data if we're the ones who initialized
02472       // it.
02473 
02474       int r1, r2;
02475 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02476         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02477      (!defined (ACE_USES_FIFO_SEM) && \
02478         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02479       // first destroy the mutex so locking after this will return errors
02480       while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
02481               && errno == EBUSY)
02482       {
02483         ACE_OS::thr_yield ();
02484       }
02485 # else
02486       r1 = ACE_OS::sema_destroy(&event->lock_);
02487 # endif
02488 
02489 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02490     (!defined (ACE_USES_FIFO_SEM) && \
02491       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02492       // now fix event to manual reset, raise signal and broadcast until is's
02493       // possible to destroy the condition
02494       event->eventdata_->manual_reset_ = 1;
02495       while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
02496               && errno == EBUSY)
02497       {
02498         event->eventdata_->is_signaled_ = 1;
02499         ACE_OS::cond_broadcast (&event->eventdata_->condition_);
02500         ACE_OS::thr_yield ();
02501       }
02502 # else
02503       r2 = ACE_OS::sema_destroy(&event->semaphore_);
02504 # endif
02505       ACE_OS::munmap (event->eventdata_,
02506                       sizeof (ACE_eventdata_t));
02507       ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR(event->name_));
02508       ACE_OS::free (event->name_);
02509       return r1 != 0 || r2 != 0 ? -1 : 0;
02510     }
02511     else
02512     {
02513       ACE_OS::munmap (event->eventdata_,
02514                       sizeof (ACE_eventdata_t));
02515 # if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || \
02516         (defined (ACE_LACKS_MUTEXATTR_PSHARED) && defined (ACE_LACKS_CONDATTR_PSHARED))) && \
02517      (defined (ACE_USES_FIFO_SEM) || \
02518         (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_TIMEOUT) && defined (ACE_LACKS_NAMED_POSIX_SEM)))
02519       ACE_OS::sema_destroy(&event->lock_);
02520 # endif
02521 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02522     (!defined (ACE_USES_FIFO_SEM) && \
02523       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02524       return 0;
02525 # else
02526       return ACE_OS::sema_destroy(&event->semaphore_);
02527 # endif
02528     }
02529   }
02530   else
02531   {
02532     int r1, r2;
02533     // first destroy the mutex so locking after this will return errors
02534 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02535         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02536      (!defined (ACE_USES_FIFO_SEM) && \
02537         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02538       // first destroy the mutex so locking after this will return errors
02539       while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
02540               && errno == EBUSY)
02541       {
02542         ACE_OS::thr_yield ();
02543       }
02544 # else
02545       r1 = ACE_OS::sema_destroy(&event->lock_);
02546 # endif
02547 
02548 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02549     (!defined (ACE_USES_FIFO_SEM) && \
02550       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02551     // now fix event to manual reset, raise signal and broadcast until is's
02552     // possible to destroy the condition
02553     event->eventdata_->manual_reset_ = 1;
02554     while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
02555             && errno == EBUSY)
02556     {
02557       event->eventdata_->is_signaled_ = 1;
02558       ACE_OS::cond_broadcast (&event->eventdata_->condition_);
02559       ACE_OS::thr_yield ();
02560     }
02561 # else
02562     r2 = ACE_OS::sema_destroy(&event->semaphore_);
02563 # endif
02564     delete event->eventdata_;
02565     return r1 != 0 || r2 != 0 ? -1 : 0;
02566   }
02567 }
02568 
02569   return 0;
02570 #else
02571   ACE_UNUSED_ARG (event);
02572   ACE_NOTSUP_RETURN (-1);
02573 #endif /* ACE_WIN32 */
02574 }
02575 
02576 int
02577 ACE_OS::event_init (ACE_event_t *event,
02578                     int manual_reset,
02579                     int initial_state,
02580                     int type,
02581                     const char *name,
02582                     void *arg,
02583                     LPSECURITY_ATTRIBUTES sa)
02584 {
02585 #if defined (ACE_WIN32)
02586   ACE_UNUSED_ARG (type);
02587   ACE_UNUSED_ARG (arg);
02588   SECURITY_ATTRIBUTES sa_buffer;
02589   SECURITY_DESCRIPTOR sd_buffer;
02590 # if defined (ACE_HAS_WINCE)
02591   // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
02592   *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
02593                              (sa, &sa_buffer, &sd_buffer),
02594                            manual_reset,
02595                            initial_state,
02596                            ACE_Ascii_To_Wide (name).wchar_rep ());
02597 # else /* ACE_HAS_WINCE */
02598   *event = ::CreateEventA (ACE_OS::default_win32_security_attributes_r
02599                              (sa, &sa_buffer, &sd_buffer),
02600                            manual_reset,
02601                            initial_state,
02602                            name);
02603 # endif /* ACE_HAS_WINCE */
02604   if (*event == 0)
02605     ACE_FAIL_RETURN (-1);
02606   else
02607     return 0;
02608 #elif defined (ACE_HAS_THREADS)
02609   ACE_UNUSED_ARG (sa);
02610   event->eventdata_ = 0;
02611   ACE_eventdata_t* evtdata;
02612 
02613   if (type == USYNC_PROCESS)
02614     {
02615       int owner = 0;
02616       // Let's see if the shared memory entity already exists.
02617       ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
02618                                         O_RDWR | O_CREAT | O_EXCL,
02619                                         ACE_DEFAULT_FILE_PERMS);
02620       if (fd == ACE_INVALID_HANDLE)
02621         {
02622           if (errno == EEXIST)
02623             fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name),
02624                                    O_RDWR | O_CREAT,
02625                                    ACE_DEFAULT_FILE_PERMS);
02626           if (fd == ACE_INVALID_HANDLE)   // Still can't get it.
02627             return -1;
02628         }
02629       else
02630         {
02631           // We own this shared memory object!  Let's set its size.
02632           if (ACE_OS::ftruncate (fd, sizeof (ACE_eventdata_t)) == -1)
02633             {
02634               ACE_OS::close (fd);
02635               return -1;
02636             }
02637           owner = 1;
02638         }
02639 
02640       evtdata =
02641         (ACE_eventdata_t *) ACE_OS::mmap (0,
02642                                           sizeof (ACE_eventdata_t),
02643                                           PROT_RDWR,
02644                                           MAP_SHARED,
02645                                           fd,
02646                                           0);
02647       ACE_OS::close (fd);
02648       if (evtdata == MAP_FAILED)
02649         {
02650           if (owner)
02651             ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name));
02652           return -1;
02653         }
02654 
02655       if (owner)
02656         {
02657           event->name_ = ACE_OS::strdup (name);
02658           if (event->name_ == 0)
02659             {
02660               ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name));
02661               return -1;
02662             }
02663           event->eventdata_ = evtdata;
02664           event->eventdata_->type_ = type;
02665           event->eventdata_->manual_reset_ = manual_reset;
02666           event->eventdata_->is_signaled_ = initial_state;
02667           event->eventdata_->auto_event_signaled_ = false;
02668           event->eventdata_->waiting_threads_ = 0;
02669           event->eventdata_->signal_count_ = 0;
02670 
02671 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02672     (!defined (ACE_USES_FIFO_SEM) && \
02673       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02674           int result = ACE_OS::cond_init (&event->eventdata_->condition_,
02675                                           static_cast<short> (type),
02676                                           name,
02677                                           arg);
02678 # else
02679           char   sem_name[128];
02680           ACE_OS::strncpy (sem_name,
02681                            name,
02682                            sizeof (sem_name) - (1 + sizeof ("._ACE_EVTSEM_")));
02683           ACE_OS::strcat (sem_name, "._ACE_EVTSEM_");
02684           int result = ACE_OS::sema_init (&event->semaphore_,
02685                                           0,
02686                                           type,
02687                                           sem_name,
02688                                           arg);
02689 # endif
02690           if (result == 0)
02691 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02692         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02693      (!defined (ACE_USES_FIFO_SEM) && \
02694         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02695             result = ACE_OS::mutex_init (&event->eventdata_->lock_,
02696                                          type,
02697                                          name,
02698                                          (ACE_mutexattr_t *) arg);
02699 # else
02700           {
02701             char   lck_name[128];
02702             ACE_OS::strncpy
02703               (lck_name,
02704                name,
02705                sizeof (lck_name) - (1 + sizeof ("._ACE_EVTLCK_")));
02706             ACE_OS::strcat (lck_name, "._ACE_EVTLCK_");
02707             result = ACE_OS::sema_init (&event->lock_,
02708                                         0,
02709                                         type,
02710                                         lck_name,
02711                                         arg);
02712             if (result == 0)
02713               result = ACE_OS::sema_post (&event->lock_); /* Initially unlock */
02714           }
02715 # endif
02716           return result;
02717         }
02718       else
02719         {
02720           int result = 0;
02721 
02722           event->name_ = 0;
02723           event->eventdata_ = evtdata;
02724 #if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_CONDATTR_PSHARED)) && \
02725   (defined (ACE_USES_FIFO_SEM) || \
02726     (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_LACKS_NAMED_POSIX_SEM)))
02727           char   sem_name[128];
02728           ACE_OS::strncpy (sem_name,
02729                            name,
02730                            sizeof (sem_name) - (1 + sizeof ("._ACE_EVTSEM_")));
02731           ACE_OS::strcat (sem_name, "._ACE_EVTSEM_");
02732           result = ACE_OS::sema_init(&event->semaphore_,
02733                                      0,
02734                                      type,
02735                                      sem_name,
02736                                      arg);
02737 # endif
02738 
02739 # if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || \
02740         (defined (ACE_LACKS_MUTEXATTR_PSHARED) && defined (ACE_LACKS_CONDATTR_PSHARED))) && \
02741      (defined (ACE_USES_FIFO_SEM) || \
02742         (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_TIMEOUT) && defined (ACE_LACKS_NAMED_POSIX_SEM)))
02743           if (result == 0)
02744             {
02745               char   lck_name[128];
02746               ACE_OS::strncpy
02747                 (lck_name,
02748                  name,
02749                  sizeof (lck_name) - (1 + sizeof ("._ACE_EVTLCK_")));
02750               ACE_OS::strcat (lck_name, "._ACE_EVTLCK_");
02751               result = ACE_OS::sema_init (&event->lock_,
02752                                           0,
02753                                           type,
02754                                           lck_name,
02755                                           arg);
02756             }
02757 # endif
02758           return result;
02759         }
02760 
02761       return 0;
02762     }
02763   else
02764     {
02765       ACE_NEW_RETURN (evtdata, ACE_eventdata_t, -1);
02766       event->name_ = 0;
02767       event->eventdata_ = evtdata;
02768       event->eventdata_->type_ = type;
02769       event->eventdata_->manual_reset_ = manual_reset;
02770       event->eventdata_->is_signaled_ = initial_state;
02771       event->eventdata_->auto_event_signaled_ = false;
02772       event->eventdata_->waiting_threads_ = 0;
02773       event->eventdata_->signal_count_ = 0;
02774 
02775 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02776     (!defined (ACE_USES_FIFO_SEM) && \
02777       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02778       int result = ACE_OS::cond_init (&event->eventdata_->condition_,
02779                                       static_cast<short> (type),
02780                                       name,
02781                                       arg);
02782 # else
02783       int result = ACE_OS::sema_init (&event->semaphore_,
02784                                       0,
02785                                       type,
02786                                       name,
02787                                       arg);
02788 # endif
02789       if (result == 0)
02790 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02791         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02792      (!defined (ACE_USES_FIFO_SEM) && \
02793         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02794         result = ACE_OS::mutex_init (&event->eventdata_->lock_,
02795                                      type,
02796                                      name,
02797                                      (ACE_mutexattr_t *) arg);
02798 # else
02799       result = ACE_OS::sema_init (&event->lock_,
02800                                   0,
02801                                   type,
02802                                   name,
02803                                   arg);
02804       if (result == 0)
02805         result = ACE_OS::sema_post(&event->lock_);    /* initially unlock */
02806 # endif
02807 
02808       return result;
02809     }
02810 #else
02811   ACE_UNUSED_ARG (event);
02812   ACE_UNUSED_ARG (manual_reset);
02813   ACE_UNUSED_ARG (initial_state);
02814   ACE_UNUSED_ARG (type);
02815   ACE_UNUSED_ARG (name);
02816   ACE_UNUSED_ARG (arg);
02817   ACE_UNUSED_ARG (sa);
02818   ACE_NOTSUP_RETURN (-1);
02819 #endif /* ACE_WIN32 */
02820 }
02821 
02822 int
02823 ACE_OS::event_pulse (ACE_event_t *event)
02824 {
02825 #if defined (ACE_WIN32)
02826   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), ace_result_), int, -1);
02827 #elif defined (ACE_HAS_THREADS)
02828   int result = 0;
02829   int error = 0;
02830 
02831   // grab the lock first
02832 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02833         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02834      (!defined (ACE_USES_FIFO_SEM) && \
02835         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02836   if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
02837 # else
02838   if (ACE_OS::sema_wait (&event->lock_) == 0)
02839 # endif
02840   {
02841     if (event->eventdata_->waiting_threads_ > 0)
02842     {
02843       // Manual-reset event.
02844       if (event->eventdata_->manual_reset_ == 1)
02845       {
02846         // Wakeup all waiters.
02847 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02848     (!defined (ACE_USES_FIFO_SEM) && \
02849       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02850         if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
02851         {
02852           result = -1;
02853           error = errno;
02854         }
02855         if (result == 0)
02856           event->eventdata_->signal_count_ = event->eventdata_->waiting_threads_;
02857 # else
02858         event->eventdata_->signal_count_ = event->eventdata_->waiting_threads_;
02859         for (unsigned long i=0; i<event->eventdata_->signal_count_ ;++i)
02860           if (ACE_OS::sema_post(&event->semaphore_) != 0)
02861           {
02862             event->eventdata_->signal_count_ = 0;
02863             result = -1;
02864             error = errno;
02865           }
02866 
02867         if (result == 0)
02868           while(event->eventdata_->signal_count_!=0 && event->eventdata_->waiting_threads_!=0)
02869             ACE_OS::thr_yield ();
02870 # endif
02871       }
02872       // Auto-reset event: wakeup one waiter.
02873       else
02874       {
02875 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02876     (!defined (ACE_USES_FIFO_SEM) && \
02877       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02878         if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0)
02879 # else
02880         if (ACE_OS::sema_post(&event->semaphore_) != 0)
02881 # endif
02882         {
02883           result = -1;
02884           error = errno;
02885         }
02886 
02887         event->eventdata_->auto_event_signaled_ = true;
02888       }
02889     }
02890 
02891     // Reset event.
02892     event->eventdata_->is_signaled_ = 0;
02893 
02894     // Now we can let go of the lock.
02895 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02896         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02897      (!defined (ACE_USES_FIFO_SEM) && \
02898         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02899     ACE_OS::mutex_unlock (&event->eventdata_->lock_);
02900 # else
02901     ACE_OS::sema_post (&event->lock_);
02902 # endif
02903     if (result == -1)
02904       // Reset errno in case mutex_unlock() also fails...
02905       errno = error;
02906   }
02907   else
02908     result = -1;
02909   return result;
02910 #else
02911   ACE_UNUSED_ARG (event);
02912   ACE_NOTSUP_RETURN (-1);
02913 #endif /* ACE_WIN32 */
02914 }
02915 
02916 int
02917 ACE_OS::event_reset (ACE_event_t *event)
02918 {
02919 #if defined (ACE_WIN32)
02920   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1);
02921 #elif defined (ACE_HAS_THREADS)
02922   int result = 0;
02923 
02924   // Grab the lock first.
02925 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02926         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02927      (!defined (ACE_USES_FIFO_SEM) && \
02928         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02929   if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
02930 # else
02931   if (ACE_OS::sema_wait (&event->lock_) == 0)
02932 # endif
02933   {
02934     // Reset event.
02935     event->eventdata_->is_signaled_ = 0;
02936     event->eventdata_->auto_event_signaled_ = false;
02937 
02938     // Now we can let go of the lock.
02939 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02940         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02941      (!defined (ACE_USES_FIFO_SEM) && \
02942         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02943     ACE_OS::mutex_unlock (&event->eventdata_->lock_);
02944 # else
02945     ACE_OS::sema_post (&event->lock_);
02946 # endif
02947   }
02948   else
02949     result = -1;
02950   return result;
02951 #else
02952   ACE_UNUSED_ARG (event);
02953   ACE_NOTSUP_RETURN (-1);
02954 #endif /* ACE_WIN32 */
02955 }
02956 
02957 int
02958 ACE_OS::event_signal (ACE_event_t *event)
02959 {
02960 #if defined (ACE_WIN32)
02961   ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1);
02962 #elif defined (ACE_HAS_THREADS)
02963   int result = 0;
02964   int error = 0;
02965 
02966   // grab the lock first
02967 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
02968         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
02969      (!defined (ACE_USES_FIFO_SEM) && \
02970         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02971   if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
02972 # else
02973   if (ACE_OS::sema_wait (&event->lock_) == 0)
02974 # endif
02975   {
02976     // Manual-reset event.
02977     if (event->eventdata_->manual_reset_ == 1)
02978     {
02979       // wakeup all
02980 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
02981     (!defined (ACE_USES_FIFO_SEM) && \
02982       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
02983       if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
02984       {
02985         result = -1;
02986         error = errno;
02987       }
02988 # else
02989       if (ACE_OS::sema_post(&event->semaphore_) != 0)
02990       {
02991         result = -1;
02992         error = errno;
02993       }
02994 # endif
02995 
02996       if (result == 0)
02997         // signal event
02998         event->eventdata_->is_signaled_ = 1;
02999     }
03000     // Auto-reset event
03001     else
03002     {
03003       if (event->eventdata_->waiting_threads_ == 0)
03004         // No waiters: signal event.
03005         event->eventdata_->is_signaled_ = 1;
03006       // Waiters: wakeup one waiter.
03007 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
03008     (!defined (ACE_USES_FIFO_SEM) && \
03009       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03010       else if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0)
03011 # else
03012       else if (ACE_OS::sema_post(&event->semaphore_) != 0)
03013 # endif
03014       {
03015         result = -1;
03016         error = errno;
03017       }
03018 
03019       event->eventdata_->auto_event_signaled_ = true;
03020     }
03021 
03022     // Now we can let go of the lock.
03023 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
03024         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
03025      (!defined (ACE_USES_FIFO_SEM) && \
03026         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03027     ACE_OS::mutex_unlock (&event->eventdata_->lock_);
03028 # else
03029     ACE_OS::sema_post (&event->lock_);
03030 # endif
03031 
03032     if (result == -1)
03033       // Reset errno in case mutex_unlock() also fails...
03034       errno = error;
03035   }
03036   else
03037     result = -1;
03038 
03039   return result;
03040 #else
03041   ACE_UNUSED_ARG (event);
03042   ACE_NOTSUP_RETURN (-1);
03043 #endif /* ACE_WIN32 */
03044 }
03045 
03046 int
03047 ACE_OS::event_timedwait (ACE_event_t *event,
03048                          ACE_Time_Value *timeout,
03049                          int use_absolute_time)
03050 {
03051 #if defined (ACE_WIN32)
03052   DWORD result;
03053 
03054   if (timeout == 0)
03055     // Wait forever
03056     result = ::WaitForSingleObject (*event, INFINITE);
03057   else if (timeout->sec () == 0 && timeout->usec () == 0)
03058     // Do a "poll".
03059     result = ::WaitForSingleObject (*event, 0);
03060   else
03061   {
03062       // Wait for upto <relative_time> number of milliseconds.  Note
03063       // that we must convert between absolute time (which is passed
03064       // as a parameter) and relative time (which is what
03065       // WaitForSingleObjects() expects).
03066       // <timeout> parameter is given in absolute or relative value
03067       // depending on parameter <use_absolute_time>.
03068     int msec_timeout;
03069     if (use_absolute_time)
03070     {
03071           // Time is given in absolute time, we should use
03072           // gettimeofday() to calculate relative time
03073       ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
03074 
03075           // Watchout for situations where a context switch has caused
03076           // the current time to be > the timeout.  Thanks to Norbert
03077           // Rapp <NRapp@nexus-informatics.de> for pointing this.
03078       if (relative_time < ACE_Time_Value::zero)
03079         msec_timeout = 0;
03080       else
03081         msec_timeout = relative_time.msec ();
03082     }
03083     else
03084          // time is given in relative time, just convert it into
03085          // milliseconds and use it
03086       msec_timeout = timeout->msec ();
03087     result = ::WaitForSingleObject (*event, msec_timeout);
03088   }
03089 
03090   switch (result)
03091   {
03092     case WAIT_OBJECT_0:
03093       return 0;
03094     case WAIT_TIMEOUT:
03095       errno = ETIME;
03096       return -1;
03097     default:
03098       // This is a hack, we need to find an appropriate mapping...
03099       ACE_OS::set_errno_to_last_error ();
03100       return -1;
03101   }
03102 #elif defined (ACE_HAS_THREADS)
03103   int result = 0;
03104   int error = 0;
03105 
03106   // grab the lock first
03107 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
03108         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
03109      (!defined (ACE_USES_FIFO_SEM) && \
03110         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03111   if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
03112 # else
03113   if (ACE_OS::sema_wait (&event->lock_) == 0)
03114 # endif
03115   {
03116     if (event->eventdata_->is_signaled_ == 1)
03117     // event is currently signaled
03118     {
03119       if (event->eventdata_->manual_reset_ == 0)
03120       {
03121         // AUTO: reset state
03122         event->eventdata_->is_signaled_ = 0;
03123         event->eventdata_->auto_event_signaled_ = false;
03124       }
03125     }
03126     else
03127     // event is currently not signaled
03128     {
03129       event->eventdata_->waiting_threads_++;
03130 
03131       ACE_Time_Value absolute_timeout = *timeout;
03132 
03133       // cond_timewait() expects absolute time, check
03134       // <use_absolute_time> flag.
03135       if (use_absolute_time == 0)
03136         absolute_timeout += ACE_OS::gettimeofday ();
03137 
03138       while (event->eventdata_->is_signaled_ == 0 &&
03139              event->eventdata_->auto_event_signaled_ == false)
03140       {
03141 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
03142     (!defined (ACE_USES_FIFO_SEM) && \
03143       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03144         if (ACE_OS::cond_timedwait (&event->eventdata_->condition_,
03145                                     &event->eventdata_->lock_,
03146                                     &absolute_timeout) != 0)
03147         {
03148           result = -1;
03149           error = errno;
03150           break;
03151         }
03152 
03153         if (event->eventdata_->signal_count_ > 0)
03154         {
03155           event->eventdata_->signal_count_--;
03156           break;
03157         }
03158 # else
03159 #   if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
03160       (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03161         if (ACE_OS::mutex_unlock (&event->eventdata_->lock_) != 0)
03162 #   else
03163         if (ACE_OS::sema_post (&event->lock_) != 0)
03164 #   endif
03165         {
03166           event->eventdata_->waiting_threads_--;
03167           return -1;
03168         }
03169 
03170         if (ACE_OS::sema_wait(&event->semaphore_, absolute_timeout) !=0)
03171         {
03172           result = -1;
03173           if (errno == ETIMEDOUT) // Semaphores time out with ETIMEDOUT (POSIX)
03174             error = ETIME;
03175           else
03176             error = errno;
03177         }
03178 
03179         bool signalled = false;
03180         if (result == 0 && event->eventdata_->signal_count_ > 0)
03181         {
03182           event->eventdata_->signal_count_--;
03183           signalled = true;
03184         }
03185 
03186 #   if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
03187       (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03188         if (ACE_OS::mutex_lock (&event->eventdata_->lock_) != 0)
03189 #   else
03190         if (ACE_OS::sema_wait (&event->lock_) != 0)
03191 #   endif
03192         {
03193           event->eventdata_->waiting_threads_--;  // yes, I know it's not save
03194           return -1;
03195         }
03196 
03197         if (result)
03198           break;
03199 
03200         if (event->eventdata_->manual_reset_ == 1 && event->eventdata_->is_signaled_ == 1)
03201           if (ACE_OS::sema_post(&event->semaphore_) != 0)
03202           {
03203             result = -1;
03204             error = errno;
03205             break;
03206           }
03207 
03208         if (signalled)
03209           break;
03210 # endif
03211       }
03212 
03213       // Reset the auto_event_signaled_ to false now that we have
03214       // woken up.
03215       if (event->eventdata_->auto_event_signaled_ == true)
03216         event->eventdata_->auto_event_signaled_ = false;
03217 
03218       event->eventdata_->waiting_threads_--;
03219     }
03220 
03221     // Now we can let go of the lock.
03222 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
03223         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
03224      (!defined (ACE_USES_FIFO_SEM) && \
03225         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03226     ACE_OS::mutex_unlock (&event->eventdata_->lock_);
03227 # else
03228     ACE_OS::sema_post (&event->lock_);
03229 # endif
03230 
03231     if (result == -1)
03232       // Reset errno in case mutex_unlock() also fails...
03233       errno = error;
03234   }
03235   else
03236     result = -1;
03237   return result;
03238 #else
03239   ACE_UNUSED_ARG (event);
03240   ACE_UNUSED_ARG (timeout);
03241   ACE_UNUSED_ARG (use_absolute_time);
03242   ACE_NOTSUP_RETURN (-1);
03243 #endif /* ACE_WIN32 */
03244 }
03245 
03246 int
03247 ACE_OS::event_wait (ACE_event_t *event)
03248 {
03249 #if defined (ACE_WIN32)
03250   switch (::WaitForSingleObject (*event, INFINITE))
03251 {
03252   case WAIT_OBJECT_0:
03253     return 0;
03254   default:
03255     ACE_OS::set_errno_to_last_error ();
03256     return -1;
03257 }
03258 #elif defined (ACE_HAS_THREADS)
03259   int result = 0;
03260   int error = 0;
03261 
03262   // grab the lock first
03263 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
03264         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
03265      (!defined (ACE_USES_FIFO_SEM) && \
03266         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03267   if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
03268 # else
03269   if (ACE_OS::sema_wait (&event->lock_) == 0)
03270 # endif
03271   {
03272     if (event->eventdata_->is_signaled_ == 1)
03273     // Event is currently signaled.
03274     {
03275       if (event->eventdata_->manual_reset_ == 0)
03276         // AUTO: reset state
03277         event->eventdata_->is_signaled_ = 0;
03278     }
03279     else // event is currently not signaled
03280     {
03281       event->eventdata_->waiting_threads_++;
03282 
03283       while (event->eventdata_->is_signaled_ == 0 &&
03284              event->eventdata_->auto_event_signaled_ == false)
03285       {
03286 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
03287     (!defined (ACE_USES_FIFO_SEM) && \
03288       (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03289         if (ACE_OS::cond_wait (&event->eventdata_->condition_,
03290                                &event->eventdata_->lock_) != 0)
03291         {
03292           result = -1;
03293           error = errno;
03294           // Something went wrong...
03295           break;
03296         }
03297         if (event->eventdata_->signal_count_ > 0)
03298         {
03299           event->eventdata_->signal_count_--;
03300           break;
03301         }
03302 # else
03303 #   if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
03304       (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03305         if (ACE_OS::mutex_unlock (&event->eventdata_->lock_) != 0)
03306 #   else
03307         if (ACE_OS::sema_post (&event->lock_) != 0)
03308 #   endif
03309         {
03310           event->eventdata_->waiting_threads_--;
03311           return -1;
03312         }
03313 
03314         if (ACE_OS::sema_wait(&event->semaphore_) !=0)
03315         {
03316           result = -1;
03317           error = errno;
03318         }
03319 
03320         bool signalled = false;
03321         if (result == 0 && event->eventdata_->signal_count_ > 0)
03322         {
03323           event->eventdata_->signal_count_--;
03324           signalled = true;
03325         }
03326 
03327 #   if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
03328       (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03329         if (ACE_OS::mutex_lock (&event->eventdata_->lock_) != 0)
03330 #   else
03331         if (ACE_OS::sema_wait (&event->lock_) != 0)
03332 #   endif
03333         {
03334           event->eventdata_->waiting_threads_--;
03335           return -1;
03336         }
03337 
03338         if (result)
03339           break;
03340 
03341         if (event->eventdata_->manual_reset_ == 1 && event->eventdata_->is_signaled_ == 1)
03342           if (ACE_OS::sema_post(&event->semaphore_) != 0)
03343           {
03344             result = -1;
03345             error = errno;
03346             break;
03347           }
03348 
03349         if (signalled)
03350           break;
03351 # endif
03352     }
03353 
03354     // Reset it since we have woken up.
03355     if (event->eventdata_->auto_event_signaled_ == true)
03356       event->eventdata_->auto_event_signaled_ = false;
03357 
03358     event->eventdata_->waiting_threads_--;
03359   }
03360 
03361   // Now we can let go of the lock.
03362 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
03363         (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
03364      (!defined (ACE_USES_FIFO_SEM) && \
03365         (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
03366     ACE_OS::mutex_unlock (&event->eventdata_->lock_);
03367 # else
03368     ACE_OS::sema_post (&event->lock_);
03369 # endif
03370 
03371   if (result == -1)
03372     // Reset errno in case mutex_unlock() also fails...
03373     errno = error;
03374 }
03375   else
03376     result = -1;
03377   return result;
03378 #else
03379   ACE_UNUSED_ARG (event);
03380   ACE_NOTSUP_RETURN (-1);
03381 #endif /* ACE_WIN32 */
03382 }
03383 
03384 /*****************************************************************************/
03385 // EVENTS END
03386 /*****************************************************************************/
03387 
03388 int
03389 ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params)
03390 {
03391 #if defined (ACE_HAS_STHREADS) || defined (sun)
03392   // Get the class TS and RT class IDs.
03393   ACE_id_t rt_id;
03394   ACE_id_t ts_id;
03395   if (ACE_OS::scheduling_class ("RT", rt_id) == -1
03396       || ACE_OS::scheduling_class ("TS", ts_id) == -1)
03397     return -1;
03398 
03399   // Get this LWP's scheduling parameters.
03400   pcparms_t pcparms;
03401   // The following is just to avoid Purify warnings about unitialized
03402   // memory reads.
03403   ACE_OS::memset (&pcparms, 0, sizeof pcparms);
03404   pcparms.pc_cid = PC_CLNULL;
03405 
03406   if (ACE_OS::priority_control (P_LWPID,
03407                                 P_MYID,
03408                                 PC_GETPARMS,
03409                                 (char *) &pcparms) == -1)
03410     return -1;
03411   else if (pcparms.pc_cid == rt_id)
03412     {
03413       // RT class.
03414       rtparms_t rtparms;
03415       ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms);
03416 
03417       sched_params.policy (ACE_SCHED_FIFO);
03418       sched_params.priority (rtparms.rt_pri);
03419       sched_params.scope (ACE_SCOPE_THREAD);
03420       ACE_Time_Value quantum (rtparms.rt_tqsecs,
03421                               rtparms.rt_tqnsecs == RT_TQINF
03422                               ? 0 : rtparms.rt_tqnsecs * 1000);
03423       sched_params.quantum (quantum);
03424       return 0;
03425     }
03426   else if (pcparms.pc_cid == ts_id)
03427     {
03428       /* TS class */
03429       tsparms_t tsparms;
03430       ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms);
03431 
03432       sched_params.policy (ACE_SCHED_OTHER);
03433       sched_params.priority (tsparms.ts_upri);
03434       sched_params.scope (ACE_SCOPE_THREAD);
03435       return 0;
03436     }
03437   else
03438     return -1;
03439 
03440 #else  /* ! ACE_HAS_STHREADS && ! sun */
03441   ACE_UNUSED_ARG (sched_params);
03442   ACE_NOTSUP_RETURN (-1);
03443 #endif /* ! ACE_HAS_STHREADS && ! sun */
03444 }
03445 
03446 int
03447 ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params)
03448 {
03449 #if defined (ACE_HAS_STHREADS) || defined (sun)
03450   ACE_Sched_Params lwp_params (sched_params);
03451   lwp_params.scope (ACE_SCOPE_LWP);
03452   return ACE_OS::sched_params (lwp_params);
03453 #else  /* ! ACE_HAS_STHREADS && ! sun */
03454   ACE_UNUSED_ARG (sched_params);
03455   ACE_NOTSUP_RETURN (-1);
03456 #endif /* ! ACE_HAS_STHREADS && ! sun */
03457 }
03458 
03459 #if !defined (ACE_HAS_THREADS) || (defined (ACE_LACKS_RWLOCK_T) && \
03460                                    !defined (ACE_HAS_PTHREADS_UNIX98_EXT))
03461 int
03462 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
03463                      int type,
03464                      const ACE_TCHAR *name,
03465                      void *arg)
03466 {
03467   // ACE_OS_TRACE ("ACE_OS::rwlock_init");
03468 # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
03469   // NT, POSIX, and VxWorks don't support this natively.
03470   ACE_UNUSED_ARG (name);
03471   int result = -1;
03472 
03473   // Since we cannot use the user specified name for all three
03474   // objects, we will create three completely new names.
03475   ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN];
03476   ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN];
03477   ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN];
03478   ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN];
03479 
03480   ACE_OS::unique_name ((const void *) &rw->lock_,
03481                        name1,
03482                        ACE_UNIQUE_NAME_LEN);
03483   ACE_OS::unique_name ((const void *) &rw->waiting_readers_,
03484                        name2,
03485                        ACE_UNIQUE_NAME_LEN);
03486   ACE_OS::unique_name ((const void *) &rw->waiting_writers_,
03487                        name3,
03488                        ACE_UNIQUE_NAME_LEN);
03489   ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_,
03490                        name4,
03491                        ACE_UNIQUE_NAME_LEN);
03492 
03493   ACE_condattr_t attributes;
03494   if (ACE_OS::condattr_init (attributes, type) == 0)
03495     {
03496       if (ACE_OS::mutex_init (&rw->lock_, type, name1,
03497                               (ACE_mutexattr_t *) arg) == 0
03498           && ACE_OS::cond_init (&rw->waiting_readers_,
03499                                 attributes, name2, arg) == 0
03500           && ACE_OS::cond_init (&rw->waiting_writers_,
03501                                 attributes, name3, arg) == 0
03502           && ACE_OS::cond_init (&rw->waiting_important_writer_,
03503                                 attributes, name4, arg) == 0)
03504         {
03505           // Success!
03506           rw->ref_count_ = 0;
03507           rw->num_waiting_writers_ = 0;
03508           rw->num_waiting_readers_ = 0;
03509           rw->important_writer_ = 0;
03510           result = 0;
03511         }
03512       ACE_OS::condattr_destroy (attributes);
03513     }
03514 
03515   if (result == -1)
03516     {
03517       // Save/restore errno.
03518       ACE_Errno_Guard error (errno);
03519       ACE_OS::mutex_destroy (&rw->lock_);
03520       ACE_OS::cond_destroy (&rw->waiting_readers_);
03521       ACE_OS::cond_destroy (&rw->waiting_writers_);
03522       ACE_OS::cond_destroy (&rw->waiting_important_writer_);
03523     }
03524   return result;
03525 # else
03526   ACE_UNUSED_ARG (rw);
03527   ACE_UNUSED_ARG (type);
03528   ACE_UNUSED_ARG (name);
03529   ACE_UNUSED_ARG (arg);
03530   ACE_NOTSUP_RETURN (-1);
03531 # endif /* ACE_HAS_THREADS */
03532 }
03533 #endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
03534 
03535 int
03536 ACE_OS::sched_params (const ACE_Sched_Params &sched_params,
03537                       ACE_id_t id)
03538 {
03539   ACE_OS_TRACE ("ACE_OS::sched_params");
03540 #if defined (ACE_HAS_STHREADS)
03541   return ACE_OS::set_scheduling_params (sched_params, id);
03542 #elif defined (ACE_HAS_PTHREADS) && \
03543       (!defined (ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
03544       defined (ACE_HAS_PTHREAD_SCHEDPARAM))
03545   if (sched_params.quantum () != ACE_Time_Value::zero)
03546     {
03547       // quantums not supported
03548       errno = EINVAL;
03549       return -1;
03550     }
03551 
03552   // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
03553   // providing this code for 1003.1c PThreads.  Please note that this
03554   // has only been tested for POSIX 1003.1c threads, and may cause
03555   // problems with other PThreads flavors!
03556 
03557   struct sched_param param;
03558   param.sched_priority = sched_params.priority ();
03559 
03560   if (sched_params.scope () == ACE_SCOPE_PROCESS)
03561     {
03562 # if defined(ACE_TANDEM_T1248_PTHREADS) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
03563       ACE_NOTSUP_RETURN (-1);
03564 # else  /* ! ACE_TANDEM_T1248_PTHREADS */
03565       int result = ::sched_setscheduler (id == ACE_SELF ? 0 : id,
03566                                          sched_params.policy (),
03567                                          &param) == -1 ? -1 : 0;
03568 # if defined (DIGITAL_UNIX)
03569       return result == 0
03570         ? // Use priocntl (2) to set the process in the RT class,
03571         // if using an RT policy.
03572         ACE_OS::set_scheduling_params (sched_params)
03573         : result;
03574 # else  /* ! DIGITAL_UNIX */
03575       return result;
03576 # endif /* ! DIGITAL_UNIX */
03577 # endif /* ! ACE_TANDEM_T1248_PTHREADS */
03578     }
03579   else if (sched_params.scope () == ACE_SCOPE_THREAD)
03580     {
03581       ACE_thread_t thr_id = ACE_OS::thr_self ();
03582 
03583 # if defined (ACE_HAS_PTHREADS_DRAFT4)
03584       return (::pthread_setscheduler (thr_id,
03585                                       sched_params.policy (),
03586                                       sched_params.priority()) == -1 ? -1 : 0);
03587 # else
03588       int result;
03589       ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
03590                                                                     sched_params.policy (),
03591                                                                     &param),
03592                                            result),
03593                          int, -1);
03594 # endif  /* ACE_HAS_PTHREADS_DRAFT4 */
03595     }
03596 # if defined (sun)
03597   // We need to be able to set LWP priorities on Suns, even without
03598   // ACE_HAS_STHREADS, to obtain preemption.
03599   else if (sched_params.scope () == ACE_SCOPE_LWP)
03600     return ACE_OS::set_scheduling_params (sched_params, id);
03601 # endif /* sun */
03602   else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
03603     {
03604       errno = EINVAL;
03605       return -1;
03606     }
03607 
03608 #elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
03609 
03610   // PharLap ETS can act on the current thread - it can set the
03611   // quantum also, unlike Win32. All this only works on the RT
03612   // version.
03613 # if defined (ACE_HAS_PHARLAP_RT)
03614   if (id != ACE_SELF)
03615     ACE_NOTSUP_RETURN (-1);
03616 
03617   if (sched_params.quantum() != ACE_Time_Value::zero)
03618     EtsSetTimeSlice (sched_params.quantum().msec());
03619 
03620 # else
03621 
03622   if (sched_params.quantum () != ACE_Time_Value::zero)
03623     {
03624       // I don't know of a way to set the quantum on Win32.
03625       errno = EINVAL;
03626       return -1;
03627     }
03628 
03629   if (sched_params.scope () == ACE_SCOPE_THREAD)
03630     {
03631 
03632       // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
03633       // a VERY BAD THING. This include guard will allow people
03634       // to easily disable this feature in ACE.
03635 #ifndef ACE_DISABLE_WIN32_INCREASE_PRIORITY
03636       // Set the priority class of this process to the REALTIME process class
03637       // _if_ the policy is ACE_SCHED_FIFO.  Otherwise, set to NORMAL.
03638       if (!::SetPriorityClass (::GetCurrentProcess (),
03639                                (sched_params.policy () == ACE_SCHED_FIFO ||
03640                                 sched_params.policy () == ACE_SCHED_RR)
03641                                ? REALTIME_PRIORITY_CLASS
03642                                : NORMAL_PRIORITY_CLASS))
03643         {
03644           ACE_OS::set_errno_to_last_error ();
03645           return -1;
03646         }
03647 #endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
03648 
03649 # endif /* ACE_HAS_PHARLAP_RT */
03650       // Now that we have set the priority class of the process, set the
03651       // priority of the current thread to the desired value.
03652       return ACE_OS::thr_setprio (sched_params.priority ());
03653     }
03654   else if (sched_params.scope () == ACE_SCOPE_PROCESS)
03655     {
03656       HANDLE hProcess = ::OpenProcess (PROCESS_SET_INFORMATION,
03657                                        FALSE,
03658                                        id);
03659       if (!hProcess)
03660         {
03661           ACE_OS::set_errno_to_last_error();
03662           return -1;
03663         }
03664       // There is no way for us to set the priority of the thread when we
03665       // are setting the priority of a different process.  So just ignore
03666       // the priority argument when ACE_SCOPE_PROCESS is specified.
03667       // Setting the priority class will automatically increase the base
03668       // priority of all the threads within a process while maintaining the
03669       // relative priorities of the threads within it.
03670       if (!::SetPriorityClass (hProcess,
03671                                (sched_params.policy () == ACE_SCHED_FIFO ||
03672                                 sched_params.policy () == ACE_SCHED_RR)
03673                                ? REALTIME_PRIORITY_CLASS
03674                                : NORMAL_PRIORITY_CLASS))
03675         {
03676           ACE_OS::set_errno_to_last_error ();
03677           ::CloseHandle (hProcess);
03678           return -1;
03679         }
03680       ::CloseHandle (hProcess);
03681       return 0;
03682     }
03683   else
03684     {
03685       errno = EINVAL;
03686       return -1;
03687     }
03688 #elif defined (ACE_VXWORKS)
03689   ACE_UNUSED_ARG (id);
03690 
03691   // There is only one class of priorities on VxWorks, and no time
03692   // quanta.  So, just set the current thread's priority.
03693 
03694   if (sched_params.policy () != ACE_SCHED_FIFO
03695       || sched_params.scope () != ACE_SCOPE_PROCESS
03696       || sched_params.quantum () != ACE_Time_Value::zero)
03697     {
03698       errno = EINVAL;
03699       return -1;
03700     }
03701 
03702   // Set the thread priority on the current thread.
03703   return ACE_OS::thr_setprio (sched_params.priority ());
03704 #else
03705   ACE_UNUSED_ARG (sched_params);
03706   ACE_UNUSED_ARG (id);
03707   ACE_NOTSUP_RETURN (-1);
03708 #endif /* ACE_HAS_STHREADS */
03709 }
03710 
03711 int
03712 ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id)
03713 {
03714 #if defined (ACE_HAS_PRIOCNTL)
03715   // Get the priority class ID.
03716   pcinfo_t pcinfo;
03717   // The following is just to avoid Purify warnings about unitialized
03718   // memory reads.
03719   ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
03720 
03721   ACE_OS::strcpy (pcinfo.pc_clname, class_name);
03722   if (ACE_OS::priority_control (P_ALL /* ignored */,
03723                                 P_MYID /* ignored */,
03724                                 PC_GETCID,
03725                                 (char *) &pcinfo) == -1)
03726     {
03727       return -1;
03728     }
03729   else
03730     {
03731       id = pcinfo.pc_cid;
03732       return 0;
03733     }
03734 #else  /* ! ACE_HAS_PRIOCNTL */
03735   ACE_UNUSED_ARG (class_name);
03736   ACE_UNUSED_ARG (id);
03737   ACE_NOTSUP_RETURN (-1);
03738 #endif /* ! ACE_HAS_PRIOCNTL */
03739 }
03740 
03741 int
03742 ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params,
03743                                ACE_id_t id)
03744 {
03745 #if defined (ACE_HAS_PRIOCNTL)
03746   // Set priority class, priority, and quantum of this LWP or process as
03747   // specified in sched_params.
03748 
03749   // Get the priority class ID.
03750   ACE_id_t class_id;
03751   if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER  ?
03752                                   "TS"  :
03753                                   "RT", class_id) == -1)
03754     {
03755       return -1;
03756     }
03757 
03758   pcparms_t pcparms;
03759   // The following is just to avoid Purify warnings about unitialized
03760   // memory reads.
03761   ACE_OS::memset (&pcparms, 0, sizeof pcparms);
03762 
03763   pcparms.pc_cid = class_id;
03764 
03765   if (sched_params.policy () == ACE_SCHED_OTHER  &&
03766       sched_params.quantum () == ACE_Time_Value::zero)
03767       // SunOS doesn't support non-zero quantums in time-sharing class:  use
03768       // real-time class instead.
03769     {
03770       tsparms_t tsparms;
03771       // The following is just to avoid Purify warnings about unitialized
03772       // memory reads.
03773       ACE_OS::memset (&tsparms, 0, sizeof tsparms);
03774 
03775       // Don't change ts_uprilim (user priority limit)
03776       tsparms.ts_uprilim = TS_NOCHANGE;
03777       tsparms.ts_upri = sched_params.priority ();
03778 
03779       // Package up the TS class ID and parameters for the
03780       // priority_control () call.
03781       ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms);
03782     }
03783   else if (sched_params.policy () == ACE_SCHED_FIFO  ||
03784            (sched_params.policy () == ACE_SCHED_RR &&
03785             sched_params.quantum () != ACE_Time_Value::zero))
03786            // must have non-zero quantum for RR, to make it meaningful
03787            // A zero quantum with FIFO has special significance:  it actually
03788            // means infinite time quantum, i.e., run-to-completion.
03789     {
03790       rtparms_t rtparms;
03791       // The following is just to avoid Purify warnings about unitialized
03792       // memory reads.
03793       ACE_OS::memset (&rtparms, 0, sizeof rtparms);
03794 
03795       rtparms.rt_pri = sched_params.priority ();
03796 
03797       if (sched_params.quantum () == ACE_Time_Value::zero)
03798         {
03799           // rtparms.rt_tqsecs is ignored with RT_TQINF
03800           rtparms.rt_tqnsecs = RT_TQINF;
03801         }
03802       else
03803         {
03804           rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec ();
03805           rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000;
03806         }
03807 
03808       // Package up the RT class ID and parameters for the
03809       // priority_control () call.
03810       ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms);
03811     }
03812   else
03813     {
03814       errno = EINVAL;
03815       return -1;
03816     }
03817 
03818   if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD
03819                                             ? ACE_SCOPE_PROCESS
03820                                             : sched_params.scope ()),
03821                                 id,
03822                                 PC_SETPARMS,
03823                                 (char *) &pcparms) < 0)
03824     {
03825       return ACE_OS::last_error ();
03826     }
03827 
03828   return 0;
03829 #else  /* ! ACE_HAS_PRIOCNTL */
03830   ACE_UNUSED_ARG (sched_params);
03831   ACE_UNUSED_ARG (id);
03832   ACE_NOTSUP_RETURN (-1);
03833 #endif /* ! ACE_HAS_PRIOCNTL */
03834 }
03835 
03836 int
03837 ACE_OS::thr_create (ACE_THR_FUNC func,
03838                     void *args,
03839                     long flags,
03840                     ACE_thread_t *thr_id,
03841                     ACE_hthread_t *thr_handle,
03842                     long priority,
03843                     void *stack,
03844                     size_t stacksize,
03845                     ACE_Base_Thread_Adapter *thread_adapter)
03846 {
03847   ACE_OS_TRACE ("ACE_OS::thr_create");
03848 
03849   if (ACE_BIT_DISABLED (flags, THR_DETACHED) &&
03850       ACE_BIT_DISABLED (flags, THR_JOINABLE))
03851     ACE_SET_BITS (flags, THR_JOINABLE);
03852 
03853 #if defined (ACE_NO_THREAD_ADAPTER)
03854 # define  ACE_THREAD_FUNCTION  func
03855 # define  ACE_THREAD_ARGUMENT  args
03856 #else /* ! defined (ACE_NO_THREAD_ADAPTER) */
03857 # define  ACE_THREAD_FUNCTION  thread_args->entry_point ()
03858 # define  ACE_THREAD_ARGUMENT  thread_args
03859 #endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
03860 
03861 
03862   ACE_Base_Thread_Adapter *thread_args = 0;
03863   if (thread_adapter == 0)
03864 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
03865     ACE_NEW_RETURN (thread_args,
03866                     ACE_OS_Thread_Adapter (func, args,
03867                                            (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
03868                                            ACE_OS_Object_Manager::seh_except_selector(),
03869                                            ACE_OS_Object_Manager::seh_except_handler()),
03870                     -1);
03871 #else
03872   ACE_NEW_RETURN (thread_args,
03873                   ACE_OS_Thread_Adapter (func, args,
03874                                          (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME),
03875                   -1);
03876 
03877 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
03878   else
03879     thread_args = thread_adapter;
03880 
03881   auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
03882 
03883   if (thread_adapter == 0)
03884     ACE_AUTO_PTR_RESET (auto_thread_args,
03885                         thread_args,
03886                         ACE_Base_Thread_Adapter);
03887 
03888 #if defined (ACE_HAS_THREADS)
03889 
03890   // *** Set Stack Size
03891 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
03892   if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
03893     stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
03894 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
03895 
03896 # if !(defined (ACE_VXWORKS) && !defined (ACE_HAS_PTHREADS))
03897   // On VxWorks, using the task API, the OS will provide a task name if
03898   // the user doesn't. So, we don't need to create a tmp_thr.  If the
03899   // caller of this member function is the Thread_Manager, than thr_id
03900   // will be non-zero anyways.
03901   ACE_thread_t tmp_thr;
03902 
03903   if (thr_id == 0)
03904     thr_id = &tmp_thr;
03905 # endif /* !(ACE_VXWORKS && !ACE_HAS_PTHREADS) */
03906 
03907   ACE_hthread_t tmp_handle;
03908   if (thr_handle == 0)
03909     thr_handle = &tmp_handle;
03910 
03911 # if defined (ACE_HAS_PTHREADS)
03912 
03913   int result;
03914 # if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
03915   /* Tests show that VxWorks 6.x pthread lib does not only
03916    * require zeroing of mutex/condition objects to function correctly
03917    * but also of the attribute objects.
03918    */
03919   pthread_attr_t attr = {0};
03920 #   else
03921   pthread_attr_t attr;
03922 #   endif
03923 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
03924   if (ACE_ADAPT_RETVAL(::pthread_attr_create (&attr), result) != 0)
03925 #   else /* ACE_HAS_PTHREADS_DRAFT4 */
03926   if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr), result) != 0)
03927 #   endif /* ACE_HAS_PTHREADS_DRAFT4 */
03928       return -1;
03929 
03930   if (stacksize != 0)
03931     {
03932       size_t size = stacksize;
03933 
03934 #   if defined (PTHREAD_STACK_MIN)
03935       if (size < static_cast <size_t> (PTHREAD_STACK_MIN))
03936         size = PTHREAD_STACK_MIN;
03937 #   endif /* PTHREAD_STACK_MIN */
03938 
03939 #   if !defined (ACE_LACKS_THREAD_STACK_SIZE)      // JCEJ 12/17/96
03940 #     if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
03941       if (::pthread_attr_setstacksize (&attr, size) != 0)
03942 #     else
03943 #       if defined (ACE_HAS_PTHREAD_SETSTACK)
03944         int result;
03945         if (stack != 0)
03946           result = ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr, stack, size), result);
03947         else
03948           result = ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result);
03949         if (result == -1)
03950 #       else
03951         if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result) == -1)
03952 #       endif /* ACE_HAS_PTHREAD_SETSTACK */
03953 #     endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */
03954           {
03955 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
03956             ::pthread_attr_delete (&attr);
03957 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
03958             ::pthread_attr_destroy (&attr);
03959 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
03960             return -1;
03961           }
03962 #   else
03963       ACE_UNUSED_ARG (size);
03964 #   endif /* !ACE_LACKS_THREAD_STACK_SIZE */
03965     }
03966 
03967   // *** Set Stack Address
03968 #   if !defined (ACE_HAS_PTHREAD_SETSTACK)
03969 #     if !defined (ACE_LACKS_THREAD_STACK_ADDR)
03970   if (stack != 0)
03971     {
03972       if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr, stack), result) != 0)
03973         {
03974 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
03975           ::pthread_attr_delete (&attr);
03976 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
03977           ::pthread_attr_destroy (&attr);
03978 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
03979           return -1;
03980         }
03981     }
03982 #     else
03983   ACE_UNUSED_ARG (stack);
03984 #     endif /* !ACE_LACKS_THREAD_STACK_ADDR */
03985 #   endif /* ACE_HAS_PTHREAD_SETSTACK */
03986 
03987   // *** Deal with various attributes
03988   if (flags != 0)
03989     {
03990       // *** Set Detach state
03991 #   if !defined (ACE_LACKS_SETDETACH)
03992       if (ACE_BIT_ENABLED (flags, THR_DETACHED)
03993           || ACE_BIT_ENABLED (flags, THR_JOINABLE))
03994         {
03995           int dstate = PTHREAD_CREATE_JOINABLE;
03996 
03997           if (ACE_BIT_ENABLED (flags, THR_DETACHED))
03998             dstate = PTHREAD_CREATE_DETACHED;
03999 
04000 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04001           if (::pthread_attr_setdetach_np (&attr, dstate) != 0)
04002 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04003 #       if defined (ACE_HAS_PTHREADS_DRAFT6)
04004             if (::pthread_attr_setdetachstate (&attr, &dstate) != 0)
04005 #       else
04006               if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
04007                                    result) != 0)
04008 #       endif /* ACE_HAS_PTHREADS_DRAFT6 */
04009 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04010                 {
04011 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04012                   ::pthread_attr_delete (&attr);
04013 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04014                   ::pthread_attr_destroy (&attr);
04015 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04016                   return -1;
04017                 }
04018         }
04019 
04020       // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
04021       // call ::pthread_detach () below.  If THR_DETACHED is not
04022       // enabled, we call ::pthread_detach () in the Thread_Manager,
04023       // after joining with the thread.
04024 #   endif /* ACE_LACKS_SETDETACH */
04025 
04026       // *** Set Policy
04027 #   if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
04028       // If we wish to set the priority explicitly, we have to enable
04029       // explicit scheduling, and a policy, too.
04030       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
04031         {
04032           ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
04033           if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
04034               && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
04035               && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
04036             ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
04037         }
04038 
04039       if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
04040           || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
04041           || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
04042         {
04043           int spolicy;
04044 
04045 #     if defined (ACE_HAS_ONLY_SCHED_OTHER)
04046           // SunOS, thru version 5.6, only supports SCHED_OTHER.
04047           spolicy = SCHED_OTHER;
04048 #     elif defined (ACE_HAS_ONLY_SCHED_FIFO)
04049           // NonStop OSS standard pthread supports only SCHED_FIFO.
04050           spolicy = SCHED_FIFO;
04051 #     else
04052           // Make sure to enable explicit scheduling, in case we didn't
04053           // enable it above (for non-default priority).
04054           ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
04055 
04056           if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
04057             spolicy = SCHED_OTHER;
04058           else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
04059             spolicy = SCHED_FIFO;
04060 #       if defined (SCHED_IO)
04061           else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
04062             spolicy = SCHED_IO;
04063 #       else
04064           else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
04065             {
04066               errno = ENOSYS;
04067               return -1;
04068             }
04069 #       endif /* SCHED_IO */
04070           else
04071             spolicy = SCHED_RR;
04072 
04073 #       if defined (ACE_HAS_FSU_PTHREADS)
04074           int ret;
04075           switch (spolicy)
04076             {
04077             case SCHED_FIFO:
04078             case SCHED_RR:
04079               ret = 0;
04080               break;
04081             default:
04082               ret = 22;
04083               break;
04084             }
04085           if (ret != 0)
04086             {
04087               ::pthread_attr_destroy (&attr);
04088               return -1;
04089             }
04090 #       endif    /*  ACE_HAS_FSU_PTHREADS */
04091 
04092 #     endif /* ACE_HAS_ONLY_SCHED_OTHER */
04093 
04094 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04095           result = ::pthread_attr_setsched (&attr, spolicy);
04096 #     elif defined (ACE_HAS_PTHREADS_DRAFT6)
04097           result = ::pthread_attr_setschedpolicy (&attr, spolicy);
04098 #     else  /* draft 7 or std */
04099           (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
04100                            result);
04101 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04102           if (result != 0)
04103             {
04104 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04105               ::pthread_attr_delete (&attr);
04106 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04107               ::pthread_attr_destroy (&attr);
04108 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04109               return -1;
04110             }
04111         }
04112 
04113       // *** Set Priority (use reasonable default priorities)
04114 #     if defined(ACE_HAS_PTHREADS_STD)
04115       // If we wish to explicitly set a scheduling policy, we also
04116       // have to specify a priority.  We choose a "middle" priority as
04117       // default.  Maybe this is also necessary on other POSIX'ish
04118       // implementations?
04119       if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
04120            || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
04121            || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
04122           && priority == ACE_DEFAULT_THREAD_PRIORITY)
04123         {
04124           if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
04125             priority = ACE_THR_PRI_FIFO_DEF;
04126           else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
04127             priority = ACE_THR_PRI_RR_DEF;
04128           else // THR_SCHED_DEFAULT
04129             priority = ACE_THR_PRI_OTHER_DEF;
04130         }
04131 #     endif /* ACE_HAS_PTHREADS_STD */
04132       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
04133         {
04134           struct sched_param sparam;
04135           ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
04136 
04137 #     if defined (ACE_HAS_IRIX62_THREADS)
04138           sparam.sched_priority = ACE_MIN (priority,
04139                                            (long) PTHREAD_MAX_PRIORITY);
04140 #     elif defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS_STD)
04141           /* For MIT pthreads... */
04142           sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
04143 #     elif defined(ACE_HAS_PTHREADS_STD) && !defined (ACE_HAS_STHREADS)
04144           // The following code forces priority into range.
04145           if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
04146             sparam.sched_priority =
04147               ACE_MIN (ACE_THR_PRI_FIFO_MAX,
04148                        ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
04149           else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
04150             sparam.sched_priority =
04151               ACE_MIN (ACE_THR_PRI_RR_MAX,
04152                        ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
04153           else // Default policy, whether set or not
04154             sparam.sched_priority =
04155               ACE_MIN (ACE_THR_PRI_OTHER_MAX,
04156                        ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
04157 #     elif defined (PRIORITY_MAX)
04158           sparam.sched_priority = ACE_MIN (priority,
04159                                            (long) PRIORITY_MAX);
04160 #     else
04161           sparam.sched_priority = priority;
04162 #     endif /* ACE_HAS_IRIX62_THREADS */
04163 
04164 #     if defined (ACE_HAS_FSU_PTHREADS)
04165           if (sparam.sched_priority >= PTHREAD_MIN_PRIORITY
04166               && sparam.sched_priority <= PTHREAD_MAX_PRIORITY)
04167             attr.prio = sparam.sched_priority;
04168           else
04169             {
04170               pthread_attr_destroy (&attr);
04171               errno = EINVAL;
04172               return -1;
04173             }
04174 #     else
04175           {
04176 #       if defined (sun)  &&  defined (ACE_HAS_ONLY_SCHED_OTHER)
04177             // SunOS, through 5.6, POSIX only allows priorities > 0 to
04178             // ::pthread_attr_setschedparam.  If a priority of 0 was
04179             // requested, set the thread priority after creating it, below.
04180             if (priority > 0)
04181 #       endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
04182               {
04183 #       if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
04184                 result = ::pthread_attr_setprio (&attr,
04185                                                  sparam.sched_priority);
04186 #       else /* this is draft 7 or std */
04187                 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
04188                                         result);
04189 #       endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */
04190                 if (result != 0)
04191                   {
04192 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
04193                     ::pthread_attr_delete (&attr);
04194 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
04195                     ::pthread_attr_destroy (&attr);
04196 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
04197                     return -1;
04198                   }
04199               }
04200           }
04201 #     endif    /* ACE_HAS_FSU_PTHREADS */
04202         }
04203 
04204       // *** Set scheduling explicit or inherited
04205       if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
04206           || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
04207         {
04208 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04209           int sched = PTHREAD_DEFAULT_SCHED;
04210 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04211           int sched = PTHREAD_EXPLICIT_SCHED;
04212 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04213           if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
04214             sched = PTHREAD_INHERIT_SCHED;
04215           if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr, sched), result) != 0)
04216             {
04217 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04218               ::pthread_attr_delete (&attr);
04219 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04220               ::pthread_attr_destroy (&attr);
04221 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04222               return -1;
04223             }
04224         }
04225 #   else /* ACE_LACKS_SETSCHED */
04226       ACE_UNUSED_ARG (priority);
04227 #   endif /* ACE_LACKS_SETSCHED */
04228 
04229       // *** Set Scope
04230 #   if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
04231       if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
04232           || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
04233         {
04234 #     if defined (ACE_CONFIG_LINUX_H) || defined (HPUX)
04235           // LinuxThreads do not have support for PTHREAD_SCOPE_PROCESS.
04236           // Neither does HPUX (up to HP-UX 11.00, as far as I know).
04237           int scope = PTHREAD_SCOPE_SYSTEM;
04238 #     else /* ACE_CONFIG_LINUX_H */
04239           int scope = PTHREAD_SCOPE_PROCESS;
04240 #     endif /* ACE_CONFIG_LINUX_H */
04241           if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
04242             scope = PTHREAD_SCOPE_SYSTEM;
04243 
04244           if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr, scope), result) != 0)
04245             {
04246 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04247               ::pthread_attr_delete (&attr);
04248 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04249               ::pthread_attr_destroy (&attr);
04250 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04251               return -1;
04252             }
04253         }
04254 #   endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
04255 
04256 #   ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
04257       if (ACE_BIT_ENABLED (flags, THR_SUSPENDED))
04258         {
04259            if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr), result) != 0)
04260              {
04261 
04262 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04263               ::pthread_attr_delete (&attr);
04264 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
04265               ::pthread_attr_destroy (&attr);
04266 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04267               return -1;
04268             }
04269         }
04270 #   endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
04271 
04272       if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
04273         {
04274           // Increment the number of LWPs by one to emulate the
04275           // SunOS semantics.
04276           int lwps = ACE_OS::thr_getconcurrency ();
04277           if (lwps == -1)
04278             {
04279               if (errno == ENOTSUP)
04280                 // Suppress the ENOTSUP because it's harmless.
04281                 errno = 0;
04282               else
04283                 // This should never happen on SunOS:
04284                 // ::thr_getconcurrency () should always succeed.
04285                 return -1;
04286             }
04287           else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
04288             {
04289               if (errno == ENOTSUP)
04290                 {
04291                   // Unlikely: ::thr_getconcurrency () is supported
04292                   // but ::thr_setconcurrency () is not?
04293                 }
04294               else
04295                 return -1;
04296             }
04297         }
04298     }
04299 
04300 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
04301   ACE_OSCALL (::pthread_create (thr_id, attr,
04302                                 thread_args->entry_point (),
04303                                 thread_args),
04304               int, -1, result);
04305 
04306 #     if defined (ACE_LACKS_SETDETACH)
04307   if (ACE_BIT_ENABLED (flags, THR_DETACHED))
04308     {
04309       ::pthread_detach (thr_id);
04310     }
04311 #     endif /* ACE_LACKS_SETDETACH */
04312 
04313   ::pthread_attr_delete (&attr);
04314 
04315 #   elif defined (ACE_HAS_PTHREADS_DRAFT6)
04316   ACE_OSCALL (::pthread_create (thr_id, &attr,
04317                                 thread_args->entry_point (),
04318                                 thread_args),
04319               int, -1, result);
04320   ::pthread_attr_destroy (&attr);
04321 
04322 #   else /* this is draft 7 or std */
04323   ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
04324                                                   &attr,
04325                                                   thread_args->entry_point (),
04326                                                   thread_args),
04327                                 result),
04328               int, -1, result);
04329   ::pthread_attr_destroy (&attr);
04330 #   endif /* ACE_HAS_PTHREADS_DRAFT4 */
04331 
04332   // This is a SunOS or POSIX implementation of pthreads, where we
04333   // assume that ACE_thread_t and ACE_hthread_t are the same.  If this
04334   // *isn't* correct on some platform, please let us know.
04335   if (result != -1)
04336     *thr_handle = *thr_id;
04337 
04338 #   if defined (sun)  &&  defined (ACE_HAS_ONLY_SCHED_OTHER)
04339   // SunOS prior to 5.7:
04340 
04341   // If the priority is 0, then we might have to set it now because we
04342   // couldn't set it with ::pthread_attr_setschedparam, as noted
04343   // above.  This doesn't provide strictly correct behavior, because
04344   // the thread was created (above) with the priority of its parent.
04345   // (That applies regardless of the inherit_sched attribute: if it
04346   // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
04347   // parent's priority.  If it was PTHREAD_EXPLICIT_SCHED, then "attr"
04348   // was initialized by the SunOS ::pthread_attr_init () to contain
04349   // NULL for the priority, which indicated to SunOS ::pthread_create
04350   // () to inherit the parent priority.)
04351   if (priority == 0)
04352     {
04353       // Check the priority of this thread, which is the parent
04354       // of the newly created thread.  If it is 0, then the
04355       // newly created thread will have inherited the priority
04356       // of 0, so there's no need to explicitly set it.
04357       struct sched_param sparam;
04358       int policy = 0;
04359       ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
04360                                                              &policy,
04361                                                              &sparam),
04362                                     result), int,
04363                   -1, result);
04364 
04365       // The only policy supported by by SunOS, thru version 5.6,
04366       // is SCHED_OTHER, so that's hard-coded here.
04367       policy = ACE_SCHED_OTHER;
04368 
04369       if (sparam.sched_priority != 0)
04370         {
04371           ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
04372           // The memset to 0 sets the priority to 0, so we don't need
04373           // to explicitly set sparam.sched_priority.
04374 
04375           ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id,
04376                                                                         policy,
04377                                                                         &sparam),
04378                                                result),
04379                              int, -1);
04380         }
04381     }
04382 
04383 #     if defined (ACE_NEEDS_LWP_PRIO_SET)
04384 #       if 0
04385   // It would be useful if we could make this work.  But, it requires
04386   // a mechanism for determining the ID of an LWP to which another
04387   // thread is bound.  Is there a way to do that?  Instead, just rely
04388   // on the code in ACE_Thread_Adapter::invoke () to set the LWP
04389   // priority.
04390 
04391   // If the thread is bound, then set the priority on its LWP.
04392   if (ACE_BIT_ENABLED (flags, THR_BOUND))
04393     {
04394       ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) ||
04395                                      ACE_BIT_ENABLED (flags, THR_SCHED_RR)  ?
04396                                      ACE_SCHED_FIFO  :
04397                                      ACE_SCHED_OTHER,
04398                                      priority);
04399       result = ACE_OS::lwp_setparams (sched_params,
04400                                       /* ? How do we find the ID of the LWP
04401                                          to which *thr_id is bound? */);
04402     }
04403 #       endif /* 0 */
04404 #     endif /* ACE_NEEDS_LWP_PRIO_SET */
04405 
04406 #   endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
04407   auto_thread_args.release ();
04408   return result;
04409 # elif defined (ACE_HAS_STHREADS)
04410   int result;
04411   int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
04412 
04413   if (priority != ACE_DEFAULT_THREAD_PRIORITY)
04414     // If we need to set the priority, then we need to start the
04415     // thread in a suspended mode.
04416     ACE_SET_BITS (flags, THR_SUSPENDED);
04417 
04418   ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize,
04419                                               thread_args->entry_point (),
04420                                               thread_args,
04421                                               flags, thr_id), result),
04422               int, -1, result);
04423 
04424   if (result != -1)
04425     {
04426       // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
04427       *thr_handle = *thr_id;
04428 
04429       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
04430         {
04431           // Set the priority of the new thread and then let it
04432           // continue, but only if the user didn't start it suspended
04433           // in the first place!
04434           result = ACE_OS::thr_setprio (*thr_id, priority);
04435           if (result != 0)
04436             {
04437               errno = result;
04438               return -1;
04439             }
04440 
04441           if (start_suspended == 0)
04442             {
04443               result = ACE_OS::thr_continue (*thr_id);
04444               if (result != 0)
04445                 {
04446                   errno = result;
04447                   return -1;
04448                 }
04449             }
04450         }
04451     }
04452   auto_thread_args.release ();
04453   return result;
04454 # elif defined (ACE_HAS_WTHREADS)
04455   ACE_UNUSED_ARG (stack);
04456 #   if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
04457   if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
04458     {
04459       CWinThread *cwin_thread =
04460         ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
04461                           thread_args,
04462                           priority,
04463                           0,
04464                           flags | THR_SUSPENDED);
04465       // Have to duplicate the handle because
04466       // CWinThread::~CWinThread() closes the original handle.
04467 #     if !defined (ACE_HAS_WINCE)
04468       (void) ::DuplicateHandle (::GetCurrentProcess (),
04469                                 cwin_thread->m_hThread,
04470                                 ::GetCurrentProcess (),
04471                                 thr_handle,
04472                                 0,
04473                                 TRUE,
04474                                 DUPLICATE_SAME_ACCESS);
04475 #     endif /* ! ACE_HAS_WINCE */
04476       *thr_id = cwin_thread->m_nThreadID;
04477 
04478       if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
04479         cwin_thread->ResumeThread ();
04480       // cwin_thread will be deleted in AfxThreadExit()
04481       // Warning: If AfxThreadExit() is called from within the
04482       // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
04483     }
04484   else
04485 #   endif /* ACE_HAS_MFC */
04486     {
04487       int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
04488 
04489       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
04490         // If we need to set the priority, then we need to start the
04491         // thread in a suspended mode.
04492         ACE_SET_BITS (flags, THR_SUSPENDED);
04493 
04494       *thr_handle = (void *) ACE_BEGINTHREADEX (0,
04495                                                 static_cast <u_int> (stacksize),
04496                                                 thread_args->entry_point (),
04497                                                 thread_args,
04498                                                 flags,
04499                                                 thr_id);
04500 
04501       if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
04502         {
04503           // Set the priority of the new thread and then let it
04504           // continue, but only if the user didn't start it suspended
04505           // in the first place!
04506           ACE_OS::thr_setprio (*thr_handle, priority);
04507 
04508           if (start_suspended == 0)
04509             ACE_OS::thr_continue (*thr_handle);
04510         }
04511     }
04512 #   if 0
04513   *thr_handle = ::CreateThread
04514     (0,
04515      stacksize,
04516      LPTHREAD_START_ROUTINE (thread_args->entry_point ()),
04517      thread_args,
04518      flags,
04519      thr_id);
04520 #   endif /* 0 */
04521 
04522   // Close down the handle if no one wants to use it.
04523   if (thr_handle == &tmp_handle && tmp_handle != 0)
04524     ::CloseHandle (tmp_handle);
04525 
04526   if (*thr_handle != 0)
04527     {
04528       auto_thread_args.release ();
04529       return 0;
04530     }
04531   else
04532     ACE_FAIL_RETURN (-1);
04533   /* NOTREACHED */
04534 
04535 # elif defined (ACE_VXWORKS)
04536   // The hard-coded values below are what ::sp () would use.  (::sp ()
04537   // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
04538   // 20,000.)  stacksize should be an even integer.  If a stack is not
04539   // specified, ::taskSpawn () is used so that we can set the
04540   // priority, flags, and stacksize.  If a stack is specified,
04541   // ::taskInit ()/::taskActivate() are used.
04542 
04543   // If called with thr_create() defaults, use same default values as ::sp ():
04544   if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
04545   // Assumes that there is a floating point coprocessor.  As noted
04546   // above, ::sp () hardcodes this, so we should be safe with it.
04547   if (flags == 0) flags = VX_FP_TASK;
04548   if (stacksize == 0) stacksize = 20000;
04549 
04550   const u_int thr_id_provided =
04551     thr_id  &&  *thr_id  &&  (*thr_id)[0] != ACE_THR_ID_ALLOCATED;
04552 
04553   ACE_hthread_t tid;
04554 #   if 0 /* Don't support setting of stack, because it doesn't seem to work. */
04555   if (stack == 0)
04556     {
04557 #   else
04558       ACE_UNUSED_ARG (stack);
04559 #   endif /* 0 */
04560       // The call below to ::taskSpawn () causes VxWorks to assign a
04561       // unique task name of the form: "t" + an integer, because the
04562       // first argument is 0.
04563       tid = ::taskSpawn (thr_id_provided  ?  *thr_id  :  0,
04564                          priority,
04565                          (int) flags,
04566                          (int) stacksize,
04567                          thread_args->entry_point (),
04568                          (int) thread_args,
04569                          0, 0, 0, 0, 0, 0, 0, 0, 0);
04570 #   if 0 /* Don't support setting of stack, because it doesn't seem to work. */
04571     }
04572   else
04573     {
04574       // If a task name (thr_id) was not supplied, then the task will
04575       // not have a unique name.  That's VxWorks' behavior.
04576 
04577       // Carve out a TCB at the beginning of the stack space.  The TCB
04578       // occupies 400 bytes with VxWorks 5.3.1/I386.
04579       WIND_TCB *tcb = (WIND_TCB *) stack;
04580 
04581       // The TID is defined to be the address of the TCB.
04582       int status = ::taskInit (tcb,
04583                                thr_id_provided  ?  *thr_id  :  0,
04584                                priority,
04585                                (int) flags,
04586                                (char *) stack + sizeof (WIND_TCB),
04587                                (int) (stacksize - sizeof (WIND_TCB)),
04588                                thread_args->entry_point (),
04589                                (int) thread_args,
04590                                0, 0, 0, 0, 0, 0, 0, 0, 0);
04591 
04592       if (status == OK)
04593         {
04594           // The task was successfully initialized, now activate it.
04595           status = ::taskActivate ((ACE_hthread_t) tcb);
04596         }
04597 
04598       tid = status == OK  ?  (ACE_hthread_t) tcb  :  ERROR;
04599     }
04600 #   endif /* 0 */
04601 
04602   if (tid == ERROR)
04603     return -1;
04604   else
04605     {
04606       if (! thr_id_provided && thr_id)
04607         {
04608           if (*thr_id && (*thr_id)[0] == ACE_THR_ID_ALLOCATED)
04609             // *thr_id was allocated by the Thread_Manager.  ::taskTcb
04610             // (int tid) returns the address of the WIND_TCB (task
04611             // control block).  According to the ::taskSpawn()
04612             // documentation, the name of the new task is stored at
04613             // pStackBase, but is that of the current task?  If so, it
04614             // might be a bit quicker than this extraction of the tcb
04615             // . . .
04616             ACE_OS::strsncpy (*thr_id + 1, ::taskName (tid), 10);
04617           else
04618             // *thr_id was not allocated by the Thread_Manager.
04619             // Pass back the task name in the location pointed to
04620             // by thr_id.
04621             *thr_id = ::taskName (tid);
04622         }
04623       // else if the thr_id was provided, there's no need to overwrite
04624       // it with the same value (string).  If thr_id is 0, then we can't
04625       // pass the task name back.
04626 
04627       if (thr_handle)
04628         *thr_handle = tid;
04629 
04630       auto_thread_args.release ();
04631       return 0;
04632     }
04633 
04634 # endif /* ACE_HAS_STHREADS */
04635 #else
04636   ACE_UNUSED_ARG (func);
04637   ACE_UNUSED_ARG (args);
04638   ACE_UNUSED_ARG (flags);
04639   ACE_UNUSED_ARG (thr_id);
04640   ACE_UNUSED_ARG (thr_handle);
04641   ACE_UNUSED_ARG (priority);
04642   ACE_UNUSED_ARG (stack);
04643   ACE_UNUSED_ARG (stacksize);
04644   ACE_NOTSUP_RETURN (-1);
04645 #endif /* ACE_HAS_THREADS */
04646 }
04647 
04648 void
04649 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
04650 {
04651   ACE_OS_TRACE ("ACE_OS::thr_exit");
04652 #if defined (ACE_HAS_THREADS)
04653 # if defined (ACE_HAS_PTHREADS)
04654     ::pthread_exit (status);
04655 # elif defined (ACE_HAS_STHREADS)
04656     ::thr_exit (status);
04657 # elif defined (ACE_HAS_WTHREADS)
04658     // Can't call it here because on NT, the thread is exited
04659     // directly by ACE_Thread_Adapter::invoke ().
04660     //   ACE_TSS_Cleanup::instance ()->thread_exit (status);
04661 
04662 #   if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
04663     int using_afx = -1;
04664     // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
04665     // But without #including ace/Thread_Manager.h, we don't know that.
04666     ACE_OS_Thread_Descriptor *td =
04667       ACE_Base_Thread_Adapter::thr_desc_log_msg ();
04668     if (td)
04669       using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
04670 #   endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
04671 
04672     // Call TSS destructors.
04673     ACE_OS::cleanup_tss (0 /* not main thread */);
04674 
04675     // Exit the thread.
04676     // Allow CWinThread-destructor to be invoked from AfxEndThread.
04677     // _endthreadex will be called from AfxEndThread so don't exit the
04678     // thread now if we are running an MFC thread.
04679 #   if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
04680     if (using_afx != -1)
04681       {
04682         if (using_afx)
04683           ::AfxEndThread (status);
04684         else
04685           ACE_ENDTHREADEX (status);
04686       }
04687     else
04688       {
04689         // Not spawned by ACE_Thread_Manager, use the old buggy
04690         // version.  You should seriously consider using
04691         // ACE_Thread_Manager to spawn threads.  The following code is
04692         // know to cause some problem.
04693         CWinThread *pThread = ::AfxGetThread ();
04694         if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
04695           ACE_ENDTHREADEX (status);
04696         else
04697           ::AfxEndThread (status);
04698       }
04699 #   else
04700     ACE_ENDTHREADEX (status);
04701 #   endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
04702 
04703 # elif defined (ACE_VXWORKS)
04704     ACE_hthread_t tid;
04705     ACE_OS::thr_self (tid);
04706     *((int *) status) = ::taskDelete (tid);
04707 # endif /* ACE_HAS_PTHREADS */
04708 #else
04709   ACE_UNUSED_ARG (status);
04710 #endif /* ACE_HAS_THREADS */
04711 }
04712 
04713 #if defined (ACE_VXWORKS) && !defined (ACE_HAS_PTHREADS)
04714 // Leave this in the global scope to allow
04715 // users to adjust the delay value.
04716 int ACE_THR_JOIN_DELAY = 5;
04717 
04718 int
04719 ACE_OS::thr_join (ACE_hthread_t thr_handle,
04720                   ACE_THR_FUNC_RETURN *status)
04721 {
04722   // We can't get the status of the thread
04723   if (status != 0)
04724     {
04725       *status = 0;
04726     }
04727 
04728   // This method can not support joining all threads
04729   if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
04730     {
04731       ACE_NOTSUP_RETURN (-1);
04732     }
04733 
04734   int retval = ESRCH;
04735   ACE_hthread_t current;
04736   ACE_OS::thr_self (current);
04737 
04738   // Make sure we are not joining ourself
04739   if (ACE_OS::thr_cmp (thr_handle, current))
04740     {
04741       retval = EDEADLK;
04742     }
04743   else
04744     {
04745       // Whether the task exists or not
04746       // we will return a successful value
04747       retval = 0;
04748 
04749       // Verify that the task id still exists
04750       while (taskIdVerify (thr_handle) == OK)
04751         {
04752           // Wait a bit to see if the task is still active.
04753           ACE_OS::sleep (ACE_THR_JOIN_DELAY);
04754         }
04755     }
04756 
04757   // Adapt the return value into errno and return value.
04758   // The ACE_ADAPT_RETVAL macro doesn't exactly do what
04759   // we need to do here, so we do it manually.
04760   if (retval != 0)
04761     {
04762       errno = retval;
04763       retval = -1;
04764     }
04765 
04766   return retval;
04767 }
04768 
04769 int
04770 ACE_OS::thr_join (ACE_thread_t waiter_id,
04771                   ACE_thread_t *thr_id,
04772                   ACE_THR_FUNC_RETURN *status)
04773 {
04774   thr_id = 0;
04775   return ACE_OS::thr_join (taskNameToId (waiter_id), status);
04776 }
04777 #endif /* ACE_VXWORKS */
04778 
04779 int
04780 ACE_OS::thr_key_detach (ACE_thread_key_t key, void *)
04781 {
04782 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
04783   TSS_Cleanup_Instance cleanup;
04784   if (cleanup.valid ())
04785     {
04786       return cleanup->thread_detach_key (key);
04787     }
04788   else
04789     {
04790       return -1;
04791     }
04792 #else
04793   ACE_UNUSED_ARG (key);
04794   ACE_NOTSUP_RETURN (-1);
04795 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
04796 }
04797 
04798 int
04799 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id,
04800                           size_t cpu_set_size,
04801                           cpu_set_t * cpu_mask)
04802 {
04803 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
04804   // Handle of the thread, which is NPTL thread-id, normally a big number
04805   if (::pthread_getaffinity_np (thr_id,
04806                                 cpu_set_size,
04807                                 cpu_mask) != 0)
04808     {
04809       return -1;
04810     }
04811   return 0;
04812 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
04813   // The process-id is expected as <thr_id>, which can be a thread-id of
04814   // linux-thread, thus making binding to cpu of that particular thread only.
04815   // If you are using this flag for NPTL-threads, however, please pass as a
04816   // thr_id process id obtained by ACE_OS::getpid ()
04817   ACE_UNUSED_ARG (cpu_set_size);
04818   if (::sched_getaffinity(thr_id,
04819                           cpu_mask) == -1)
04820     {
04821       return -1;
04822     }
04823   return 0;
04824 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
04825   // The process-id is expected as <thr_id>, which can be a thread-id of
04826   // linux-thread, thus making binding to cpu of that particular thread only.
04827   // If you are using this flag for NPTL-threads, however, please pass as a
04828   // thr_id process id obtained by ACE_OS::getpid ()
04829   if (::sched_getaffinity(thr_id,
04830                           cpu_set_size,
04831                           cpu_mask) == -1)
04832     {
04833       return -1;
04834     }
04835   return 0;
04836 #else
04837   ACE_UNUSED_ARG (thr_id);
04838   ACE_UNUSED_ARG (cpu_set_size);
04839   ACE_UNUSED_ARG (cpu_mask);
04840   ACE_NOTSUP_RETURN (-1);
04841 #endif
04842 }
04843 
04844 int
04845 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id,
04846                           size_t cpu_set_size,
04847                           const cpu_set_t * cpu_mask)
04848 {
04849 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
04850   if (::pthread_setaffinity_np (thr_id,
04851                                 cpu_set_size,
04852                                 cpu_mask) != 0)
04853     {
04854       return -1;
04855     }
04856   return 0;
04857 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
04858   // The process-id is expected as <thr_id>, which can be a thread-id of
04859   // linux-thread, thus making binding to cpu of that particular thread only.
04860   // If you are using this flag for NPTL-threads, however, please pass as a
04861   // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
04862   //
04863   ACE_UNUSED_ARG (cpu_set_size);
04864   if (::sched_setaffinity (thr_id,
04865                            cpu_mask) == -1)
04866     {
04867       return -1;
04868     }
04869   return 0;
04870 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
04871   // The process-id is expected as <thr_id>, which can be a thread-id of
04872   // linux-thread, thus making binding to cpu of that particular thread only.
04873   // If you are using this flag for NPTL-threads, however, please pass as a
04874   // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
04875   //
04876   if (::sched_setaffinity (thr_id,
04877                            cpu_set_size,
04878                            cpu_mask) == -1)
04879     {
04880       return -1;
04881     }
04882   return 0;
04883 #else
04884   ACE_UNUSED_ARG (thr_id);
04885   ACE_UNUSED_ARG (cpu_set_size);
04886   ACE_UNUSED_ARG (cpu_mask);
04887   ACE_NOTSUP_RETURN (-1);
04888 #endif
04889 }
04890 
04891 int
04892 ACE_OS::thr_key_used (ACE_thread_key_t key)
04893 {
04894 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
04895   TSS_Cleanup_Instance cleanup;
04896   if (cleanup.valid ())
04897     {
04898       cleanup->thread_use_key (key);
04899       return 0;
04900     }
04901   return -1;
04902 #else
04903   ACE_UNUSED_ARG (key);
04904   ACE_NOTSUP_RETURN (-1);
04905 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
04906 }
04907 
04908 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
04909 int
04910 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t *key,
04911 # if defined (ACE_HAS_THR_C_DEST)
04912                        ACE_THR_C_DEST dest
04913 # else
04914                        ACE_THR_DEST dest
04915 # endif /* ACE_HAS_THR_C_DEST */
04916                        )
04917 {
04918   // can't trace here. Trace uses TSS
04919   // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
04920 # if defined (ACE_HAS_THREADS)
04921 #   if defined (ACE_HAS_PTHREADS)
04922 
04923 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
04924 #       if defined (ACE_HAS_STDARG_THR_DEST)
04925     ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1);
04926 #       else  /* ! ACE_HAS_STDARG_THR_DEST */
04927     ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1);
04928 #       endif /* ! ACE_HAS_STDARG_THR_DEST */
04929 #     elif defined (ACE_HAS_PTHREADS_DRAFT6)
04930     ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1);
04931 #     else
04932     int result;
04933     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
04934                                          result),
04935                        int, -1);
04936 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
04937 #   elif defined (ACE_HAS_STHREADS)
04938     int result;
04939     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
04940                                          result),
04941                        int, -1);
04942 #   elif defined (ACE_HAS_WTHREADS)
04943     ACE_UNUSED_ARG (dest);
04944     *key = ::TlsAlloc ();
04945 
04946     if (*key == ACE_SYSCALL_FAILED)
04947       ACE_FAIL_RETURN (-1);
04948     return 0;
04949 #   endif /* ACE_HAS_STHREADS */
04950 # else
04951   ACE_UNUSED_ARG (key);
04952   ACE_UNUSED_ARG (dest);
04953   ACE_NOTSUP_RETURN (-1);
04954 # endif /* ACE_HAS_THREADS */
04955 }
04956 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
04957 
04958 int
04959 ACE_OS::thr_keycreate (ACE_thread_key_t *key,
04960 # if defined (ACE_HAS_THR_C_DEST)
04961                        ACE_THR_C_DEST dest,
04962 # else
04963                        ACE_THR_DEST dest,
04964 # endif /* ACE_HAS_THR_C_DEST */
04965                        void *)
04966 {
04967   // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
04968 #if defined (ACE_HAS_THREADS)
04969 #   if defined (ACE_HAS_TSS_EMULATION)
04970     if (ACE_TSS_Emulation::next_key (*key) == 0)
04971       {
04972         ACE_TSS_Emulation::tss_destructor (*key, dest);
04973 
04974         // Extract out the thread-specific table instance and stash away
04975         // the key and destructor so that we can free it up later on...
04976         TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
04977         if (cleanup.valid ())
04978           {
04979             return cleanup->insert (*key, dest);
04980           }
04981         else
04982           {
04983             return -1;
04984           }
04985       }
04986     else
04987       return -1;
04988 #   elif defined (ACE_HAS_WTHREADS)
04989     if (ACE_OS::thr_keycreate_native (key, dest) == 0)
04990       {
04991         // Extract out the thread-specific table instance and stash away
04992         // the key and destructor so that we can free it up later on...
04993         TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
04994         if (cleanup.valid ())
04995           {
04996             return cleanup->insert (*key, dest);
04997           }
04998         else
04999           {
05000             return -1;
05001           }
05002       }
05003     else
05004       return -1;
05005       /* NOTREACHED */
05006 #   elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
05007     return  ACE_OS::thr_keycreate_native (key, dest);
05008 #   else
05009     ACE_UNUSED_ARG (key);
05010     ACE_UNUSED_ARG (dest);
05011     ACE_NOTSUP_RETURN (-1);
05012 #   endif /* ACE_HAS_TSS_EMULATION */
05013 # else /* ACE_HAS_THREADS */
05014   ACE_UNUSED_ARG (key);
05015   ACE_UNUSED_ARG (dest);
05016   ACE_NOTSUP_RETURN (-1);
05017 # endif /* ACE_HAS_THREADS */
05018 }
05019 
05020 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
05021 int
05022 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key)
05023 {
05024   ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
05025 # if defined (ACE_HAS_THREADS)
05026 #   if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
05027     ACE_UNUSED_ARG (key);
05028     ACE_NOTSUP_RETURN (-1);
05029 #   elif defined (ACE_HAS_PTHREADS)
05030     return ::pthread_key_delete (key);
05031 #   elif defined (ACE_HAS_THR_KEYDELETE)
05032     return ::thr_keydelete (key);
05033 #   elif defined (ACE_HAS_STHREADS)
05034     ACE_UNUSED_ARG (key);
05035     ACE_NOTSUP_RETURN (-1);
05036 #   elif defined (ACE_HAS_WTHREADS)
05037     ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
05038 #   else
05039     ACE_UNUSED_ARG (key);
05040     ACE_NOTSUP_RETURN (-1);
05041 #   endif /* ACE_HAS_PTHREADS */
05042 # else
05043   ACE_UNUSED_ARG (key);
05044   ACE_NOTSUP_RETURN (-1);
05045 # endif /* ACE_HAS_THREADS */
05046 }
05047 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
05048 
05049 int
05050 ACE_OS::thr_keyfree (ACE_thread_key_t key)
05051 {
05052   ACE_OS_TRACE ("ACE_OS::thr_keyfree");
05053 # if defined (ACE_HAS_THREADS)
05054 #   if defined (ACE_HAS_TSS_EMULATION)
05055     // Release the key in the TSS_Emulation administration
05056     ACE_TSS_Emulation::release_key (key);
05057     TSS_Cleanup_Instance cleanup;
05058     if (cleanup.valid ())
05059       {
05060         return cleanup->free_key (key);
05061       }
05062     return -1;
05063 #   elif defined (ACE_HAS_WTHREADS)
05064     // Extract out the thread-specific table instance and free up
05065     // the key and destructor.
05066     TSS_Cleanup_Instance cleanup;
05067     if (cleanup.valid ())
05068       {
05069         return cleanup->free_key (key);
05070       }
05071     return -1;
05072 #   elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
05073     return ACE_OS::thr_keyfree_native (key);
05074 #   else
05075     ACE_UNUSED_ARG (key);
05076     ACE_NOTSUP_RETURN (-1);
05077 #   endif /* ACE_HAS_TSS_EMULATION */
05078 # else /* ACE_HAS_THREADS */
05079   ACE_UNUSED_ARG (key);
05080   ACE_NOTSUP_RETURN (-1);
05081   return 0;
05082 # endif /* ACE_HAS_THREADS */
05083 }
05084 
05085 int
05086 ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
05087 {
05088   // Set the thread priority on the current thread.
05089   ACE_hthread_t my_thread_id;
05090   ACE_OS::thr_self (my_thread_id);
05091 
05092   int status = ACE_OS::thr_setprio (my_thread_id, prio);
05093 
05094 #if defined (ACE_NEEDS_LWP_PRIO_SET)
05095   // If the thread is in the RT class, then set the priority on its
05096   // LWP.  (Instead of doing this if the thread is in the RT class, it
05097   // should be done for all bound threads.  But, there doesn't appear
05098   // to be an easy way to determine if the thread is bound.)
05099 
05100   if (status == 0)
05101     {
05102       // Find what scheduling class the thread's LWP is in.
05103       ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0);
05104       if (ACE_OS::lwp_getparams (sched_params) == -1)
05105         {
05106           return -1;
05107         }
05108       else if (sched_params.policy () == ACE_SCHED_FIFO  ||
05109                sched_params.policy () == ACE_SCHED_RR)
05110         {
05111           // This thread's LWP is in the RT class, so we need to set
05112           // its priority.
05113           sched_params.priority (prio);
05114           return ACE_OS::lwp_setparams (sched_params);
05115         }
05116       // else this is not an RT thread.  Nothing more needs to be
05117       // done.
05118     }
05119 #endif /* ACE_NEEDS_LWP_PRIO_SET */
05120 
05121   return status;
05122 }
05123 
05124 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
05125 int
05126 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key, void *data)
05127 {
05128   // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
05129 #   if defined (ACE_HAS_THREADS)
05130 #     if defined (ACE_HAS_PTHREADS)
05131 #       if defined (ACE_HAS_FSU_PTHREADS)
05132       // Call pthread_init() here to initialize threads package.  FSU
05133       // threads need an initialization before the first thread constructor.
05134       // This seems to be the one; however, a segmentation fault may
05135       // indicate that another pthread_init() is necessary, perhaps in
05136       // Synch.cpp or Synch_T.cpp.  FSU threads will not reinit if called
05137       // more than once, so another call to pthread_init will not adversely
05138       // affect existing threads.
05139       pthread_init ();
05140 #       endif /*  ACE_HAS_FSU_PTHREADS */
05141 #      if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
05142     ACE_OSCALL_RETURN (::pthread_setspecific (key, data), int, -1);
05143 #       else
05144     int result;
05145     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key, data),
05146                                          result),
05147                        int, -1);
05148 #       endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */
05149 
05150 #     elif defined (ACE_HAS_STHREADS)
05151       int result;
05152       ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), result), int, -1);
05153 #     elif defined (ACE_HAS_WTHREADS)
05154       ::TlsSetValue (key, data);
05155       return 0;
05156 #     else /* ACE_HAS_STHREADS */
05157       ACE_UNUSED_ARG (key);
05158       ACE_UNUSED_ARG (data);
05159       ACE_NOTSUP_RETURN (-1);
05160 #     endif /* ACE_HAS_STHREADS */
05161 #   else
05162     ACE_UNUSED_ARG (key);
05163     ACE_UNUSED_ARG (data);
05164     ACE_NOTSUP_RETURN (-1);
05165 #   endif /* ACE_HAS_THREADS */
05166 }
05167 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
05168 
05169 int
05170 ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
05171 {
05172   // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
05173 #if defined (ACE_HAS_THREADS)
05174 #   if defined (ACE_HAS_TSS_EMULATION)
05175     if (ACE_TSS_Emulation::is_key (key) == 0)
05176       {
05177         errno = EINVAL;
05178         data = 0;
05179         return -1;
05180       }
05181     else
05182       {
05183         ACE_TSS_Emulation::ts_object (key) = data;
05184         TSS_Cleanup_Instance cleanup;
05185         if (cleanup.valid ())
05186           {
05187             cleanup->thread_use_key (key);
05188             // for TSS_Cleanup purposes treat stetting data to zero
05189             // like detaching.  This is a consequence of POSIX allowing
05190             // deletion of a "used" key.
05191             if (data == 0)
05192               {
05193                 cleanup->thread_detach_key (key);
05194               }
05195             return 0;
05196           }
05197         else
05198           {
05199             return -1;
05200           }
05201       }
05202 #   elif defined (ACE_HAS_WTHREADS)
05203     if (ACE_OS::thr_setspecific_native (key, data) == 0)
05204       {
05205         TSS_Cleanup_Instance cleanup;
05206         if (cleanup.valid ())
05207           {
05208             cleanup->thread_use_key (key);
05209             // for TSS_Cleanup purposes treat stetting data to zero
05210             // like detaching.  This is a consequence of POSIX allowing
05211             // deletion of a "used" key.
05212             if (data == 0)
05213               {
05214                 cleanup->thread_detach_key (key);
05215               }
05216             return 0;
05217           }
05218         return -1;
05219       }
05220     return -1;
05221 #   elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
05222       return ACE_OS::thr_setspecific_native (key, data);
05223 #   else /* ACE_HAS_TSS_EMULATION */
05224       ACE_UNUSED_ARG (key);
05225       ACE_UNUSED_ARG (data);
05226       ACE_NOTSUP_RETURN (-1);
05227 #   endif /* ACE_HAS_TSS_EMULATION */
05228 # else /* ACE_HAS_THREADS */
05229   ACE_UNUSED_ARG (key);
05230   ACE_UNUSED_ARG (data);
05231   ACE_NOTSUP_RETURN (-1);
05232 # endif /* ACE_HAS_THREADS */
05233 }
05234 
05235 void
05236 ACE_OS::unique_name (const void *object,
05237                      char *name,
05238                      size_t length)
05239 {
05240   // The process ID will provide uniqueness between processes on the
05241   // same machine. The "this" pointer of the <object> will provide
05242   // uniqueness between other "live" objects in the same process. The
05243   // uniqueness of this name is therefore only valid for the life of
05244   // <object>.
05245   char temp_name[ACE_UNIQUE_NAME_LEN];
05246   ACE_OS::sprintf (temp_name,
05247                    "%p%d",
05248                    object,
05249                    static_cast <int> (ACE_OS::getpid ()));
05250   ACE_OS::strsncpy (name,
05251                     temp_name,
05252                     length);
05253 }
05254 
05255 #if defined (ACE_USES_WCHAR)
05256 void
05257 ACE_OS::unique_name (const void *object,
05258                      wchar_t *name,
05259                      size_t length)
05260 {
05261   // The process ID will provide uniqueness between processes on the
05262   // same machine. The "this" pointer of the <object> will provide
05263   // uniqueness between other "live" objects in the same process. The
05264   // uniqueness of this name is therefore only valid for the life of
05265   // <object>.
05266   wchar_t temp_name[ACE_UNIQUE_NAME_LEN];
05267   ACE_OS::sprintf (temp_name,
05268                    ACE_LIB_TEXT ("%p%d"),
05269                    object,
05270                    static_cast <int> (ACE_OS::getpid ()));
05271   ACE_OS::strsncpy (name,
05272                     temp_name,
05273                     length);
05274 }
05275 #endif
05276 
05277 ACE_END_VERSIONED_NAMESPACE_DECL
05278 
05279 #if defined (ACE_VXWORKS) && !defined (__RTP__)
05280 # include /**/ <usrLib.h>   /* for ::sp() */
05281 # include /**/ <sysLib.h>   /* for ::sysClkRateGet() */
05282 
05283 // This global function can be used from the VxWorks shell to pass
05284 // arguments to a C main () function.
05285 //
05286 // usage: -> spa main, "arg1", "arg2"
05287 //
05288 // All arguments must be quoted, even numbers.
05289 int
05290 spa (FUNCPTR entry, ...)
05291 {
05292   static const unsigned int ACE_MAX_ARGS = 10;
05293   static char *argv[ACE_MAX_ARGS];
05294   va_list pvar;
05295   unsigned int argc;
05296 
05297   // Hardcode a program name because the real one isn't available
05298   // through the VxWorks shell.
05299   argv[0] = "ace_main";
05300 
05301   // Peel off arguments to spa () and put into argv.  va_arg () isn't
05302   // necessarily supposed to return 0 when done, though since the
05303   // VxWorks shell uses a fixed number (10) of arguments, it might 0
05304   // the unused ones.  This function could be used to increase that
05305   // limit, but then it couldn't depend on the trailing 0.  So, the
05306   // number of arguments would have to be passed.
05307   va_start (pvar, entry);
05308 
05309   for (argc = 1; argc <= ACE_MAX_ARGS; ++argc)
05310     {
05311       argv[argc] = va_arg (pvar, char *);
05312 
05313       if (argv[argc] == 0)
05314         break;
05315     }
05316 
05317   if (argc > ACE_MAX_ARGS  &&  argv[argc-1] != 0)
05318     {
05319       // try to read another arg, and warn user if the limit was exceeded
05320       if (va_arg (pvar, char *) != 0)
05321         ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %d\n",
05322                          ACE_MAX_ARGS);
05323     }
05324   else
05325     {
05326       // fill unused argv slots with 0 to get rid of leftovers
05327       // from previous invocations
05328       for (unsigned int i = argc; i <= ACE_MAX_ARGS; ++i)
05329         argv[i] = 0;
05330     }
05331 
05332   // The hard-coded options are what ::sp () uses, except for the
05333   // larger stack size (instead of ::sp ()'s 20000).
05334   const int ret = ::taskSpawn (argv[0],    // task name
05335                                100,        // task priority
05336                                VX_FP_TASK, // task options
05337                                ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
05338                                entry,      // entry point
05339                                argc,       // first argument to main ()
05340                                (int) argv, // second argument to main ()
05341                                0, 0, 0, 0, 0, 0, 0, 0);
05342   va_end (pvar);
05343 
05344   // ::taskSpawn () returns the taskID on success: return 0 instead if
05345   // successful
05346   return ret > 0 ? 0 : ret;
05347 }
05348 
05349 // A helper function for the extended spa functions
05350 static void
05351 add_to_argv (int& argc, char** argv, int max_args, char* string)
05352 {
05353   char indouble   = 0;
05354   size_t previous = 0;
05355   size_t length   = ACE_OS::strlen (string);
05356 
05357   // We use <= to make sure that we get the last argument
05358   for (size_t i = 0; i <= length; i++)
05359     {
05360       // Is it a double quote that hasn't been escaped?
05361       if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
05362         {
05363           indouble ^= 1;
05364           if (indouble)
05365             {
05366               // We have just entered a double quoted string, so
05367               // save the starting position of the contents.
05368               previous = i + 1;
05369             }
05370           else
05371             {
05372               // We have just left a double quoted string, so
05373               // zero out the ending double quote.
05374               string[i] = '\0';
05375             }
05376         }
05377       else if (string[i] == '\\')  // Escape the next character
05378         {
05379           // The next character is automatically
05380           // skipped because of the strcpy
05381           ACE_OS::strcpy (string + i, string + i + 1);
05382           length--;
05383         }
05384       else if (!indouble &&
05385                (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
05386         {
05387           string[i] = '\0';
05388           if (argc < max_args)
05389             {
05390               argv[argc] = string + previous;
05391               argc++;
05392             }
05393           else
05394             {
05395               ACE_OS::fprintf (stderr, "spae(): number of arguments "
05396                                        "limited to %d\n", max_args);
05397             }
05398 
05399           // Skip over whitespace in between arguments
05400           for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
05401             {
05402             }
05403 
05404           // Save the starting point for the next time around
05405           previous = i;
05406 
05407           // Make sure we don't skip over a character due
05408           // to the above loop to skip over whitespace
05409           i--;
05410         }
05411     }
05412 }
05413 
05414 // This global function can be used from the VxWorks shell to pass
05415 // arguments to a C main () function.
05416 //
05417 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
05418 //
05419 // All arguments must be within double quotes, even numbers.
05420 int
05421 spae (FUNCPTR entry, ...)
05422 {
05423   static const int WINDSH_ARGS = 10;
05424   static const int ACE_MAX_ARGS    = 128;
05425   static char* argv[ACE_MAX_ARGS]  = { "ace_main", 0 };
05426   va_list pvar;
05427   int argc = 1;
05428 
05429   // Peel off arguments to spa () and put into argv.  va_arg () isn't
05430   // necessarily supposed to return 0 when done, though since the
05431   // VxWorks shell uses a fixed number (10) of arguments, it might 0
05432   // the unused ones.
05433   va_start (pvar, entry);
05434 
05435   int i = 0;
05436   for (char* str = va_arg (pvar, char*);
05437        str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
05438     {
05439       add_to_argv(argc, argv, ACE_MAX_ARGS, str);
05440     }
05441 
05442   // fill unused argv slots with 0 to get rid of leftovers
05443   // from previous invocations
05444   for (i = argc; i < ACE_MAX_ARGS; ++i)
05445     argv[i] = 0;
05446 
05447   // The hard-coded options are what ::sp () uses, except for the
05448   // larger stack size (instead of ::sp ()'s 20000).
05449   const int ret = ::taskSpawn (argv[0],    // task name
05450                                100,        // task priority
05451                                VX_FP_TASK, // task options
05452                                ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
05453                                entry,      // entry point
05454                                argc,       // first argument to main ()
05455                                (int) argv, // second argument to main ()
05456                                0, 0, 0, 0, 0, 0, 0, 0);
05457   va_end (pvar);
05458 
05459   // ::taskSpawn () returns the taskID on success: return 0 instead if
05460   // successful
05461   return ret > 0 ? 0 : ret;
05462 }
05463 
05464 // This global function can be used from the VxWorks shell to pass
05465 // arguments to a C main () function.  The function will be run
05466 // within the shells task.
05467 //
05468 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
05469 //
05470 // All arguments must be within double quotes, even numbers.
05471 // Unlike the spae function, this fuction executes the supplied
05472 // routine in the foreground, rather than spawning it in a separate
05473 // task.
05474 int
05475 spaef (FUNCPTR entry, ...)
05476 {
05477   static const int WINDSH_ARGS = 10;
05478   static const int ACE_MAX_ARGS    = 128;
05479   static char* argv[ACE_MAX_ARGS]  = { "ace_main", 0 };
05480   va_list pvar;
05481   int argc = 1;
05482 
05483   // Peel off arguments to spa () and put into argv.  va_arg () isn't
05484   // necessarily supposed to return 0 when done, though since the
05485   // VxWorks shell uses a fixed number (10) of arguments, it might 0
05486   // the unused ones.
05487   va_start (pvar, entry);
05488 
05489   int i = 0;
05490   for (char* str = va_arg (pvar, char*);
05491        str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
05492     {
05493       add_to_argv(argc, argv, ACE_MAX_ARGS, str);
05494     }
05495 
05496   // fill unused argv slots with 0 to get rid of leftovers
05497   // from previous invocations
05498   for (i = argc; i < ACE_MAX_ARGS; ++i)
05499     argv[i] = 0;
05500 
05501   int ret = entry (argc, argv);
05502 
05503   va_end (pvar);
05504 
05505   // Return the return value of the invoked ace_main routine.
05506   return ret;
05507 }
05508 
05509 // This global function can be used from the VxWorks shell to pass
05510 // arguments to and run a main () function (i.e. ace_main).
05511 //
05512 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
05513 //
05514 // All arguments must be within double quotes, even numbers.
05515 // This routine spawns the main () function in a separate task and waits till the
05516 // task has finished.
05517 static int _vx_call_rc = 0;
05518 
05519 static int
05520 _vx_call_entry(FUNCPTR entry, int argc, char* argv[])
05521 {
05522     _vx_call_rc = entry (argc, argv);
05523     return _vx_call_rc;
05524 }
05525 
05526 int
05527 vx_execae (FUNCPTR entry, char* arg, int prio, int opt, int stacksz, ...)
05528 {
05529   static const int ACE_MAX_ARGS    = 128;
05530   static char* argv[ACE_MAX_ARGS]  = { "ace_main", 0 };
05531   int argc = 1;
05532 
05533   // Peel off arguments to run_main () and put into argv.
05534 
05535   if (arg)
05536     add_to_argv(argc, argv, ACE_MAX_ARGS, arg);
05537 
05538   // fill unused argv slots with 0 to get rid of leftovers
05539   // from previous invocations
05540   for (int i = argc; i < ACE_MAX_ARGS; ++i)
05541     argv[i] = 0;
05542 
05543   // The hard-coded options are what ::sp () uses, except for the
05544   // larger stack size (instead of ::sp ()'s 20000).
05545   const int ret = ::taskSpawn (argv[0],    // task name
05546                                prio==0 ? 100 : prio,        // task priority
05547                                opt==0 ? VX_FP_TASK : opt, // task options
05548                                stacksz==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE : stacksz, // stack size
05549                                (FUNCPTR)_vx_call_entry, // entrypoint caller
05550                                (int)entry,              // entry point
05551                                argc,                    // first argument to main ()
05552                                (int) argv,              // second argument to main ()
05553                                0, 0, 0, 0, 0, 0, 0);
05554 
05555   while( ret > 0 && ::taskIdVerify (ret) != ERROR )
05556     ::taskDelay (3 * ::sysClkRateGet ());
05557 
05558   // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
05559   // successful
05560   return ret > 0 ? _vx_call_rc : 255;
05561 }
05562 #endif /* ACE_VXWORKS && !__RTP__ */
05563 
05564 #if defined (__DGUX) && defined (ACE_HAS_THREADS) && defined (_POSIX4A_DRAFT10_SOURCE)
05565 extern "C" int __d6_sigwait (sigset_t *set);
05566 
05567 extern "C" int __d10_sigwait (const sigset_t *set, int *sig)
05568 {
05569   sigset_t unconst_set = *set;
05570   int caught_sig = __d6_sigwait (&unconst_set);
05571 
05572   if (caught == -1)
05573     return -1;
05574 
05575   *sig = caught_sig;
05576   return 0;
05577 }
05578 #endif /* __DGUX && PTHREADS && _POSIX4A_DRAFT10_SOURCE */

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