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

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