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

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