Changes to attempt to silence bcc64x
[ACE_TAO.git] / ACE / ace / OS_NS_Thread.cpp
blob1dff5ccf076a127d2b391358378d4f731ca7ec37
1 #include "ace/OS_NS_Thread.h"
3 #if !defined (ACE_HAS_INLINED_OSCALLS)
4 # include "ace/OS_NS_Thread.inl"
5 #endif /* ACE_HAS_INLINED_OSCALLS */
7 #include "ace/OS_NS_stdio.h"
8 #include "ace/Sched_Params.h"
9 #include "ace/OS_Memory.h"
10 #include "ace/OS_Thread_Adapter.h"
11 #include "ace/Min_Max.h"
12 #include "ace/Object_Manager_Base.h"
13 #include "ace/OS_NS_errno.h"
14 #include "ace/OS_NS_ctype.h"
15 #include "ace/Log_Category.h" // for ACE_ASSERT
16 #include "ace/Thread_Mutex.h"
17 #include "ace/Condition_Thread_Mutex.h"
18 #include "ace/Guard_T.h"
19 #ifdef ACE_HAS_GETTID
20 # include "ace/OS_NS_sys_resource.h" // syscall for gettid impl
21 #endif
22 #include <memory>
24 extern "C" void
25 ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args)
27 ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::mutex_lock_cleanup (args);
30 #if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
31 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
32 (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID)
33 #elif defined(ACE_HAS_WTHREADS)
34 // Green Hills compiler gets confused when __stdcall is embedded in
35 // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
36 // instead.
37 typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*);
38 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
39 ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
40 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
42 /*****************************************************************************/
44 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
46 void
47 ACE_Thread_ID::to_string (char *thr_string, size_t thr_string_len) const
49 #if defined (ACE_WIN32)
50 ACE_OS::snprintf (thr_string, thr_string_len, "%u",
51 static_cast <unsigned> (this->thread_id_));
52 #else
53 // Yes, this is an ugly C-style cast, but the correct C++ cast is
54 // different depending on whether the t_id is an integral type or a
55 // pointer type. FreeBSD uses a pointer type, but doesn't have a _np
56 // function to get an integral type like other OSes, so use the
57 // bigger hammer.
58 ACE_OS::snprintf (thr_string, thr_string_len, "%lu",
59 # ifdef ACE_THREAD_T_IS_A_STRUCT
60 *reinterpret_cast<const unsigned long *> (&
61 # else
62 (unsigned long) (
63 # endif // ACE_THREAD_T_IS_A_STRUCT
64 thread_handle_));
66 #endif /* ACE_WIN32 */
69 /*****************************************************************************/
71 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
73 #if defined (ACE_HAS_TSS_EMULATION)
74 u_int ACE_TSS_Emulation::total_keys_ = 0;
76 ACE_TSS_Keys* ACE_TSS_Emulation::tss_keys_used_ = 0;
78 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
79 ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]
80 = { 0 };
82 # if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) && defined (ACE_HAS_VXTHREADS)
84 # if (defined (_WRS_CONFIG_SMP) || defined (INCLUDE_AMP_CPU))
85 __thread void* ACE_TSS_Emulation::ace_tss_keys = 0;
86 # else /* ! VxWorks SMP */
87 void* ACE_TSS_Emulation::ace_tss_keys = 0;
88 # endif /* ! VxWorks SMP */
90 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
92 bool ACE_TSS_Emulation::key_created_ = false;
94 ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_;
96 /* static */
97 # if defined (ACE_HAS_THR_C_FUNC)
98 extern "C"
99 void
100 ACE_TSS_Emulation_cleanup (void *)
102 // Really this must be used for ACE_TSS_Emulation code to make the TSS
103 // cleanup
105 # else
106 void
107 ACE_TSS_Emulation_cleanup (void *)
109 // Really this must be used for ACE_TSS_Emulation code to make the TSS
110 // cleanup
112 # endif /* ACE_HAS_THR_C_FUNC */
114 void **
115 ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created)
117 // TSS Singleton implementation.
119 // Create the one native TSS key, if necessary.
120 if (!key_created_)
122 // Double-checked lock . . .
123 ACE_TSS_BASE_GUARD
125 if (!key_created_)
127 if (ACE_OS::thr_keycreate_native (&native_tss_key_,
128 &ACE_TSS_Emulation_cleanup) != 0)
130 ACE_ASSERT (0);
131 return 0; // Major problems, this should *never* happen!
133 key_created_ = true;
137 void **old_ts_storage = 0;
139 // Get the tss_storage from thread-OS specific storage.
140 if (ACE_OS::thr_getspecific_native (native_tss_key_,
141 (void **) &old_ts_storage) == -1)
143 ACE_ASSERT (false);
144 return 0; // This should not happen!
147 // Check to see if this is the first time in for this thread.
148 // This block can also be entered after a fork () in the child process.
149 if (old_ts_storage == 0)
151 if (ts_created)
152 *ts_created = 1u;
154 // Use the ts_storage passed as argument, if non-zero. It is
155 // possible that this has been implemented in the stack. At the
156 // moment, this is unknown. The cleanup must not do nothing.
157 // If ts_storage is zero, allocate (and eventually leak) the
158 // storage array.
159 if (ts_storage == 0)
161 #ifdef ACE_HAS_ALLOC_HOOKS
162 const size_t n = ACE_TSS_THREAD_KEYS_MAX * sizeof (void *);
163 ACE_Allocator *const alloc = ACE_Allocator::instance ();
164 ACE_ALLOCATOR_RETURN (ts_storage,
165 static_cast<void **> (alloc->malloc (n)), 0);
166 #else
167 ACE_NEW_RETURN (ts_storage,
168 void*[ACE_TSS_THREAD_KEYS_MAX],
170 #endif
172 // Zero the entire TSS array. Do it manually instead of
173 // using memset, for optimum speed. Though, memset may be
174 // faster :-)
175 void **tss_base_p = ts_storage;
177 for (u_int i = 0;
178 i < ACE_TSS_THREAD_KEYS_MAX;
179 ++i)
180 *tss_base_p++ = 0;
183 // Store the pointer in thread-specific storage. It gets
184 // deleted via the ACE_TSS_Emulation_cleanup function when the
185 // thread terminates.
186 if (ACE_OS::thr_setspecific_native (native_tss_key_,
187 (void *) ts_storage) != 0)
189 ACE_ASSERT (false);
190 return 0; // This should not happen!
193 else
194 if (ts_created)
195 ts_created = 0;
197 return ts_storage ? ts_storage : old_ts_storage;
199 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
201 u_int
202 ACE_TSS_Emulation::total_keys ()
204 ACE_OS_Recursive_Thread_Mutex_Guard (
205 *static_cast <ACE_recursive_thread_mutex_t *>
206 (ACE_OS_Object_Manager::preallocated_object[
207 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
209 return total_keys_;
213 ACE_TSS_Emulation::next_key (ACE_thread_key_t &key)
215 ACE_OS_Recursive_Thread_Mutex_Guard (
216 *static_cast <ACE_recursive_thread_mutex_t *>
217 (ACE_OS_Object_Manager::preallocated_object[
218 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
220 // Initialize the tss_keys_used_ pointer on first use.
221 if (tss_keys_used_ == 0)
223 ACE_NEW_RETURN (tss_keys_used_, ACE_TSS_Keys, -1);
226 if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX)
228 u_int counter = 0;
229 // Loop through all possible keys and check whether a key is free
230 for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++)
232 ACE_thread_key_t localkey = counter;
233 // If the key is not set as used, we can give out this key, if not
234 // we have to search further
235 if (tss_keys_used_->is_set(localkey) == 0)
237 tss_keys_used_->test_and_set(localkey);
238 key = localkey;
239 break;
243 ++total_keys_;
244 return 0;
246 else
248 key = ACE_OS::NULL_key;
249 return -1;
254 ACE_TSS_Emulation::release_key (ACE_thread_key_t key)
256 ACE_OS_Recursive_Thread_Mutex_Guard (
257 *static_cast <ACE_recursive_thread_mutex_t *>
258 (ACE_OS_Object_Manager::preallocated_object[
259 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
261 if (tss_keys_used_ != 0 &&
262 tss_keys_used_->test_and_clear (key) == 0)
264 --total_keys_;
265 return 0;
267 return 1;
271 ACE_TSS_Emulation::is_key (ACE_thread_key_t key)
273 ACE_OS_Recursive_Thread_Mutex_Guard (
274 *static_cast <ACE_recursive_thread_mutex_t *>
275 (ACE_OS_Object_Manager::preallocated_object[
276 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
278 if (tss_keys_used_ != 0 &&
279 tss_keys_used_->is_set (key) == 1)
281 return 1;
283 return 0;
286 void *
287 ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX])
289 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
290 // On VxWorks, in particular, don't check to see if the field
291 // is 0. It isn't always, specifically, when a program is run
292 // directly by the shell (without spawning a new task) after
293 // another program has been run.
295 u_int ts_created = 0;
296 tss_base (ts_storage, &ts_created);
297 if (ts_created)
299 # else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
300 tss_base () = ts_storage;
301 # endif
303 // Zero the entire TSS array. Do it manually instead of using
304 // memset, for optimum speed. Though, memset may be faster :-)
305 void **tss_base_p = tss_base ();
306 for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
308 *tss_base_p = 0;
311 return tss_base ();
312 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
314 else
316 return 0;
318 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
321 void
322 ACE_TSS_Emulation::tss_close ()
324 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
325 ACE_OS::thr_keyfree_native (native_tss_key_);
326 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
329 #endif /* ACE_HAS_TSS_EMULATION */
331 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
333 /*****************************************************************************/
335 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
337 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
338 // the single file of template instantiations.
340 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id)
341 : tid_(id)
343 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
346 ACE_TSS_Ref::ACE_TSS_Ref ()
348 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
351 // Check for equality.
352 bool
353 ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const
355 ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
357 #ifdef ACE_THREAD_T_IS_A_STRUCT
358 return 0 == ACE_OS::memcmp (&this->tid_, &info.tid_, sizeof tid_);
359 #else
360 return this->tid_ == info.tid_;
361 #endif
364 // Check for inequality.
365 bool
366 ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
368 ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
370 return !(*this == tss_ref);
373 // moved class ACE_TSS_Info declaration
374 // to OS.h so it can be visible to the
375 // single file of template instantiations
377 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
378 ACE_TSS_Info::Destructor dest)
379 : key_ (key),
380 destructor_ (dest),
381 thread_count_ (-1)
383 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
386 ACE_TSS_Info::ACE_TSS_Info ()
387 : key_ (ACE_OS::NULL_key),
388 destructor_ (0),
389 thread_count_ (-1)
391 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
394 // Check for equality.
395 bool
396 ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const
398 ACE_OS_TRACE ("ACE_TSS_Info::operator==");
400 return this->key_ == info.key_;
403 // Check for inequality.
404 bool
405 ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const
407 ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
409 return !(*this == info);
412 void
413 ACE_TSS_Info::dump ()
415 # if defined (ACE_HAS_DUMP)
416 // ACE_OS_TRACE ("ACE_TSS_Info::dump");
418 # if 0
419 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
420 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %u\n"), this->key_));
421 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("destructor_ = %u\n"), this->destructor_));
422 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
423 # endif /* 0 */
424 # endif /* ACE_HAS_DUMP */
427 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
428 // to the single file of template instantiations.
430 ACE_TSS_Keys::ACE_TSS_Keys ()
432 for (u_int i = 0; i < ACE_WORDS; ++i)
434 key_bit_words_[i] = 0;
439 void
440 ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit)
442 word = key / ACE_BITS_PER_WORD;
443 bit = key % ACE_BITS_PER_WORD;
447 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key)
449 u_int word, bit;
450 find (key, word, bit);
452 if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
454 return 1;
456 else
458 ACE_SET_BITS (key_bit_words_[word], 1 << bit);
459 return 0;
464 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key)
466 u_int word, bit;
467 find (key, word, bit);
469 if (word < ACE_WORDS && ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
471 ACE_CLR_BITS (key_bit_words_[word], 1 << bit);
472 return 0;
474 else
476 return 1;
481 ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
483 u_int word, bit;
484 find (key, word, bit);
486 return word < ACE_WORDS ? ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit) : 0;
490 * @class ACE_TSS_Cleanup
491 * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
493 class ACE_TSS_Cleanup
495 public:
496 ACE_ALLOC_HOOK_DECLARE;
498 /// Register a newly-allocated key
499 /// @param key the key to be monitored
500 /// @param destructor the function to call to delete objects stored via this key
501 int insert (ACE_thread_key_t key, void (*destructor)(void *));
503 /// Mark a key as being used by this thread.
504 void thread_use_key (ACE_thread_key_t key);
506 /// This thread is no longer using this key
507 /// call destructor if appropriate
508 int thread_detach_key (ACE_thread_key_t key);
510 /// This key is no longer used
511 /// Release key if use count == 0
512 /// fail if use_count != 0;
513 /// @param key the key to be released
514 int free_key (ACE_thread_key_t key);
516 /// Cleanup the thread-specific objects. Does _NOT_ exit the thread.
517 /// For each used key perform the same actions as free_key.
518 void thread_exit ();
520 private:
521 void dump ();
523 /// Release a key used by this thread
524 /// @param info reference to the info for this key
525 /// @param destructor out arg to receive destructor function ptr
526 /// @param tss_obj out arg to receive pointer to deletable object
527 void thread_release (
528 ACE_TSS_Info &info,
529 ACE_TSS_Info::Destructor & destructor,
530 void *& tss_obj);
532 /// remove key if it's unused (thread_count == 0)
533 /// @param info reference to the info for this key
534 int remove_key (ACE_TSS_Info &info);
536 /// Find the TSS keys (if any) for this thread.
537 /// @param thread_keys reference to pointer to be filled in by this function.
538 /// @return false if keys don't exist.
539 bool find_tss_keys (ACE_TSS_Keys *& thread_keys) const;
541 /// Accessor for this threads ACE_TSS_Keys instance.
542 /// Creates the keys if necessary.
543 ACE_TSS_Keys *tss_keys ();
545 /// Ensure singleton.
546 ACE_TSS_Cleanup ();
547 ~ACE_TSS_Cleanup ();
549 /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
550 friend class TSS_Cleanup_Instance;
552 private:
553 // Array of <ACE_TSS_Info> objects.
554 typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS];
555 typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR;
557 /// Table of <ACE_TSS_Info>'s.
558 ACE_TSS_TABLE table_;
560 /// Key for the thread-specific ACE_TSS_Keys
561 /// Used by find_tss_keys() or tss_keys() to find the
562 /// bit array that records whether each TSS key is in
563 /// use by this thread.
564 ACE_thread_key_t in_use_;
567 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Cleanup);
568 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Keys);
570 /*****************************************************************************/
572 * @class TSS_Cleanup_Instance
573 * @A class to manage an instance pointer to ACE_TSS_Cleanup.
574 * Note: that the double checked locking pattern doesn't allow
575 * safe deletion.
576 * Callers who wish to access the singleton ACE_TSS_Cleanup must
577 * do so by instantiating a TSS_Cleanup_Instance, calling the valid
578 * method to be sure the ACE_TSS_Cleanup is available, then using
579 * the TSS_Cleanup_Instance as a pointer to the instance.
580 * Construction argument to the TSS_Cleanup_Instance determines how
581 * it is to be used:
582 * CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
583 * USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
584 * DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
585 * delete it when the TSS_Cleanup_Instance goes out of scope.
588 class TSS_Cleanup_Instance
590 public:
591 enum Purpose
593 CREATE,
594 USE,
595 DESTROY
597 explicit TSS_Cleanup_Instance (Purpose purpose = USE);
598 ~TSS_Cleanup_Instance();
600 bool valid();
601 ACE_TSS_Cleanup * operator ->();
603 private:
604 ACE_TSS_Cleanup * operator *();
606 private:
607 static unsigned int reference_count_;
608 static ACE_TSS_Cleanup * instance_;
609 static ACE_Thread_Mutex* mutex_;
610 static ACE_Condition_Thread_Mutex* condition_;
612 private:
613 ACE_TSS_Cleanup * ptr_;
614 unsigned short flags_;
615 enum
617 FLAG_DELETING = 1,
618 FLAG_VALID_CHECKED = 2
622 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose)
623 : ptr_(0)
624 , flags_(0)
626 // During static construction or construction of the ACE_Object_Manager,
627 // there can be only one thread in this constructor at any one time, so
628 // it's safe to check for a zero mutex_. If it's zero, we create a new
629 // mutex and condition variable.
630 if (mutex_ == 0)
632 ACE_NEW (mutex_, ACE_Thread_Mutex ());
633 ACE_NEW (condition_, ACE_Condition_Thread_Mutex (*mutex_));
636 ACE_GUARD (ACE_Thread_Mutex, m, *mutex_);
638 if (purpose == CREATE)
640 if (instance_ == 0)
642 instance_ = new ACE_TSS_Cleanup();
644 ptr_ = instance_;
645 ++reference_count_;
647 else if(purpose == DESTROY)
649 if (instance_ != 0)
651 ptr_ = instance_;
652 instance_ = 0;
653 ACE_SET_BITS(flags_, FLAG_DELETING);
654 while (reference_count_ > 0)
656 condition_->wait();
660 else // must be normal use
662 ACE_ASSERT(purpose == USE);
663 if (instance_ != 0)
665 ptr_ = instance_;
666 ++reference_count_;
671 TSS_Cleanup_Instance::~TSS_Cleanup_Instance ()
673 // Variable to hold the mutex_ to delete outside the scope of the
674 // guard.
675 ACE_Thread_Mutex *del_mutex = 0;
677 // scope the guard
679 ACE_GUARD (ACE_Thread_Mutex, guard, *mutex_);
680 if (ptr_ != 0)
682 if (ACE_BIT_ENABLED (flags_, FLAG_DELETING))
684 ACE_ASSERT(instance_ == 0);
685 ACE_ASSERT(reference_count_ == 0);
686 delete ptr_;
687 del_mutex = mutex_ ;
688 mutex_ = 0;
690 else
692 ACE_ASSERT (reference_count_ > 0);
693 --reference_count_;
694 if (reference_count_ == 0 && instance_ == 0)
695 condition_->signal ();
698 }// end of guard scope
700 if (del_mutex != 0)
702 delete condition_;
703 condition_ = 0;
704 delete del_mutex;
708 bool
709 TSS_Cleanup_Instance::valid()
711 ACE_SET_BITS(flags_, FLAG_VALID_CHECKED);
712 return (this->instance_ != 0);
715 ACE_TSS_Cleanup *
716 TSS_Cleanup_Instance::operator *()
718 ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
719 return instance_;
722 ACE_TSS_Cleanup *
723 TSS_Cleanup_Instance::operator ->()
725 ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
726 return instance_;
729 // = Static object initialization.
730 unsigned int TSS_Cleanup_Instance::reference_count_ = 0;
731 ACE_TSS_Cleanup * TSS_Cleanup_Instance::instance_ = 0;
732 ACE_Thread_Mutex* TSS_Cleanup_Instance::mutex_ = 0;
733 ACE_Condition_Thread_Mutex* TSS_Cleanup_Instance::condition_ = 0;
735 ACE_TSS_Cleanup::~ACE_TSS_Cleanup ()
739 void
740 ACE_TSS_Cleanup::thread_exit ()
742 ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
743 // variables to hold the destructors, keys
744 // and pointers to the object to be destructed
745 // the actual destruction is deferred until the guard is released
746 ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
747 void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
748 ACE_thread_key_t keys[ACE_DEFAULT_THREAD_KEYS];
749 // count of items to be destroyed
750 unsigned int d_count = 0;
752 // scope the guard
754 ACE_TSS_CLEANUP_GUARD
756 // if not initialized or already cleaned up
757 ACE_TSS_Keys *this_thread_keys = 0;
758 if (! find_tss_keys (this_thread_keys) )
760 return;
763 // Minor hack: Iterating in reverse order means the LOG buffer which is
764 // accidentally allocated first will be accidentally deallocated (almost)
765 // last -- in case someone logs something from the other destructors.
766 // applications should not count on this behavior because platforms which
767 // do not use ACE_TSS_Cleanup may delete objects in other orders.
768 unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
769 while( key_index > 0)
771 --key_index;
772 ACE_TSS_Info & info = this->table_[key_index];
773 // if this key is in use by this thread
774 if (info.key_in_use () && this_thread_keys->is_set(info.key_))
776 // defer deleting the in-use key until all others have been deleted
777 if(info.key_ != this->in_use_)
779 destructor[d_count] = 0;
780 tss_obj[d_count] = 0;
781 keys[d_count] = 0;
782 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
783 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
785 keys[d_count] = info.key_;
786 ++d_count;
792 // remove the in_use bit vector last
793 u_int use_index = this->in_use_;
794 ACE_TSS_Info & info = this->table_[use_index];
795 destructor[d_count] = 0;
796 tss_obj[d_count] = 0;
797 keys[d_count] = 0;
798 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
799 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
801 keys[d_count] = info.key_;
802 ++d_count;
804 } // end of guard scope
805 for (unsigned int d_index = 0; d_index < d_count; ++d_index)
807 (*destructor[d_index])(tss_obj[d_index]);
808 #if defined (ACE_HAS_TSS_EMULATION)
809 ACE_TSS_Emulation::ts_object (keys[d_index]) = 0;
810 #else // defined (ACE_HAS_TSS_EMULATION)
811 ACE_OS::thr_setspecific_native (keys[d_index], 0);
812 #endif // defined (ACE_HAS_TSS_EMULATION)
816 extern "C" void
817 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
819 delete static_cast <ACE_TSS_Keys *> (tss_keys);
822 ACE_TSS_Cleanup::ACE_TSS_Cleanup ()
823 : in_use_ (ACE_OS::NULL_key)
825 ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
829 ACE_TSS_Cleanup::insert (ACE_thread_key_t key,
830 void (*destructor)(void *))
832 ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
833 ACE_TSS_CLEANUP_GUARD
835 u_int key_index = key;
836 ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
837 if (key_index < ACE_DEFAULT_THREAD_KEYS)
839 ACE_ASSERT (table_[key_index].thread_count_ == -1);
840 table_[key_index] = ACE_TSS_Info (key, destructor);
841 table_[key_index].thread_count_ = 0; // inserting it does not use it
842 // but it does "allocate" it
843 return 0;
845 else
847 return -1;
852 ACE_TSS_Cleanup::free_key (ACE_thread_key_t key)
854 ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
855 ACE_TSS_CLEANUP_GUARD
856 u_int key_index = key;
857 if (key_index < ACE_DEFAULT_THREAD_KEYS)
859 return remove_key (this->table_ [key_index]);
861 return -1;
865 ACE_TSS_Cleanup::remove_key (ACE_TSS_Info &info)
867 // assume CLEANUP_GUARD is held by caller
868 ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
870 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
871 // When this is done, any existing TSS objects controlled by this key are leaked
872 // There is no "right thing" to do in this case
874 // only remove it if all threads are done with it
875 if (info.thread_count_ != 0)
877 return -1;
879 #endif // 0
881 #if !defined (ACE_HAS_TSS_EMULATION)
882 ACE_OS_thread_key_t temp_key = info.key_;
883 ACE_OS::thr_keyfree_native (temp_key);
884 #endif /* !ACE_HAS_TSS_EMULATION */
885 if (info.key_ == this->in_use_)
887 this->in_use_ = ACE_OS::NULL_key;
889 info.key_in_use (0);
890 info.destructor_ = 0;
891 return 0;
895 ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key)
897 // variables to hold the destructor and the object to be destructed
898 // the actual call is deferred until the guard is released
899 ACE_TSS_Info::Destructor destructor = 0;
900 void * tss_obj = 0;
902 // scope the guard
904 ACE_TSS_CLEANUP_GUARD
906 u_int key_index = key;
907 ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0]));
908 // If this entry was never set, just bug out. If it is set, but is the
909 // wrong key, assert.
910 if (this->table_[key_index].key_ == 0)
911 return 0;
912 ACE_ASSERT (this->table_[key_index].key_ == key);
913 ACE_TSS_Info &info = this->table_ [key_index];
915 // sanity check
916 if (!info.key_in_use ())
918 return -1;
921 this->thread_release (info, destructor, tss_obj);
922 } // end of scope for the Guard
923 // if there's a destructor and an object to be destroyed
924 if (destructor != 0 && tss_obj != 0)
926 (*destructor) (tss_obj);
928 return 0;
931 void
932 ACE_TSS_Cleanup::thread_release (
933 ACE_TSS_Info &info,
934 ACE_TSS_Info::Destructor & destructor,
935 void *& tss_obj)
937 // assume guard is held by caller
938 // Find the TSS keys (if any) for this thread
939 // do not create them if they don't exist
940 ACE_TSS_Keys * thread_keys = 0;
941 if (find_tss_keys (thread_keys))
943 // if this key is in use by this thread
944 if (thread_keys->test_and_clear(info.key_) == 0)
946 // save destructor & pointer to tss object
947 // until after the guard is released
948 destructor = info.destructor_;
949 ACE_OS::thr_getspecific (info.key_, &tss_obj);
950 ACE_ASSERT (info.thread_count_ > 0);
951 --info.thread_count_;
956 void
957 ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key)
959 // If the key's ACE_TSS_Info in-use bit for this thread is not set,
960 // set it and increment the key's thread_count_.
961 if (! tss_keys ()->test_and_set (key))
963 ACE_TSS_CLEANUP_GUARD
965 // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
966 u_int key_index = key;
967 ACE_TSS_Info &key_info = this->table_ [key_index];
969 ACE_ASSERT (key_info.key_in_use ());
970 ++key_info.thread_count_;
974 void
975 ACE_TSS_Cleanup::dump ()
977 # if defined (ACE_HAS_DUMP)
978 // Iterate through all the thread-specific items and dump them all.
980 ACE_TSS_TABLE_ITERATOR key_info = table_;
981 for (unsigned int i = 0;
982 i < ACE_DEFAULT_THREAD_KEYS;
983 ++key_info, ++i)
984 key_info->dump ();
985 # endif /* ACE_HAS_DUMP */
988 bool
989 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys *& tss_keys) const
991 if (this->in_use_ == ACE_OS::NULL_key)
992 return false;
993 if (ACE_OS::thr_getspecific (in_use_,
994 reinterpret_cast<void **> (&tss_keys)) == -1)
996 ACE_ASSERT (false);
997 return false; // This should not happen!
999 return tss_keys != 0;
1002 ACE_TSS_Keys *
1003 ACE_TSS_Cleanup::tss_keys ()
1005 if (this->in_use_ == ACE_OS::NULL_key)
1007 ACE_TSS_CLEANUP_GUARD
1008 // Double-check;
1009 if (in_use_ == ACE_OS::NULL_key)
1011 // Initialize in_use_ with a new key.
1012 if (ACE_OS::thr_keycreate (&in_use_,
1013 &ACE_TSS_Cleanup_keys_destroyer))
1015 ACE_ASSERT (false);
1016 return 0; // Major problems, this should *never* happen!
1021 void *ts_keys = 0;
1022 if (ACE_OS::thr_getspecific (in_use_, &ts_keys) == -1)
1024 ACE_ASSERT (false);
1025 return 0; // This should not happen!
1028 if (ts_keys == 0)
1030 ACE_NEW_RETURN (ts_keys,
1031 ACE_TSS_Keys,
1033 // Store the dynamically allocated pointer in thread-specific
1034 // storage.
1035 if (ACE_OS::thr_setspecific (in_use_, ts_keys) == -1)
1037 ACE_ASSERT (false);
1038 delete reinterpret_cast <ACE_TSS_Keys*> (ts_keys);
1039 return 0; // Major problems, this should *never* happen!
1043 return reinterpret_cast <ACE_TSS_Keys*>(ts_keys);
1046 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
1048 /*****************************************************************************/
1050 // = Static initialization.
1052 // This is necessary to deal with POSIX pthreads insanity. This
1053 // guarantees that we've got a "zero'd" thread id even when
1054 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
1055 // as structures... Under no circumstances should these be given
1056 // initial values.
1057 // Note: these three objects require static construction.
1058 ACE_thread_t ACE_OS::NULL_thread;
1059 ACE_hthread_t ACE_OS::NULL_hthread;
1060 #if defined (ACE_HAS_TSS_EMULATION)
1061 ACE_thread_key_t ACE_OS::NULL_key = static_cast <ACE_thread_key_t> (-1);
1062 #else /* ! ACE_HAS_TSS_EMULATION */
1063 ACE_thread_key_t ACE_OS::NULL_key;
1064 #endif /* ! ACE_HAS_TSS_EMULATION */
1066 /*****************************************************************************/
1068 void
1069 ACE_OS::cleanup_tss (const u_int main_thread)
1071 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
1072 { // scope the cleanup instance
1073 // Call TSS destructors for current thread.
1074 TSS_Cleanup_Instance cleanup;
1075 if (cleanup.valid ())
1077 cleanup->thread_exit ();
1080 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
1082 if (main_thread)
1084 #if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS)
1085 // Just close the ACE_Log_Msg for the current (which should be
1086 // main) thread. We don't have TSS emulation; if there's native
1087 // TSS, it should call its destructors when the main thread
1088 // exits.
1089 ACE_Base_Thread_Adapter::close_log_msg ();
1090 #endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
1092 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
1093 // Finally, free up the ACE_TSS_Cleanup instance. This method gets
1094 // called by the ACE_Object_Manager.
1095 TSS_Cleanup_Instance cleanup(TSS_Cleanup_Instance::DESTROY);
1096 if (cleanup.valid ())
1098 ; // the pointer deletes the Cleanup when it goes out of scope
1101 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
1103 #if defined (ACE_HAS_TSS_EMULATION)
1104 ACE_TSS_Emulation::tss_close ();
1105 #endif /* ACE_HAS_TSS_EMULATION */
1109 /*****************************************************************************/
1110 // CONDITIONS BEGIN
1111 /*****************************************************************************/
1113 #if defined (ACE_LACKS_COND_T)
1115 ACE_OS::cond_broadcast (ACE_cond_t *cv)
1117 ACE_OS_TRACE ("ACE_OS::cond_broadcast");
1118 # if defined (ACE_HAS_THREADS)
1119 // The <external_mutex> must be locked before this call is made.
1121 // This is needed to ensure that <waiters_> and <was_broadcast_> are
1122 // consistent relative to each other.
1123 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1125 return -1;
1128 bool have_waiters = false;
1130 if (cv->waiters_ > 0)
1132 // We are broadcasting, even if there is just one waiter...
1133 // Record the fact that we are broadcasting. This helps the
1134 // cond_wait() method know how to optimize itself. Be sure to
1135 // set this with the <waiters_lock_> held.
1136 cv->was_broadcast_ = 1;
1137 have_waiters = true;
1140 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1142 // This is really bad, we have the lock but can't release it anymore
1143 return -1;
1146 int result = 0;
1147 if (have_waiters)
1149 // Wake up all the waiters.
1150 if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1)
1151 result = -1;
1152 // Wait for all the awakened threads to acquire their part of
1153 // the counting semaphore.
1154 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1155 else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1)
1156 # else
1157 else if (ACE_OS::event_wait (&cv->waiters_done_) == -1)
1158 # endif /* ACE_VXWORKS */
1159 result = -1;
1160 // This is okay, even without the <waiters_lock_> held because
1161 // no other waiter threads can wake up to access it.
1162 cv->was_broadcast_ = 0;
1164 return result;
1165 # else
1166 ACE_UNUSED_ARG (cv);
1167 ACE_NOTSUP_RETURN (-1);
1168 # endif /* ACE_HAS_THREADS */
1172 ACE_OS::cond_destroy (ACE_cond_t *cv)
1174 ACE_OS_TRACE ("ACE_OS::cond_destroy");
1175 # if defined (ACE_HAS_THREADS)
1176 # if defined (ACE_HAS_WTHREADS)
1177 ACE_OS::event_destroy (&cv->waiters_done_);
1178 # elif defined (ACE_VXWORKS) || defined (ACE_MQX)
1179 ACE_OS::sema_destroy (&cv->waiters_done_);
1180 # endif /* ACE_VXWORKS */
1181 int result = 0;
1182 if (ACE_OS::thread_mutex_destroy (&cv->waiters_lock_) != 0)
1183 result = -1;
1185 if (ACE_OS::sema_destroy (&cv->sema_) != 0)
1186 result = -1;
1188 return result;
1189 # else
1190 ACE_UNUSED_ARG (cv);
1191 ACE_NOTSUP_RETURN (-1);
1192 # endif /* ACE_HAS_THREADS */
1196 ACE_OS::cond_init (ACE_cond_t *cv,
1197 ACE_condattr_t &attributes,
1198 const char *name, void *arg)
1200 return
1201 ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
1204 # if defined (ACE_HAS_WCHAR)
1206 ACE_OS::cond_init (ACE_cond_t *cv,
1207 ACE_condattr_t &attributes,
1208 const wchar_t *name, void *arg)
1210 return
1211 ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
1213 # endif /* ACE_HAS_WCHAR */
1216 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
1218 ACE_OS_TRACE ("ACE_OS::cond_init");
1219 # if defined (ACE_HAS_THREADS)
1220 cv->waiters_ = 0;
1221 cv->was_broadcast_ = 0;
1223 int result = 0;
1224 if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
1225 result = -1;
1226 else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
1227 result = -1;
1228 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1229 else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
1230 # else
1231 else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
1232 # endif /* ACE_VXWORKS */
1233 result = -1;
1234 return result;
1235 # else
1236 ACE_UNUSED_ARG (cv);
1237 ACE_UNUSED_ARG (type);
1238 ACE_UNUSED_ARG (name);
1239 ACE_UNUSED_ARG (arg);
1240 ACE_NOTSUP_RETURN (-1);
1241 # endif /* ACE_HAS_THREADS */
1244 # if defined (ACE_HAS_WCHAR)
1246 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
1248 ACE_OS_TRACE ("ACE_OS::cond_init");
1249 # if defined (ACE_HAS_THREADS)
1250 cv->waiters_ = 0;
1251 cv->was_broadcast_ = 0;
1253 int result = 0;
1254 if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
1255 result = -1;
1256 else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
1257 result = -1;
1258 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1259 else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
1260 # else
1261 else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
1262 # endif /* ACE_VXWORKS */
1263 result = -1;
1264 return result;
1265 # else
1266 ACE_UNUSED_ARG (cv);
1267 ACE_UNUSED_ARG (type);
1268 ACE_UNUSED_ARG (name);
1269 ACE_UNUSED_ARG (arg);
1270 ACE_NOTSUP_RETURN (-1);
1271 # endif /* ACE_HAS_THREADS */
1273 # endif /* ACE_HAS_WCHAR */
1276 ACE_OS::cond_signal (ACE_cond_t *cv)
1278 ACE_OS_TRACE ("ACE_OS::cond_signal");
1279 # if defined (ACE_HAS_THREADS)
1280 // If there aren't any waiters, then this is a no-op. Note that
1281 // this function *must* be called with the <external_mutex> held
1282 // since other wise there is a race condition that can lead to the
1283 // lost wakeup bug... This is needed to ensure that the <waiters_>
1284 // value is not in an inconsistent internal state while being
1285 // updated by another thread.
1286 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1287 return -1;
1288 bool const have_waiters = cv->waiters_ > 0;
1289 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1290 return -1;
1292 if (have_waiters)
1293 return ACE_OS::sema_post (&cv->sema_);
1294 else
1295 return 0; // No-op
1296 # else
1297 ACE_UNUSED_ARG (cv);
1298 ACE_NOTSUP_RETURN (-1);
1299 # endif /* ACE_HAS_THREADS */
1303 ACE_OS::cond_wait (ACE_cond_t *cv,
1304 ACE_mutex_t *external_mutex)
1306 ACE_OS_TRACE ("ACE_OS::cond_wait");
1307 # if defined (ACE_HAS_THREADS)
1308 // Prevent race conditions on the <waiters_> count.
1309 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1310 return -1;
1312 ++cv->waiters_;
1314 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1315 return -1;
1317 int result = 0;
1319 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1320 if (external_mutex->type_ == USYNC_PROCESS)
1322 // This call will automatically release the mutex and wait on the semaphore.
1323 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_,
1324 cv->sema_, INFINITE, FALSE),
1325 result),
1326 int, -1, result);
1327 if (result == -1)
1328 return result;
1330 else
1331 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1333 // We keep the lock held just long enough to increment the count of
1334 // waiters by one. Note that we can't keep it held across the call
1335 // to ACE_OS::sema_wait() since that will deadlock other calls to
1336 // ACE_OS::cond_signal().
1337 if (ACE_OS::mutex_unlock (external_mutex) != 0)
1338 return -1;
1340 // Wait to be awakened by a ACE_OS::cond_signal() or
1341 // ACE_OS::cond_broadcast().
1342 result = ACE_OS::sema_wait (&cv->sema_);
1345 // Reacquire lock to avoid race conditions on the <waiters_> count.
1346 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1347 return -1;
1349 // We're ready to return, so there's one less waiter.
1350 --cv->waiters_;
1352 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1354 // Release the lock so that other collaborating threads can make
1355 // progress.
1356 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1357 return -1;
1359 if (result == -1)
1360 // Bad things happened, so let's just return below.
1361 /* NOOP */;
1362 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1363 else if (external_mutex->type_ == USYNC_PROCESS)
1365 if (last_waiter)
1367 // This call atomically signals the <waiters_done_> event and
1368 // waits until it can acquire the mutex. This is important to
1369 // prevent unfairness.
1370 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
1371 external_mutex->proc_mutex_,
1372 INFINITE, FALSE),
1373 result),
1374 int, -1, result);
1375 else
1376 // We must always regain the <external_mutex>, even when
1377 // errors occur because that's the guarantee that we give to
1378 // our callers.
1379 if (ACE_OS::mutex_lock (external_mutex) != 0)
1380 return -1;
1382 return result;
1383 /* NOTREACHED */
1385 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1386 // If we're the last waiter thread during this particular broadcast
1387 // then let all the other threads proceed.
1388 else if (last_waiter)
1389 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1390 ACE_OS::sema_post (&cv->waiters_done_);
1391 # else
1392 ACE_OS::event_signal (&cv->waiters_done_);
1393 # endif /* ACE_VXWORKS */
1395 // We must always regain the <external_mutex>, even when errors
1396 // occur because that's the guarantee that we give to our callers.
1397 ACE_OS::mutex_lock (external_mutex);
1399 return result;
1400 # else
1401 ACE_UNUSED_ARG (cv);
1402 ACE_UNUSED_ARG (external_mutex);
1403 ACE_NOTSUP_RETURN (-1);
1404 # endif /* ACE_HAS_THREADS */
1408 ACE_OS::cond_timedwait (ACE_cond_t *cv,
1409 ACE_mutex_t *external_mutex,
1410 ACE_Time_Value *timeout)
1412 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1413 # if defined (ACE_HAS_THREADS)
1414 // Handle the easy case first.
1415 if (timeout == 0)
1416 return ACE_OS::cond_wait (cv, external_mutex);
1417 # if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS) || defined (ACE_MQX)
1419 // Prevent race conditions on the <waiters_> count.
1420 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1421 return -1;
1423 ++cv->waiters_;
1425 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1426 return -1;
1428 int result = 0;
1429 ACE_Errno_Guard error (errno, 0);
1430 int msec_timeout = 0;
1432 if (timeout != 0 && *timeout != ACE_Time_Value::zero)
1434 // Note that we must convert between absolute time (which is
1435 // passed as a parameter) and relative time (which is what
1436 // WaitForSingleObjects() expects).
1437 ACE_Time_Value relative_time = timeout->to_relative_time ();
1439 // Watchout for situations where a context switch has caused the
1440 // current time to be > the timeout.
1441 if (relative_time > ACE_Time_Value::zero)
1442 msec_timeout = relative_time.msec ();
1445 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1446 if (external_mutex->type_ == USYNC_PROCESS)
1447 // This call will automatically release the mutex and wait on the
1448 // semaphore.
1449 result = ::SignalObjectAndWait (external_mutex->proc_mutex_,
1450 cv->sema_,
1451 msec_timeout,
1452 FALSE);
1453 else
1454 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1456 // We keep the lock held just long enough to increment the count
1457 // of waiters by one. Note that we can't keep it held across
1458 // the call to WaitForSingleObject since that will deadlock
1459 // other calls to ACE_OS::cond_signal().
1460 if (ACE_OS::mutex_unlock (external_mutex) != 0)
1461 return -1;
1463 // Wait to be awakened by a ACE_OS::signal() or
1464 // ACE_OS::broadcast().
1465 # if defined (ACE_WIN32)
1466 result = ::WaitForSingleObject (cv->sema_, msec_timeout);
1467 # elif defined (ACE_VXWORKS)
1468 // Inline the call to ACE_OS::sema_wait () because it takes an
1469 // ACE_Time_Value argument. Avoid the cost of that conversion . . .
1470 _Vx_freq_t const ticks_per_sec = ::sysClkRateGet ();
1471 int const ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS;
1472 result = ::semTake (cv->sema_.sema_, ticks);
1473 # else
1474 result = ACE_OS::sema_wait (&cv->sema_, timeout);
1475 # endif /* ACE_WIN32 || VXWORKS */
1478 // Reacquire lock to avoid race conditions.
1479 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1480 return -1;
1482 --cv->waiters_;
1484 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1486 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1487 return -1;
1489 # if defined (ACE_WIN32)
1490 if (result != (int)WAIT_OBJECT_0)
1492 switch (result)
1494 case WAIT_TIMEOUT:
1495 error = ETIME;
1496 break;
1497 default:
1498 error = ::GetLastError ();
1499 break;
1501 result = -1;
1503 # elif defined (ACE_VXWORKS)
1504 if (result == ERROR)
1506 switch (errno)
1508 case S_objLib_OBJ_TIMEOUT:
1509 error = ETIME;
1510 break;
1511 case S_objLib_OBJ_UNAVAILABLE:
1512 if (msec_timeout == 0)
1513 error = ETIME;
1514 break;
1515 default:
1516 error = errno;
1517 break;
1519 result = -1;
1521 # endif /* ACE_WIN32 || VXWORKS */
1522 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1523 if (external_mutex->type_ == USYNC_PROCESS)
1525 if (last_waiter)
1526 // This call atomically signals the <waiters_done_> event and
1527 // waits until it can acquire the mutex. This is important to
1528 // prevent unfairness.
1529 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
1530 external_mutex->proc_mutex_,
1531 INFINITE, FALSE),
1532 result),
1533 int, -1, result);
1534 else
1536 // We must always regain the <external_Mutex>, even when
1537 // errors occur because that's the guarantee that we give to
1538 // our callers.
1539 if (ACE_OS::mutex_lock (external_mutex) != 0)
1540 return -1;
1543 return result;
1544 /* NOTREACHED */
1546 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1547 // Note that this *must* be an "if" statement rather than an "else
1548 // if" statement since the caller may have timed out and hence the
1549 // result would have been -1 above.
1550 if (last_waiter)
1552 // Release the signaler/broadcaster if we're the last waiter.
1553 # if defined (ACE_WIN32)
1554 if (ACE_OS::event_signal (&cv->waiters_done_) != 0)
1555 # else
1556 if (ACE_OS::sema_post (&cv->waiters_done_) != 0)
1557 # endif /* ACE_WIN32 */
1558 return -1;
1561 // We must always regain the <external_mutex>, even when errors
1562 // occur because that's the guarantee that we give to our callers.
1563 if (ACE_OS::mutex_lock (external_mutex) != 0)
1564 return -1;
1566 return result;
1567 # endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
1568 # else
1569 ACE_UNUSED_ARG (cv);
1570 ACE_UNUSED_ARG (external_mutex);
1571 ACE_UNUSED_ARG (timeout);
1572 ACE_NOTSUP_RETURN (-1);
1573 # endif /* ACE_HAS_THREADS */
1575 #else
1577 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
1579 ACE_condattr_t attributes;
1580 if (ACE_OS::condattr_init (attributes, type) == 0
1581 && ACE_OS::cond_init (cv, attributes, name, arg) == 0)
1583 (void) ACE_OS::condattr_destroy (attributes);
1584 return 0;
1586 return -1;
1588 #endif /* ACE_LACKS_COND_T */
1590 #if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS)
1592 ACE_OS::cond_timedwait (ACE_cond_t *cv,
1593 ACE_thread_mutex_t *external_mutex,
1594 ACE_Time_Value *timeout)
1596 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1597 # if defined (ACE_HAS_THREADS)
1598 // Handle the easy case first.
1599 if (timeout == 0)
1600 return ACE_OS::cond_wait (cv, external_mutex);
1602 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1603 int msec_timeout = 0;
1604 int result = 0;
1606 ACE_Time_Value relative_time = timeout->to_relative_time ();
1607 // Watchout for situations where a context switch has caused the
1608 // current time to be > the timeout.
1609 if (relative_time > ACE_Time_Value::zero)
1610 msec_timeout = relative_time.msec ();
1612 ACE_OSCALL (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, external_mutex, msec_timeout),
1613 result),
1614 int, result);
1615 return result;
1616 #else
1617 // Prevent race conditions on the <waiters_> count.
1618 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1619 return -1;
1621 ++cv->waiters_;
1623 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1624 return -1;
1626 int result = 0;
1627 int error = 0;
1628 int msec_timeout = 0;
1630 if (timeout != 0 && *timeout != ACE_Time_Value::zero)
1632 // Note that we must convert between absolute time (which is
1633 // passed as a parameter) and relative time (which is what
1634 // WaitForSingleObjects() expects).
1635 ACE_Time_Value relative_time = timeout->to_relative_time ();
1637 // Watchout for situations where a context switch has caused the
1638 // current time to be > the timeout.
1639 if (relative_time > ACE_Time_Value::zero)
1640 msec_timeout = relative_time.msec ();
1643 // We keep the lock held just long enough to increment the count of
1644 // waiters by one. Note that we can't keep it held across the call
1645 // to WaitForSingleObject since that will deadlock other calls to
1646 // ACE_OS::cond_signal().
1647 if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
1648 return -1;
1650 // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
1651 result = ::WaitForSingleObject (cv->sema_, msec_timeout);
1653 // Reacquire lock to avoid race conditions.
1654 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1655 return -1;
1657 --cv->waiters_;
1659 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1661 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1662 return -1;
1664 if (result != (int)WAIT_OBJECT_0)
1666 switch (result)
1668 case WAIT_TIMEOUT:
1669 error = ETIME;
1670 break;
1671 default:
1672 error = ::GetLastError ();
1673 break;
1675 result = -1;
1678 if (last_waiter)
1680 // Release the signaler/broadcaster if we're the last waiter.
1681 if (ACE_OS::event_signal (&cv->waiters_done_) != 0)
1682 return -1;
1685 // We must always regain the <external_mutex>, even when errors
1686 // occur because that's the guarantee that we give to our callers.
1687 if (ACE_OS::thread_mutex_lock (external_mutex) != 0)
1688 result = -1;
1690 if (error != 0)
1692 /* This assignment must only be done if error != 0,
1693 * since writing 0 to errno violates the POSIX specification.
1695 errno = error;
1697 return result;
1698 # endif
1699 # else
1700 ACE_NOTSUP_RETURN (-1);
1701 # endif /* ACE_HAS_THREADS */
1705 ACE_OS::cond_wait (ACE_cond_t *cv,
1706 ACE_thread_mutex_t *external_mutex)
1708 ACE_OS_TRACE ("ACE_OS::cond_wait");
1709 # if defined (ACE_HAS_THREADS)
1710 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1711 int result;
1712 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, external_mutex, INFINITE), result), int);
1713 #else
1714 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1715 return -1;
1716 ++cv->waiters_;
1718 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1719 return -1;
1721 int result = 0;
1722 int error = 0;
1724 // We keep the lock held just long enough to increment the count of
1725 // waiters by one. Note that we can't keep it held across the call
1726 // to ACE_OS::sema_wait() since that will deadlock other calls to
1727 // ACE_OS::cond_signal().
1728 if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
1729 return -1;
1731 // Wait to be awakened by a ACE_OS::cond_signal() or
1732 // ACE_OS::cond_broadcast().
1733 result = ::WaitForSingleObject (cv->sema_, INFINITE);
1735 // Reacquire lock to avoid race conditions.
1736 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1737 return -1;
1739 cv->waiters_--;
1741 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1743 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1744 return -1;
1746 if (result != (int)WAIT_OBJECT_0)
1748 switch (result)
1750 case WAIT_TIMEOUT:
1751 error = ETIME;
1752 break;
1753 default:
1754 error = ::GetLastError ();
1755 break;
1758 else if (last_waiter)
1760 // Release the signaler/broadcaster if we're the last waiter.
1761 if (ACE_OS::event_signal (&cv->waiters_done_) != 0)
1762 return -1;
1765 // We must always regain the <external_mutex>, even when errors
1766 // occur because that's the guarantee that we give to our callers.
1767 if (ACE_OS::thread_mutex_lock (external_mutex) != 0)
1768 result = -1;
1770 // Reset errno in case mutex_lock() also fails...
1771 if (error != 0)
1773 /* This assignment must only be done if error != 0,
1774 * since writing 0 to errno violates the POSIX specification.
1776 errno = error;
1778 return result;
1779 #endif
1780 # else
1781 ACE_NOTSUP_RETURN (-1);
1782 # endif /* ACE_HAS_THREADS */
1784 # endif /* ACE_HAS_WTHREADS */
1786 /*****************************************************************************/
1787 // CONDITIONS END
1788 /*****************************************************************************/
1790 /*****************************************************************************/
1791 // MUTEXES BEGIN
1792 /*****************************************************************************/
1795 ACE_OS::mutex_init (ACE_mutex_t *m,
1796 int lock_scope,
1797 const char *name,
1798 ACE_mutexattr_t *attributes,
1799 LPSECURITY_ATTRIBUTES sa,
1800 int lock_type)
1802 // ACE_OS_TRACE ("ACE_OS::mutex_init");
1803 #if defined (ACE_HAS_THREADS)
1804 # if defined (ACE_HAS_PTHREADS)
1805 ACE_UNUSED_ARG (name);
1806 ACE_UNUSED_ARG (sa);
1808 # if defined (ACE_PTHREAD_MUTEXATTR_T_INITIALIZE)
1809 /* Tests show that VxWorks 6.x pthread lib does not only
1810 * require zeroing of mutex/condition objects to function correctly
1811 * but also of the attribute objects.
1813 pthread_mutexattr_t l_attributes = {0};
1814 # else
1815 pthread_mutexattr_t l_attributes;
1816 # endif
1818 if (attributes == 0)
1819 attributes = &l_attributes;
1820 int result = 0;
1821 int attr_init = 0; // have we initialized the local attributes.
1823 // Only do these initializations if the <attributes> parameter
1824 // wasn't originally set.
1825 if (attributes == &l_attributes)
1827 if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0)
1829 result = 0;
1830 attr_init = 1; // we have initialized these attributes
1832 else
1834 result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
1838 if (result == 0 && lock_scope != 0)
1840 # if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
1841 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes,
1842 lock_scope),
1843 result);
1844 # endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
1847 if (result == 0 && lock_type != 0)
1849 # if defined (ACE_HAS_RECURSIVE_MUTEXES) && !defined (ACE_LACKS_PTHREAD_MUTEXATTR_SETTYPE)
1850 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes,
1851 lock_type),
1852 result);
1853 # endif /* ACE_HAS_RECURSIVE_MUTEXES */
1856 if (result == 0)
1858 # if defined (ACE_PTHREAD_MUTEX_T_INITIALIZE)
1859 /* VxWorks 6.x API reference states:
1860 * If the memory for the mutex variable object has been allocated
1861 * dynamically, it is a good policy to always zero out the
1862 * block of memory so as to avoid spurious EBUSY return code
1863 * when calling this routine.
1864 * Tests shows this to be necessary.
1866 ACE_OS::memset (m, 0, sizeof (*m));
1867 # endif
1868 if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0)
1869 result = 0;
1870 else
1871 result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
1874 // Only do the deletions if the <attributes> parameter wasn't
1875 // originally set.
1876 if (attributes == &l_attributes && attr_init)
1877 ::pthread_mutexattr_destroy (&l_attributes);
1879 return result;
1880 # elif defined (ACE_HAS_WTHREADS)
1881 m->type_ = lock_scope;
1883 SECURITY_ATTRIBUTES sa_buffer;
1884 SECURITY_DESCRIPTOR sd_buffer;
1885 switch (lock_scope)
1887 case USYNC_PROCESS:
1888 m->proc_mutex_ =
1889 ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
1890 (sa, &sa_buffer, &sd_buffer),
1891 FALSE,
1892 name);
1893 if (m->proc_mutex_ == 0)
1894 ACE_FAIL_RETURN (-1);
1895 else
1897 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1898 ACE_OS::set_errno_to_last_error ();
1899 return 0;
1901 case USYNC_THREAD:
1902 return ACE_OS::thread_mutex_init (&m->thr_mutex_,
1903 lock_type,
1904 name,
1905 attributes);
1906 default:
1907 errno = EINVAL;
1908 return -1;
1910 /* NOTREACHED */
1912 # elif defined (ACE_VXWORKS)
1913 ACE_UNUSED_ARG (name);
1914 ACE_UNUSED_ARG (attributes);
1915 ACE_UNUSED_ARG (sa);
1916 ACE_UNUSED_ARG (lock_type);
1918 return (*m = ::semMCreate (lock_scope)) == 0 ? -1 : 0;
1919 # endif /* ACE_HAS_PTHREADS */
1920 #else
1921 ACE_UNUSED_ARG (m);
1922 ACE_UNUSED_ARG (lock_scope);
1923 ACE_UNUSED_ARG (name);
1924 ACE_UNUSED_ARG (attributes);
1925 ACE_UNUSED_ARG (sa);
1926 ACE_UNUSED_ARG (lock_type);
1927 ACE_NOTSUP_RETURN (-1);
1928 #endif /* ACE_HAS_THREADS */
1932 ACE_OS::mutex_destroy (ACE_mutex_t *m)
1934 ACE_OS_TRACE ("ACE_OS::mutex_destroy");
1935 #if defined (ACE_HAS_THREADS)
1936 # if defined (ACE_HAS_PTHREADS)
1937 # if defined (ACE_LACKS_PTHREAD_MUTEX_DESTROY)
1938 ACE_UNUSED_ARG (m);
1939 ACE_NOTSUP_RETURN (-1);
1940 # else
1941 int result;
1942 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m), result), int);
1943 # endif /* ACE_LACKS_PTHREAD_MUTEX_DESTROY */
1944 # elif defined (ACE_HAS_WTHREADS)
1945 switch (m->type_)
1947 case USYNC_PROCESS:
1948 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_),
1949 ace_result_),
1950 int, -1);
1951 case USYNC_THREAD:
1952 return ACE_OS::thread_mutex_destroy (&m->thr_mutex_);
1953 default:
1954 errno = EINVAL;
1955 return -1;
1957 /* NOTREACHED */
1958 # elif defined (ACE_VXWORKS)
1959 return ::semDelete (*m) == OK ? 0 : -1;
1960 # endif /* Threads variety case */
1961 #else
1962 ACE_UNUSED_ARG (m);
1963 ACE_NOTSUP_RETURN (-1);
1964 #endif /* ACE_HAS_THREADS */
1967 #if defined (ACE_HAS_WCHAR)
1969 ACE_OS::mutex_init (ACE_mutex_t *m,
1970 int lock_scope,
1971 const wchar_t *name,
1972 ACE_mutexattr_t *attributes,
1973 LPSECURITY_ATTRIBUTES sa,
1974 int lock_type)
1976 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
1977 m->type_ = lock_scope;
1978 SECURITY_ATTRIBUTES sa_buffer;
1979 SECURITY_DESCRIPTOR sd_buffer;
1980 switch (lock_scope)
1982 case USYNC_PROCESS:
1983 m->proc_mutex_ =
1984 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1985 (sa, &sa_buffer, &sd_buffer),
1986 FALSE,
1987 name);
1988 if (m->proc_mutex_ == 0)
1989 ACE_FAIL_RETURN (-1);
1990 else
1992 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1993 ACE_OS::set_errno_to_last_error ();
1994 return 0;
1996 case USYNC_THREAD:
1997 return ACE_OS::thread_mutex_init (&m->thr_mutex_,
1998 lock_type,
1999 name,
2000 attributes);
2003 errno = EINVAL;
2004 return -1;
2005 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2006 return ACE_OS::mutex_init (m,
2007 lock_scope,
2008 ACE_Wide_To_Ascii (name).char_rep (),
2009 attributes,
2011 lock_type);
2012 #endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2014 #endif /* ACE_HAS_WCHAR */
2017 ACE_OS::mutex_lock (ACE_mutex_t *m)
2019 // ACE_OS_TRACE ("ACE_OS::mutex_lock");
2020 #if defined (ACE_HAS_THREADS)
2021 # if defined (ACE_HAS_PTHREADS)
2022 // Note, don't use "::" here since the following call is often a macro.
2023 int result;
2024 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), result), int);
2025 # elif defined (ACE_HAS_WTHREADS)
2026 switch (m->type_)
2028 case USYNC_PROCESS:
2029 switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
2032 // Timeout can't occur, so don't bother checking...
2034 case WAIT_OBJECT_0:
2035 case WAIT_ABANDONED:
2036 // We will ignore abandonments in this method
2037 // Note that we still hold the lock
2038 return 0;
2039 default:
2040 // This is a hack, we need to find an appropriate mapping...
2041 ACE_OS::set_errno_to_last_error ();
2042 return -1;
2044 case USYNC_THREAD:
2045 return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
2046 default:
2047 errno = EINVAL;
2048 return -1;
2050 /* NOTREACHED */
2051 # elif defined (ACE_VXWORKS)
2052 return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1;
2053 # endif /* Threads variety case */
2054 #else
2055 ACE_UNUSED_ARG (m);
2056 ACE_NOTSUP_RETURN (-1);
2057 #endif /* ACE_HAS_THREADS */
2061 ACE_OS::mutex_lock (ACE_mutex_t *m,
2062 int &abandoned)
2064 ACE_OS_TRACE ("ACE_OS::mutex_lock");
2065 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2066 abandoned = 0;
2067 switch (m->type_)
2069 case USYNC_PROCESS:
2070 switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
2073 // Timeout can't occur, so don't bother checking...
2075 case WAIT_OBJECT_0:
2076 return 0;
2077 case WAIT_ABANDONED:
2078 abandoned = 1;
2079 return 0; // something goofed, but we hold the lock ...
2080 default:
2081 // This is a hack, we need to find an appropriate mapping...
2082 ACE_OS::set_errno_to_last_error ();
2083 return -1;
2085 case USYNC_THREAD:
2086 return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
2087 default:
2088 errno = EINVAL;
2089 return -1;
2091 /* NOTREACHED */
2092 #else
2093 ACE_UNUSED_ARG (m);
2094 ACE_UNUSED_ARG (abandoned);
2095 ACE_NOTSUP_RETURN (-1);
2096 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2100 ACE_OS::mutex_lock (ACE_mutex_t *m,
2101 const ACE_Time_Value &timeout)
2103 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
2105 # if defined (ACE_HAS_PTHREADS)
2106 int result;
2108 // "timeout" should be an absolute time.
2110 timespec_t ts = timeout; // Calls ACE_Time_Value::operator timespec_t().
2112 // Note that the mutex should not be a recursive one, i.e., it
2113 // should only be a standard mutex or an error checking mutex.
2115 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, result);
2117 // We need to adjust this to make the errno values consistent.
2118 if (result == -1 && errno == ETIMEDOUT)
2119 errno = ETIME;
2120 return result;
2122 # elif defined (ACE_HAS_WTHREADS)
2123 // Note that we must convert between absolute time (which is passed
2124 // as a parameter) and relative time (which is what the system call
2125 // expects).
2126 ACE_Time_Value relative_time = timeout.to_relative_time ();
2128 switch (m->type_)
2130 case USYNC_PROCESS:
2131 switch (::WaitForSingleObject (m->proc_mutex_,
2132 relative_time.msec ()))
2134 case WAIT_OBJECT_0:
2135 case WAIT_ABANDONED:
2136 // We will ignore abandonments in this method
2137 // Note that we still hold the lock
2138 return 0;
2139 case WAIT_TIMEOUT:
2140 errno = ETIME;
2141 return -1;
2142 default:
2143 // This is a hack, we need to find an appropriate mapping...
2144 ACE_OS::set_errno_to_last_error ();
2145 return -1;
2147 case USYNC_THREAD:
2148 ACE_NOTSUP_RETURN (-1);
2149 default:
2150 errno = EINVAL;
2151 return -1;
2153 /* NOTREACHED */
2155 # elif defined (ACE_VXWORKS)
2157 // Note that we must convert between absolute time (which is passed
2158 // as a parameter) and relative time (which is what the system call
2159 // expects).
2160 ACE_Time_Value relative_time = timeout.to_relative_time ();
2162 _Vx_freq_t const ticks_per_sec = ::sysClkRateGet ();
2164 int ticks = relative_time.sec() * ticks_per_sec +
2165 relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
2166 if (::semTake (*m, ticks) == ERROR)
2168 if (errno == S_objLib_OBJ_TIMEOUT)
2169 // Convert the VxWorks errno to one that's common for to ACE
2170 // platforms.
2171 errno = ETIME;
2172 else if (errno == S_objLib_OBJ_UNAVAILABLE)
2173 errno = EBUSY;
2174 return -1;
2176 else
2177 return 0;
2178 # endif /* ACE_HAS_PTHREADS */
2180 #else
2181 ACE_UNUSED_ARG (m);
2182 ACE_UNUSED_ARG (timeout);
2183 ACE_NOTSUP_RETURN (-1);
2184 #endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
2188 ACE_OS::mutex_trylock (ACE_mutex_t *m)
2190 ACE_OS_TRACE ("ACE_OS::mutex_trylock");
2191 #if defined (ACE_HAS_THREADS)
2192 # if defined (ACE_HAS_PTHREADS)
2193 // Note, don't use "::" here since the following call is often a macro.
2194 int result;
2195 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), result), int);
2196 # elif defined (ACE_HAS_WTHREADS)
2197 switch (m->type_)
2199 case USYNC_PROCESS:
2201 // Try for 0 milliseconds - i.e. nonblocking.
2202 switch (::WaitForSingleObject (m->proc_mutex_, 0))
2204 case WAIT_OBJECT_0:
2205 return 0;
2206 case WAIT_ABANDONED:
2207 // We will ignore abandonments in this method. Note that
2208 // we still hold the lock.
2209 return 0;
2210 case WAIT_TIMEOUT:
2211 errno = EBUSY;
2212 return -1;
2213 default:
2214 ACE_OS::set_errno_to_last_error ();
2215 return -1;
2218 case USYNC_THREAD:
2219 return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
2220 default:
2221 errno = EINVAL;
2222 return -1;
2224 /* NOTREACHED */
2225 # elif defined (ACE_VXWORKS)
2226 if (::semTake (*m, NO_WAIT) == ERROR)
2227 if (errno == S_objLib_OBJ_UNAVAILABLE)
2229 // couldn't get the semaphore
2230 errno = EBUSY;
2231 return -1;
2233 else
2234 // error
2235 return -1;
2236 else
2237 // got the semaphore
2238 return 0;
2239 # endif /* Threads variety case */
2240 #else
2241 ACE_UNUSED_ARG (m);
2242 ACE_NOTSUP_RETURN (-1);
2243 #endif /* ACE_HAS_THREADS */
2247 ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned)
2249 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2250 abandoned = 0;
2251 switch (m->type_)
2253 case USYNC_PROCESS:
2255 // Try for 0 milliseconds - i.e. nonblocking.
2256 switch (::WaitForSingleObject (m->proc_mutex_, 0))
2258 case WAIT_OBJECT_0:
2259 return 0;
2260 case WAIT_ABANDONED:
2261 abandoned = 1;
2262 return 0; // something goofed, but we hold the lock ...
2263 case WAIT_TIMEOUT:
2264 errno = EBUSY;
2265 return -1;
2266 default:
2267 ACE_OS::set_errno_to_last_error ();
2268 return -1;
2271 case USYNC_THREAD:
2272 return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
2273 default:
2274 errno = EINVAL;
2275 return -1;
2277 /* NOTREACHED */
2278 #else
2279 ACE_UNUSED_ARG (m);
2280 ACE_UNUSED_ARG (abandoned);
2281 ACE_NOTSUP_RETURN (-1);
2282 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2286 ACE_OS::mutex_unlock (ACE_mutex_t *m)
2288 ACE_OS_TRACE ("ACE_OS::mutex_unlock");
2289 #if defined (ACE_HAS_THREADS)
2290 # if defined (ACE_HAS_PTHREADS)
2291 // Note, don't use "::" here since the following call is often a macro.
2292 int result;
2293 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), result), int);
2294 # elif defined (ACE_HAS_WTHREADS)
2295 switch (m->type_)
2297 case USYNC_PROCESS:
2298 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_),
2299 ace_result_),
2300 int, -1);
2301 case USYNC_THREAD:
2302 return ACE_OS::thread_mutex_unlock (&m->thr_mutex_);
2303 default:
2304 errno = EINVAL;
2305 return -1;
2307 /* NOTREACHED */
2308 # elif defined (ACE_VXWORKS)
2309 return ::semGive (*m) == OK ? 0 : -1;
2310 # endif /* Threads variety case */
2311 #else
2312 ACE_UNUSED_ARG (m);
2313 ACE_NOTSUP_RETURN (-1);
2314 #endif /* ACE_HAS_THREADS */
2317 void
2318 ACE_OS::mutex_lock_cleanup (void *mutex)
2320 ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
2321 #if defined (ACE_HAS_THREADS)
2322 # if defined (ACE_HAS_PTHREADS)
2323 ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex;
2324 ACE_OS::mutex_unlock (p_lock);
2325 # else
2326 ACE_UNUSED_ARG (mutex);
2327 # endif /* ACE_HAS_PTHREADS */
2328 #else
2329 ACE_UNUSED_ARG (mutex);
2330 #endif /* ACE_HAS_THREADS */
2333 /*****************************************************************************/
2334 // MUTEXES END
2335 /*****************************************************************************/
2337 /*****************************************************************************/
2338 // EVENTS BEGIN
2339 /*****************************************************************************/
2341 #ifndef ACE_WIN32
2343 int ACE_event_t::lock ()
2345 # if !ACE_EVENT_USE_MUTEX_PSHARED
2346 if (this->eventdata_->type_ == USYNC_PROCESS)
2347 return ACE_OS::sema_wait (&this->lock_);
2348 # endif
2349 return ACE_OS::mutex_lock (&this->eventdata_->lock_);
2352 int ACE_event_t::unlock ()
2354 # if !ACE_EVENT_USE_MUTEX_PSHARED
2355 if (this->eventdata_->type_ == USYNC_PROCESS)
2356 return ACE_OS::sema_post (&this->lock_);
2357 # endif
2358 return ACE_OS::mutex_unlock (&this->eventdata_->lock_);
2361 int ACE_event_t::wake_one ()
2363 # if !ACE_EVENT_USE_COND_PSHARED
2364 if (this->eventdata_->type_ == USYNC_PROCESS)
2366 if (ACE_OS::sema_post (&this->semaphore_) != 0)
2367 return -1;
2369 else
2370 # endif
2371 if (ACE_OS::cond_signal (&this->eventdata_->condition_) != 0)
2372 return -1;
2373 return 0;
2376 #endif /* ACE_WIN32 */
2379 ACE_OS::event_destroy (ACE_event_t *event)
2381 #if defined (ACE_WIN32)
2382 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1);
2383 #elif defined (ACE_HAS_THREADS)
2384 if (!event->eventdata_)
2386 errno = EINVAL;
2387 return -1;
2390 // mutex_destroy()/cond_destroy() are called in a loop if the object
2391 // is BUSY. This avoids conditions where we fail to destroy these
2392 // objects because at time of destroy they were just being used in
2393 // another thread possibly causing deadlocks later on if they keep
2394 // being used after we're gone.
2396 if (event->eventdata_->type_ == USYNC_PROCESS)
2398 if (event->name_)
2400 int r1, r2;
2401 # if ACE_EVENT_USE_MUTEX_PSHARED
2402 // First destroy the mutex so locking after this will return
2403 // errors.
2404 while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
2405 && errno == EBUSY)
2406 ACE_OS::thr_yield ();
2407 # else
2408 r1 = ACE_OS::sema_destroy (&event->lock_);
2409 # endif
2411 # if ACE_EVENT_USE_COND_PSHARED
2412 // Now fix event to manual reset, raise signal and broadcast
2413 // until is's possible to destroy the condition.
2414 event->eventdata_->manual_reset_ = 1;
2415 while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_))
2416 == -1 && errno == EBUSY)
2418 event->eventdata_->is_signaled_ = 1;
2419 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2420 return -1;
2421 ACE_OS::thr_yield ();
2423 # else
2424 r2 = ACE_OS::sema_destroy (&event->semaphore_);
2425 # endif
2426 ACE_OS::munmap (event->eventdata_, sizeof (ACE_eventdata_t));
2427 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (event->name_));
2428 # if defined (ACE_HAS_ALLOC_HOOKS)
2429 ACE_Allocator::instance ()->free (event->name_);
2430 # else
2431 ACE_OS::free (event->name_);
2432 # endif /* ACE_HAS_ALLOC_HOOKS */
2433 return r1 != 0 || r2 != 0 ? -1 : 0;
2435 else // !name_ (not owned by this process)
2437 ACE_OS::munmap (event->eventdata_, sizeof (ACE_eventdata_t));
2439 # if !ACE_EVENT_USE_MUTEX_PSHARED
2440 ACE_OS::sema_destroy (&event->lock_);
2441 # endif
2443 # if !ACE_EVENT_USE_COND_PSHARED
2444 return ACE_OS::sema_destroy (&event->semaphore_);
2445 # endif
2448 else // USYNC_THREAD:
2450 int r1, r2;
2451 // First destroy the mutex so locking after this will return errors.
2452 while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
2453 && errno == EBUSY)
2454 ACE_OS::thr_yield ();
2456 // Now fix event to manual reset, raise signal and broadcast until
2457 // it's possible to destroy the condition.
2458 event->eventdata_->manual_reset_ = 1;
2459 while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
2460 && errno == EBUSY)
2462 event->eventdata_->is_signaled_ = 1;
2463 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2464 return -1;
2465 ACE_OS::thr_yield ();
2468 delete event->eventdata_;
2469 return r1 != 0 || r2 != 0 ? -1 : 0;
2472 return 0;
2473 #else
2474 ACE_UNUSED_ARG (event);
2475 ACE_NOTSUP_RETURN (-1);
2476 #endif /* ACE_WIN32 */
2479 ACE_ALLOC_HOOK_DEFINE (ACE_eventdata_t)
2481 #ifndef ACE_WIN32
2482 namespace {
2483 int eventdata_init (ACE_eventdata_t *evtdata, int type, int manual_reset,
2484 int initial_state, ACE_condattr_t *attributes,
2485 const char *name, void *arg, int init_condition = 1,
2486 int init_mutex = 1)
2488 evtdata->type_ = type;
2489 evtdata->manual_reset_ = manual_reset;
2490 evtdata->is_signaled_ = initial_state;
2491 evtdata->auto_event_signaled_ = false;
2492 evtdata->waiting_threads_ = 0;
2493 evtdata->signal_count_ = 0;
2495 if (init_condition)
2497 const int result = attributes ?
2498 ACE_OS::cond_init (&evtdata->condition_, *attributes, name, arg) :
2499 ACE_OS::cond_init (&evtdata->condition_, (short) type, name, arg);
2501 if (result != 0)
2502 return result;
2505 return init_mutex ? ACE_OS::mutex_init (&evtdata->lock_, type, name,
2506 (ACE_mutexattr_t *) arg) : 0;
2509 template <size_t N, size_t M>
2510 void format_name (char (&str)[N], const char *name, const char (&suffix)[M])
2512 ACE_OS::strncpy (str, name, N - M);
2513 ACE_OS::strcat (str, suffix);
2516 #endif /* ACE_WIN32 */
2519 ACE_OS::event_init (ACE_event_t *event,
2520 int type,
2521 ACE_condattr_t *attributes,
2522 int manual_reset,
2523 int initial_state,
2524 const char *name,
2525 void *arg,
2526 LPSECURITY_ATTRIBUTES sa)
2528 #if defined (ACE_WIN32)
2529 ACE_UNUSED_ARG (type);
2530 ACE_UNUSED_ARG (attributes);
2531 ACE_UNUSED_ARG (arg);
2532 SECURITY_ATTRIBUTES sa_buffer;
2533 SECURITY_DESCRIPTOR sd_buffer;
2534 *event = ::CreateEventA (ACE_OS::default_win32_security_attributes_r
2535 (sa, &sa_buffer, &sd_buffer),
2536 manual_reset,
2537 initial_state,
2538 name);
2539 if (*event == 0)
2540 ACE_FAIL_RETURN (-1);
2541 else
2543 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
2544 ACE_OS::set_errno_to_last_error ();
2545 return 0;
2547 #elif defined (ACE_HAS_THREADS)
2548 ACE_UNUSED_ARG (sa);
2549 event->name_ = 0;
2550 event->eventdata_ = 0;
2552 if (type == USYNC_PROCESS)
2554 const char *name_p = name;
2555 bool owner = false;
2556 // Let's see if the shared memory entity already exists.
2557 ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
2558 O_RDWR | O_CREAT | O_EXCL,
2559 ACE_DEFAULT_FILE_PERMS);
2560 if (fd == ACE_INVALID_HANDLE)
2562 if (errno == EEXIST)
2563 fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
2564 O_RDWR | O_CREAT,
2565 ACE_DEFAULT_FILE_PERMS);
2566 if (fd == ACE_INVALID_HANDLE) // Still can't get it.
2567 return -1;
2569 else
2571 // We own this shared memory object! Let's set its size.
2572 if (ACE_OS::ftruncate (fd, sizeof (ACE_eventdata_t)) == -1)
2574 ACE_OS::close (fd);
2575 return -1;
2577 owner = true;
2580 void *const mapped = ACE_OS::mmap (0, sizeof (ACE_eventdata_t),
2581 PROT_RDWR, MAP_SHARED, fd);
2582 ACE_eventdata_t *evtdata = reinterpret_cast<ACE_eventdata_t *> (mapped);
2583 ACE_OS::close (fd);
2584 if (evtdata == MAP_FAILED)
2586 if (owner)
2587 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2588 return -1;
2591 event->eventdata_ = evtdata;
2593 if (owner)
2595 event->name_ = ACE_OS::strdup (name_p);
2596 if (event->name_ == 0 ||
2597 eventdata_init (event->eventdata_, USYNC_PROCESS, manual_reset,
2598 initial_state, attributes, name, arg,
2599 ACE_EVENT_USE_COND_PSHARED,
2600 ACE_EVENT_USE_MUTEX_PSHARED) != 0)
2602 ACE_OS::munmap (evtdata, sizeof (ACE_eventdata_t));
2603 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2604 return -1;
2608 int result = 0;
2609 # if !ACE_EVENT_USE_COND_PSHARED
2610 char sem_name[128] = {};
2611 format_name (sem_name, name, "._ACE_EVTSEM_");
2612 result = ACE_OS::sema_init (&event->semaphore_, 0, type, attributes,
2613 sem_name, arg);
2614 # endif
2616 # if !ACE_EVENT_USE_MUTEX_PSHARED
2617 if (result == 0)
2619 char lck_name[128] = {};
2620 format_name (lck_name, name, "._ACE_EVTLCK_");
2621 result = ACE_OS::sema_init (&event->lock_, owner, type, attributes,
2622 lck_name, arg);
2624 # endif
2626 # if !ACE_EVENT_USE_COND_PSHARED || !ACE_EVENT_USE_MUTEX_PSHARED
2627 if (result != 0 && owner)
2628 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2629 # endif
2631 return result;
2633 else
2635 ACE_NEW_RETURN (event->eventdata_, ACE_eventdata_t, -1);
2636 return eventdata_init (event->eventdata_, USYNC_THREAD, manual_reset,
2637 initial_state, attributes, name, arg);
2639 #else
2640 ACE_UNUSED_ARG (event);
2641 ACE_UNUSED_ARG (manual_reset);
2642 ACE_UNUSED_ARG (initial_state);
2643 ACE_UNUSED_ARG (type);
2644 ACE_UNUSED_ARG (attributes);
2645 ACE_UNUSED_ARG (name);
2646 ACE_UNUSED_ARG (arg);
2647 ACE_UNUSED_ARG (sa);
2648 ACE_NOTSUP_RETURN (-1);
2649 #endif /* ACE_WIN32 */
2653 ACE_OS::event_pulse (ACE_event_t *event)
2655 #if defined (ACE_WIN32)
2656 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), ace_result_), int, -1);
2657 #elif defined (ACE_HAS_THREADS)
2658 int error = 0;
2659 int result = event->lock ();
2660 if (result != 0)
2661 return result;
2663 if (event->eventdata_->waiting_threads_ > 0)
2665 if (event->eventdata_->manual_reset_ == 1)
2667 // Wakeup all waiters.
2668 # if !ACE_EVENT_USE_COND_PSHARED
2669 if (event->eventdata_->type_ == USYNC_PROCESS)
2671 event->eventdata_->signal_count_ =
2672 event->eventdata_->waiting_threads_;
2673 for (unsigned long i = 0;
2674 i < event->eventdata_->signal_count_; ++i)
2675 if (ACE_OS::sema_post (&event->semaphore_) != 0)
2677 event->eventdata_->signal_count_ = 0;
2678 result = -1;
2679 error = errno;
2682 if (result == 0)
2683 while (event->eventdata_->signal_count_ != 0 &&
2684 event->eventdata_->waiting_threads_ != 0)
2685 ACE_OS::thr_yield ();
2687 else
2688 #endif
2689 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2691 result = -1;
2692 error = errno;
2694 else
2695 event->eventdata_->signal_count_ =
2696 event->eventdata_->waiting_threads_;
2698 else // Auto-reset event: wakeup one waiter.
2700 if (event->wake_one () != 0)
2702 result = -1;
2703 error = errno;
2706 event->eventdata_->auto_event_signaled_ = true;
2710 event->eventdata_->is_signaled_ = 0;
2712 if (event->unlock () != 0)
2713 return -1;
2715 if (result == -1)
2716 errno = error;
2718 return result;
2719 #else
2720 ACE_UNUSED_ARG (event);
2721 ACE_NOTSUP_RETURN (-1);
2722 #endif /* ACE_WIN32 */
2726 ACE_OS::event_reset (ACE_event_t *event)
2728 #if defined (ACE_WIN32)
2729 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1);
2730 #elif defined (ACE_HAS_THREADS)
2731 if (event->lock () != 0)
2732 return -1;
2734 event->eventdata_->is_signaled_ = 0;
2735 event->eventdata_->auto_event_signaled_ = false;
2737 return event->unlock ();
2738 #else
2739 ACE_UNUSED_ARG (event);
2740 ACE_NOTSUP_RETURN (-1);
2741 #endif /* ACE_WIN32 */
2745 ACE_OS::event_signal (ACE_event_t *event)
2747 #if defined (ACE_WIN32)
2748 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1);
2749 #elif defined (ACE_HAS_THREADS)
2750 int error = 0;
2751 int result = event->lock ();
2753 if (result != 0)
2754 return result;
2756 if (event->eventdata_->manual_reset_ == 1)
2758 // wakeup all
2759 # if !ACE_EVENT_USE_COND_PSHARED
2760 if (event->eventdata_->type_ == USYNC_PROCESS)
2762 if (ACE_OS::sema_post (&event->semaphore_) != 0)
2764 result = -1;
2765 error = errno;
2768 else
2769 #endif
2770 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2772 result = -1;
2773 error = errno;
2776 if (result == 0)
2777 event->eventdata_->is_signaled_ = 1;
2779 else // Auto-reset event
2781 if (event->eventdata_->waiting_threads_ == 0)
2782 event->eventdata_->is_signaled_ = 1;
2783 else if (event->wake_one () != 0)
2785 result = -1;
2786 error = errno;
2789 event->eventdata_->auto_event_signaled_ = true;
2792 if (event->unlock () != 0)
2793 return -1;
2795 if (result == -1)
2796 errno = error;
2798 return result;
2799 #else
2800 ACE_UNUSED_ARG (event);
2801 ACE_NOTSUP_RETURN (-1);
2802 #endif /* ACE_WIN32 */
2806 ACE_OS::event_timedwait (ACE_event_t *event,
2807 ACE_Time_Value *timeout,
2808 int use_absolute_time)
2810 #if defined (ACE_WIN32)
2811 DWORD result;
2813 if (timeout && *timeout == ACE_Time_Value::zero)
2814 // Do a "poll".
2815 result = ::WaitForSingleObject (*event, 0);
2816 else
2818 // Wait for upto <relative_time> number of milliseconds. Note
2819 // that we must convert between absolute time (which is passed
2820 // as a parameter) and relative time (which is what
2821 // WaitForSingleObjects() expects).
2822 // <timeout> parameter is given in absolute or relative value
2823 // depending on parameter <use_absolute_time>.
2824 int msec_timeout = 0;
2825 if (!timeout)
2827 msec_timeout = INFINITE;
2829 else if (use_absolute_time)
2831 // Time is given in absolute time, we should use
2832 // gettimeofday() to calculate relative time
2833 ACE_Time_Value relative_time = timeout->to_relative_time ();
2835 // Watchout for situations where a context switch has caused
2836 // the current time to be > the timeout. Thanks to Norbert
2837 // Rapp <NRapp@nexus-informatics.de> for pointing this.
2838 if (relative_time > ACE_Time_Value::zero)
2839 msec_timeout = relative_time.msec ();
2841 else
2842 // time is given in relative time, just convert it into
2843 // milliseconds and use it
2844 msec_timeout = timeout->msec ();
2845 result = ::WaitForSingleObject (*event, msec_timeout);
2848 switch (result)
2850 case WAIT_OBJECT_0:
2851 return 0;
2852 case WAIT_TIMEOUT:
2853 errno = ETIME;
2854 return -1;
2855 default:
2856 // This is a hack, we need to find an appropriate mapping...
2857 ACE_OS::set_errno_to_last_error ();
2858 return -1;
2860 #elif defined (ACE_HAS_THREADS)
2861 int error = 0;
2862 int result = event->lock ();
2864 if (result != 0)
2865 return result;
2867 if (event->eventdata_->is_signaled_ == 1)
2869 if (event->eventdata_->manual_reset_ == 0)
2871 // AUTO: reset state
2872 event->eventdata_->is_signaled_ = 0;
2873 event->eventdata_->auto_event_signaled_ = false;
2876 else // event is currently not signaled
2878 ++event->eventdata_->waiting_threads_;
2880 ACE_Time_Value *absolute_timeout = timeout, converted_time;
2882 // cond_timedwait() expects absolute time, check <use_absolute_time> flag
2883 if (timeout && use_absolute_time == 0)
2885 converted_time = timeout->to_absolute_time ();
2886 absolute_timeout = &converted_time;
2889 while (event->eventdata_->is_signaled_ == 0 &&
2890 !event->eventdata_->auto_event_signaled_)
2891 # if !ACE_EVENT_USE_COND_PSHARED
2892 if (event->eventdata_->type_ == USYNC_PROCESS)
2894 if (event->unlock () != 0)
2896 --event->eventdata_->waiting_threads_;
2897 return -1;
2900 if (ACE_OS::sema_wait (&event->semaphore_, absolute_timeout) != 0)
2902 result = -1;
2903 error = (errno == ETIMEDOUT) // Semaphores use ETIMEDOUT (POSIX)
2904 ? ETIME : errno;
2907 bool signalled = false;
2908 if (result == 0 && event->eventdata_->signal_count_ > 0)
2910 --event->eventdata_->signal_count_;
2911 signalled = true;
2914 if (event->lock () != 0)
2916 --event->eventdata_->waiting_threads_;
2917 return -1;
2920 if (result != 0)
2921 break;
2923 if (event->eventdata_->manual_reset_ == 1 &&
2924 event->eventdata_->is_signaled_ == 1 &&
2925 ACE_OS::sema_post (&event->semaphore_) != 0)
2927 result = -1;
2928 error = errno;
2929 break;
2932 if (signalled)
2933 break;
2935 else
2936 #endif
2938 if (ACE_OS::cond_timedwait (&event->eventdata_->condition_,
2939 &event->eventdata_->lock_,
2940 absolute_timeout) != 0)
2942 result = -1;
2943 error = errno;
2944 break;
2947 if (event->eventdata_->signal_count_ > 0)
2949 --event->eventdata_->signal_count_;
2950 break;
2954 // Reset the auto_event_signaled_ to false now that we have woken up.
2955 if (event->eventdata_->auto_event_signaled_)
2956 event->eventdata_->auto_event_signaled_ = false;
2958 --event->eventdata_->waiting_threads_;
2961 if (event->unlock () != 0)
2962 return -1;
2964 if (result == -1)
2965 errno = error;
2967 return result;
2968 #else
2969 ACE_UNUSED_ARG (event);
2970 ACE_UNUSED_ARG (timeout);
2971 ACE_UNUSED_ARG (use_absolute_time);
2972 ACE_NOTSUP_RETURN (-1);
2973 #endif /* ACE_WIN32 */
2976 /*****************************************************************************/
2977 // EVENTS END
2978 /*****************************************************************************/
2981 ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params)
2983 ACE_UNUSED_ARG (sched_params);
2984 ACE_NOTSUP_RETURN (-1);
2988 ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params)
2990 ACE_UNUSED_ARG (sched_params);
2991 ACE_NOTSUP_RETURN (-1);
2994 #if defined ACE_HAS_THREADS && defined ACE_LACKS_RWLOCK_T
2995 namespace {
2996 struct UniqueName {
2997 UniqueName (int type, const void *addr)
2999 #ifdef ACE_WIN32
3000 if (type == USYNC_THREAD)
3002 this->named_ = false;
3003 return;
3005 this->named_ = true;
3006 #else
3007 ACE_UNUSED_ARG (type);
3008 #endif
3009 ACE_OS::unique_name (addr, &this->buffer_[0], ACE_UNIQUE_NAME_LEN);
3012 operator const ACE_TCHAR * () const
3014 #ifdef ACE_WIN32
3015 if (!this->named_)
3017 return 0;
3019 #endif
3020 return &this->buffer_[0];
3023 ACE_TCHAR buffer_[ACE_UNIQUE_NAME_LEN];
3024 #ifdef ACE_WIN32
3025 bool named_;
3026 #endif
3029 enum RWLockCleanup {RWLC_CondAttr, RWLC_Lock, RWLC_CondReaders, RWLC_CondWriters};
3031 struct RWLockCleaner {
3032 RWLockCleaner (ACE_condattr_t &attr, ACE_rwlock_t *rw)
3033 : state_ (RWLC_CondAttr)
3034 , attr_ (attr)
3035 , rw_ (rw)
3038 ~RWLockCleaner ()
3040 ACE_Errno_Guard error (errno);
3041 switch (this->state_)
3043 case RWLC_CondWriters:
3044 ACE_OS::cond_destroy (&this->rw_->waiting_writers_);
3045 ACE_FALLTHROUGH;
3046 case RWLC_CondReaders:
3047 ACE_OS::cond_destroy (&this->rw_->waiting_readers_);
3048 ACE_FALLTHROUGH;
3049 case RWLC_Lock:
3050 ACE_OS::mutex_destroy (&this->rw_->lock_);
3051 ACE_FALLTHROUGH;
3052 case RWLC_CondAttr:
3053 ACE_OS::condattr_destroy (this->attr_);
3057 RWLockCleanup state_;
3058 ACE_condattr_t &attr_;
3059 ACE_rwlock_t *rw_;
3062 #endif
3064 #if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T)
3066 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
3067 int type,
3068 const ACE_TCHAR *,
3069 void *arg)
3071 // ACE_OS_TRACE ("ACE_OS::rwlock_init");
3072 # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
3073 // NT, POSIX, and VxWorks don't support this natively.
3075 ACE_condattr_t attributes;
3076 if (ACE_OS::condattr_init (attributes, type) != 0)
3077 return -1;
3079 RWLockCleaner cleanup (attributes, rw);
3081 if (ACE_OS::mutex_init (&rw->lock_, type, UniqueName (type, &rw->lock_),
3082 (ACE_mutexattr_t *) arg) != 0)
3083 return -1;
3085 cleanup.state_ = RWLC_Lock;
3086 if (ACE_OS::cond_init (&rw->waiting_readers_, attributes,
3087 UniqueName (type, &rw->waiting_readers_), arg) != 0)
3088 return -1;
3090 cleanup.state_ = RWLC_CondReaders;
3091 if (ACE_OS::cond_init (&rw->waiting_writers_, attributes,
3092 UniqueName (type, &rw->waiting_writers_), arg) != 0)
3093 return -1;
3095 cleanup.state_ = RWLC_CondWriters;
3096 if (ACE_OS::cond_init (&rw->waiting_important_writer_, attributes,
3097 UniqueName (type, &rw->waiting_important_writer_),
3098 arg) != 0)
3099 return -1;
3101 cleanup.state_ = RWLC_CondAttr;
3102 rw->ref_count_ = 0;
3103 rw->num_waiting_writers_ = 0;
3104 rw->num_waiting_readers_ = 0;
3105 rw->important_writer_ = false;
3106 return 0;
3107 # else
3108 ACE_UNUSED_ARG (rw);
3109 ACE_UNUSED_ARG (type);
3110 ACE_UNUSED_ARG (arg);
3111 ACE_NOTSUP_RETURN (-1);
3112 # endif /* ACE_HAS_THREADS */
3114 #endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
3117 ACE_OS::sched_params (const ACE_Sched_Params &sched_params,
3118 ACE_id_t id)
3120 ACE_OS_TRACE ("ACE_OS::sched_params");
3121 #if defined (ACE_HAS_PTHREADS) && \
3122 (!defined (ACE_LACKS_SETSCHED) || \
3123 defined (ACE_HAS_PTHREAD_SCHEDPARAM))
3124 if (sched_params.quantum () != ACE_Time_Value::zero)
3126 // quantums not supported
3127 errno = EINVAL;
3128 return -1;
3131 // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
3132 // providing this code for 1003.1c PThreads. Please note that this
3133 // has only been tested for POSIX 1003.1c threads, and may cause
3134 // problems with other PThreads flavors!
3136 struct sched_param param;
3137 param.sched_priority = sched_params.priority ();
3139 if (sched_params.scope () == ACE_SCOPE_PROCESS)
3141 # if defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3142 ACE_UNUSED_ARG (id);
3143 ACE_NOTSUP_RETURN (-1);
3144 # else /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3145 int result = ::sched_setscheduler (id == ACE_SELF ? 0 : id,
3146 sched_params.policy (),
3147 &param) == -1 ? -1 : 0;
3148 return result;
3149 # endif /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3151 else if (sched_params.scope () == ACE_SCOPE_THREAD)
3153 ACE_thread_t thr_id = ACE_OS::thr_self ();
3155 int result;
3156 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
3157 sched_params.policy (),
3158 &param),
3159 result),
3160 int);
3162 else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
3164 errno = EINVAL;
3165 return -1;
3168 #elif defined (ACE_WIN32)
3169 if (sched_params.scope () == ACE_SCOPE_THREAD)
3171 // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
3172 // a VERY BAD THING. This include guard will allow people
3173 // to easily disable this feature in ACE.
3174 #if !defined (ACE_DISABLE_WIN32_INCREASE_PRIORITY)
3175 // Set the priority class of this process to the REALTIME process class
3176 // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL.
3177 if (!::SetPriorityClass (::GetCurrentProcess (),
3178 (sched_params.policy () == ACE_SCHED_FIFO ||
3179 sched_params.policy () == ACE_SCHED_RR)
3180 ? REALTIME_PRIORITY_CLASS
3181 : NORMAL_PRIORITY_CLASS))
3183 ACE_OS::set_errno_to_last_error ();
3184 return -1;
3186 #endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
3188 // Now that we have set the priority class of the process, set the
3189 // priority of the current thread to the desired value.
3190 return ACE_OS::thr_setprio (sched_params.priority ());
3192 else if (sched_params.scope () == ACE_SCOPE_PROCESS)
3194 HANDLE hProcess
3195 = ::OpenProcess (PROCESS_SET_INFORMATION,
3196 FALSE,
3197 id == ACE_SELF ? ::GetCurrentProcessId() : id);
3198 if (!hProcess)
3200 ACE_OS::set_errno_to_last_error();
3201 return -1;
3203 // There is no way for us to set the priority of the thread when we
3204 // are setting the priority of a different process. So just ignore
3205 // the priority argument when ACE_SCOPE_PROCESS is specified.
3206 // Setting the priority class will automatically increase the base
3207 // priority of all the threads within a process while maintaining the
3208 // relative priorities of the threads within it.
3209 if (!::SetPriorityClass (hProcess,
3210 (sched_params.policy () == ACE_SCHED_FIFO ||
3211 sched_params.policy () == ACE_SCHED_RR)
3212 ? REALTIME_PRIORITY_CLASS
3213 : NORMAL_PRIORITY_CLASS))
3215 ACE_OS::set_errno_to_last_error ();
3216 ::CloseHandle (hProcess);
3217 return -1;
3219 ::CloseHandle (hProcess);
3220 return 0;
3222 else
3224 errno = EINVAL;
3225 return -1;
3227 #elif defined (ACE_VXWORKS)
3228 ACE_UNUSED_ARG (id);
3230 // There is only one class of priorities on VxWorks, and no time
3231 // quanta. So, just set the current thread's priority.
3233 if (sched_params.policy () != ACE_SCHED_FIFO
3234 || sched_params.scope () != ACE_SCOPE_PROCESS
3235 || sched_params.quantum () != ACE_Time_Value::zero)
3237 errno = EINVAL;
3238 return -1;
3241 // Set the thread priority on the current thread.
3242 return ACE_OS::thr_setprio (sched_params.priority ());
3243 #else
3244 ACE_UNUSED_ARG (sched_params);
3245 ACE_UNUSED_ARG (id);
3246 ACE_NOTSUP_RETURN (-1);
3247 #endif /* ACE_HAS_PTHREADS */
3251 ACE_OS::scheduling_class (const char */*class_name*/, ACE_id_t &/*id*/)
3253 ACE_NOTSUP_RETURN (-1);
3257 ACE_OS::set_scheduling_params (const ACE_Sched_Params &/*sched_params*/, ACE_id_t /*id*/)
3259 ACE_NOTSUP_RETURN (-1);
3263 ACE_OS::thr_create (ACE_THR_FUNC func,
3264 void *args,
3265 long flags,
3266 ACE_thread_t *thr_id,
3267 ACE_hthread_t *thr_handle,
3268 long priority,
3269 void *stack,
3270 size_t stacksize,
3271 ACE_Base_Thread_Adapter *thread_adapter,
3272 const char** thr_name)
3274 ACE_OS_TRACE ("ACE_OS::thr_create");
3276 if (ACE_BIT_DISABLED (flags, THR_DETACHED) &&
3277 ACE_BIT_DISABLED (flags, THR_JOINABLE))
3278 ACE_SET_BITS (flags, THR_JOINABLE);
3280 #if defined (ACE_NO_THREAD_ADAPTER)
3281 # define ACE_THREAD_FUNCTION func
3282 # define ACE_THREAD_ARGUMENT args
3283 #else /* ! defined (ACE_NO_THREAD_ADAPTER) */
3284 # define ACE_THREAD_FUNCTION thread_args->entry_point ()
3285 # define ACE_THREAD_ARGUMENT thread_args
3286 #endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
3288 ACE_Base_Thread_Adapter *thread_args = 0;
3289 if (thread_adapter == 0)
3290 #if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
3291 ACE_NEW_RETURN (thread_args,
3292 ACE_OS_Thread_Adapter (func, args,
3293 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
3294 ACE_OS_Object_Manager::seh_except_selector(),
3295 ACE_OS_Object_Manager::seh_except_handler(),
3296 flags),
3297 -1);
3298 #else
3299 ACE_NEW_RETURN (thread_args,
3300 ACE_OS_Thread_Adapter (func, args,
3301 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
3302 flags),
3303 -1);
3305 #endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
3306 else
3307 thread_args = thread_adapter;
3309 std::unique_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
3311 if (thread_adapter == 0)
3312 auto_thread_args.reset (thread_args);
3314 #if defined (ACE_HAS_THREADS)
3316 // *** Set Stack Size
3317 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3318 if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3319 stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
3320 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
3322 ACE_thread_t tmp_thr;
3323 if (thr_id == 0)
3324 thr_id = &tmp_thr;
3326 ACE_hthread_t tmp_handle;
3327 if (thr_handle == 0)
3328 thr_handle = &tmp_handle;
3330 # if defined (ACE_HAS_PTHREADS)
3331 int result;
3332 # if defined (ACE_PTHREAD_ATTR_T_INITIALIZE)
3333 /* Tests show that VxWorks 6.x pthread lib does not only
3334 * require zeroing of mutex/condition objects to function correctly
3335 * but also of the attribute objects.
3337 pthread_attr_t attr = {0};
3338 # else
3339 pthread_attr_t attr;
3340 # endif
3341 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr), result) != 0)
3342 return -1;
3344 if (stacksize != 0)
3346 size_t size = stacksize;
3348 # if defined (PTHREAD_STACK_MIN)
3349 if (size < static_cast <size_t> (PTHREAD_STACK_MIN))
3350 size = PTHREAD_STACK_MIN;
3351 # endif /* PTHREAD_STACK_MIN */
3353 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
3354 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3355 int result;
3356 if (stack != 0)
3357 result = ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr, stack, size), result);
3358 else
3359 result = ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result);
3360 if (result == -1)
3361 # else
3362 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result) == -1)
3363 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3365 ::pthread_attr_destroy (&attr);
3366 return -1;
3368 # else
3369 ACE_UNUSED_ARG (size);
3370 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
3373 // *** Set Stack Address
3374 # if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3375 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
3376 if (stack != 0)
3378 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr, stack), result) != 0)
3380 ::pthread_attr_destroy (&attr);
3381 return -1;
3384 # else
3385 ACE_UNUSED_ARG (stack);
3386 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3387 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3389 // *** Deal with various attributes
3390 if (flags != 0)
3392 // *** Set Detach state
3393 # if !defined (ACE_LACKS_SETDETACH)
3394 if (ACE_BIT_ENABLED (flags, THR_DETACHED)
3395 || ACE_BIT_ENABLED (flags, THR_JOINABLE))
3397 int dstate = PTHREAD_CREATE_JOINABLE;
3399 if (ACE_BIT_ENABLED (flags, THR_DETACHED))
3400 dstate = PTHREAD_CREATE_DETACHED;
3402 if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
3403 result) != 0)
3405 ::pthread_attr_destroy (&attr);
3406 return -1;
3410 // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
3411 // call ::pthread_detach () below. If THR_DETACHED is not
3412 // enabled, we call ::pthread_detach () in the Thread_Manager,
3413 // after joining with the thread.
3414 # endif /* ACE_LACKS_SETDETACH */
3416 // *** Set Policy
3417 # if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3418 // If we wish to set the priority explicitly, we have to enable
3419 // explicit scheduling, and a policy, too.
3420 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3422 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3423 if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
3424 && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
3425 && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
3426 ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
3429 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3430 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3431 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3433 int spolicy;
3435 # if defined (ACE_HAS_ONLY_SCHED_OTHER)
3436 // SunOS, thru version 5.6, only supports SCHED_OTHER.
3437 spolicy = SCHED_OTHER;
3438 # else
3439 // Make sure to enable explicit scheduling, in case we didn't
3440 // enable it above (for non-default priority).
3441 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3443 if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3444 spolicy = SCHED_OTHER;
3445 else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3446 spolicy = SCHED_FIFO;
3447 # if defined (SCHED_IO)
3448 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3449 spolicy = SCHED_IO;
3450 # else
3451 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3453 errno = ENOSYS;
3454 return -1;
3456 # endif /* SCHED_IO */
3457 else
3458 spolicy = SCHED_RR;
3460 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3462 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
3463 result);
3464 if (result != 0)
3466 ::pthread_attr_destroy (&attr);
3467 return -1;
3471 // *** Set Priority (use reasonable default priorities)
3472 # if defined(ACE_HAS_PTHREADS)
3473 // If we wish to explicitly set a scheduling policy, we also
3474 // have to specify a priority. We choose a "middle" priority as
3475 // default. Maybe this is also necessary on other POSIX'ish
3476 // implementations?
3477 if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3478 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3479 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3480 && priority == ACE_DEFAULT_THREAD_PRIORITY)
3482 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3483 priority = ACE_THR_PRI_FIFO_DEF;
3484 else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
3485 priority = ACE_THR_PRI_RR_DEF;
3486 else // THR_SCHED_DEFAULT
3487 priority = ACE_THR_PRI_OTHER_DEF;
3489 # endif /* ACE_HAS_PTHREADS */
3490 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3492 struct sched_param sparam;
3493 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
3495 # if defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
3496 /* For MIT pthreads... */
3497 sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
3498 # elif defined(ACE_HAS_PTHREADS)
3499 // The following code forces priority into range.
3500 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3501 sparam.sched_priority =
3502 ACE_MIN (ACE_THR_PRI_FIFO_MAX,
3503 ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
3504 else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
3505 sparam.sched_priority =
3506 ACE_MIN (ACE_THR_PRI_RR_MAX,
3507 ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
3508 else // Default policy, whether set or not
3509 sparam.sched_priority =
3510 ACE_MIN (ACE_THR_PRI_OTHER_MAX,
3511 ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
3512 # elif defined (PRIORITY_MAX)
3513 sparam.sched_priority = ACE_MIN (priority,
3514 (long) PRIORITY_MAX);
3515 # else
3516 sparam.sched_priority = priority;
3517 # endif /* PTHREAD_MAX_PRIORITY */
3520 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
3521 result);
3522 if (result != 0)
3524 ::pthread_attr_destroy (&attr);
3525 return -1;
3530 # if !defined (ACE_LACKS_SETINHERITSCHED)
3531 // *** Set scheduling explicit or inherited
3532 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
3533 || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
3535 int sched = PTHREAD_EXPLICIT_SCHED;
3536 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
3537 sched = PTHREAD_INHERIT_SCHED;
3538 if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr, sched), result) != 0)
3540 ::pthread_attr_destroy (&attr);
3541 return -1;
3544 # endif /* ACE_LACKS_SETINHERITSCHED */
3545 # else /* ACE_LACKS_SETSCHED */
3546 ACE_UNUSED_ARG (priority);
3547 # endif /* ACE_LACKS_SETSCHED */
3549 // *** Set pthread name
3550 # if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3551 if (thr_name && *thr_name)
3553 if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr, const_cast<char*>(*thr_name)), result) != 0)
3555 ::pthread_attr_destroy (&attr);
3556 return -1;
3559 # endif /* ACE_HAS_PTHREAD_ATTR_SETNAME */
3561 // *** Set Scope
3562 # if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
3563 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
3564 || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
3566 # if defined (ACE_LACKS_PTHREAD_SCOPE_PROCESS)
3567 int scope = PTHREAD_SCOPE_SYSTEM;
3568 # else /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3569 int scope = PTHREAD_SCOPE_PROCESS;
3570 # endif /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3571 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
3572 scope = PTHREAD_SCOPE_SYSTEM;
3574 if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr, scope), result) != 0)
3576 ::pthread_attr_destroy (&attr);
3577 return -1;
3580 # endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
3582 # ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
3583 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED))
3585 if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr), result) != 0)
3587 ::pthread_attr_destroy (&attr);
3588 return -1;
3591 # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
3593 if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
3595 // Increment the number of LWPs by one to emulate the
3596 // SunOS semantics.
3597 int lwps = ACE_OS::thr_getconcurrency ();
3598 if (lwps == -1)
3600 if (errno == ENOTSUP)
3601 // Suppress the ENOTSUP because it's harmless.
3602 errno = 0;
3603 else
3604 // This should never happen on SunOS:
3605 // ::thr_getconcurrency () should always succeed.
3606 return -1;
3608 else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
3610 if (errno == ENOTSUP)
3612 // Unlikely: ::thr_getconcurrency () is supported
3613 // but ::thr_setconcurrency () is not?
3615 else
3616 return -1;
3621 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
3622 &attr,
3623 thread_args->entry_point (),
3624 thread_args),
3625 result),
3626 int, result);
3627 ::pthread_attr_destroy (&attr);
3629 // This is a SunOS or POSIX implementation of pthreads, where we
3630 // assume that ACE_thread_t and ACE_hthread_t are the same. If this
3631 // *isn't* correct on some platform, please let us know.
3632 if (result != -1)
3633 *thr_handle = *thr_id;
3635 auto_thread_args.release ();
3637 // *** Set pthread name (second try)
3638 # if !defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3639 # if defined (ACE_HAS_PTHREAD_SETNAME_NP)
3640 if (thr_name && *thr_name)
3642 ACE_OSCALL (ACE_ADAPT_RETVAL(::pthread_setname_np (*thr_id, *thr_name),
3643 result),
3644 int,
3645 result);
3647 # else
3648 ACE_UNUSED_ARG (thr_name);
3649 # endif /* ACE_HAS_PTHREAD_SETNAME_NP */
3650 # endif /* !ACE_HAS_PTHREAD_ATTR_SETNAME */
3652 return result;
3653 # elif defined (ACE_HAS_WTHREADS)
3654 ACE_UNUSED_ARG (thr_name);
3655 ACE_UNUSED_ARG (stack);
3656 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
3657 if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
3659 CWinThread *cwin_thread =
3660 ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
3661 thread_args,
3662 priority,
3664 flags | THR_SUSPENDED);
3665 // Have to duplicate the handle because
3666 // CWinThread::~CWinThread() closes the original handle.
3667 (void) ::DuplicateHandle (::GetCurrentProcess (),
3668 cwin_thread->m_hThread,
3669 ::GetCurrentProcess (),
3670 thr_handle,
3672 TRUE,
3673 DUPLICATE_SAME_ACCESS);
3674 *thr_id = cwin_thread->m_nThreadID;
3676 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
3677 cwin_thread->ResumeThread ();
3678 // cwin_thread will be deleted in AfxThreadExit()
3679 // Warning: If AfxThreadExit() is called from within the
3680 // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
3682 else
3683 # endif /* ACE_HAS_MFC */
3685 int const start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
3687 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3688 // If we need to set the priority, then we need to start the
3689 // thread in a suspended mode.
3690 ACE_SET_BITS (flags, THR_SUSPENDED);
3692 *thr_handle = (void *) ACE_BEGINTHREADEX (0,
3693 static_cast <u_int> (stacksize),
3694 thread_args->entry_point (),
3695 thread_args,
3696 flags,
3697 thr_id);
3699 if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
3701 // Set the priority of the new thread and then let it
3702 // continue, but only if the user didn't start it suspended
3703 // in the first place!
3704 if (ACE_OS::thr_setprio (*thr_handle, priority) != 0)
3706 return -1;
3709 if (start_suspended == 0)
3711 ACE_OS::thr_continue (*thr_handle);
3716 // Close down the handle if no one wants to use it.
3717 if (thr_handle == &tmp_handle && tmp_handle != 0)
3718 ::CloseHandle (tmp_handle);
3720 if (*thr_handle != 0)
3722 auto_thread_args.release ();
3723 return 0;
3725 else
3726 ACE_FAIL_RETURN (-1);
3727 /* NOTREACHED */
3729 # elif defined (ACE_VXWORKS)
3730 // The hard-coded values below are what ::sp () would use. (::sp ()
3731 // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
3732 // 20,000.) stacksize should be an even integer. If a stack is not
3733 // specified, ::taskSpawn () is used so that we can set the
3734 // priority, flags, and stacksize. If a stack is specified,
3735 // ::taskInit ()/::taskActivate() are used.
3737 // If called with thr_create() defaults, use same default values as ::sp ():
3738 if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
3739 // Assumes that there is a floating point coprocessor. As noted
3740 // above, ::sp () hardcodes this, so we should be safe with it.
3741 if (flags == 0) flags = VX_FP_TASK;
3742 if (stacksize == 0) stacksize = 20000;
3744 ACE_thread_t tid;
3745 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
3746 if (stack == 0)
3748 # else
3749 ACE_UNUSED_ARG (stack);
3750 # endif /* 0 */
3751 // The call below to ::taskSpawn () causes VxWorks to assign a
3752 // unique task name of the form: "t" + an integer, because the
3753 // first argument is 0.
3754 tid = ::taskSpawn (thr_name && *thr_name ? const_cast <char*> (*thr_name) : 0,
3755 priority,
3756 (int) flags,
3757 stacksize,
3758 thread_args->entry_point (),
3759 (ACE_VX_USR_ARG_T) thread_args,
3760 0, 0, 0, 0, 0, 0, 0, 0, 0);
3761 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
3763 else
3765 // If a task name (thr_id) was not supplied, then the task will
3766 // not have a unique name. That's VxWorks' behavior.
3768 // Carve out a TCB at the beginning of the stack space. The TCB
3769 // occupies 400 bytes with VxWorks 5.3.1/I386.
3770 WIND_TCB *tcb = (WIND_TCB *) stack;
3772 // The TID is defined to be the address of the TCB.
3773 int status = ::taskInit (tcb,
3774 thr_name && *thr_name ? const_cast <char*>(*thr_name) : 0,
3775 priority,
3776 (int) flags,
3777 (char *) stack + sizeof (WIND_TCB),
3778 (int) (stacksize - sizeof (WIND_TCB)),
3779 thread_args->entry_point (),
3780 (int) thread_args,
3781 0, 0, 0, 0, 0, 0, 0, 0, 0);
3783 if (status == OK)
3785 // The task was successfully initialized, now activate it.
3786 status = ::taskActivate ((ACE_hthread_t) tcb);
3789 tid = status == OK ? (ACE_thread_t) tcb : ERROR;
3791 # endif /* 0 */
3793 if (tid == ACE_VX_TASK_ID_ERROR)
3794 return -1;
3795 else
3797 if (thr_id)
3798 *thr_id = tid;
3800 if (thr_handle)
3801 *thr_handle = tid;
3803 if (thr_name && !(*thr_name))
3804 *thr_name = ::taskName (tid);
3806 auto_thread_args.release ();
3807 return 0;
3810 # endif /* ACE_HAS_PTHREADS */
3811 #else
3812 ACE_UNUSED_ARG (func);
3813 ACE_UNUSED_ARG (args);
3814 ACE_UNUSED_ARG (flags);
3815 ACE_UNUSED_ARG (thr_id);
3816 ACE_UNUSED_ARG (thr_handle);
3817 ACE_UNUSED_ARG (priority);
3818 ACE_UNUSED_ARG (stack);
3819 ACE_UNUSED_ARG (stacksize);
3820 ACE_UNUSED_ARG (thr_name);
3821 ACE_NOTSUP_RETURN (-1);
3822 #endif /* ACE_HAS_THREADS */
3825 void
3826 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
3828 ACE_OS_TRACE ("ACE_OS::thr_exit");
3829 #if defined (ACE_HAS_THREADS)
3830 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_EXIT)
3831 ::pthread_exit (status);
3832 # elif defined (ACE_HAS_WTHREADS)
3833 // Can't call it here because on NT, the thread is exited
3834 // directly by ACE_Thread_Adapter::invoke ().
3835 // ACE_TSS_Cleanup::instance ()->thread_exit (status);
3837 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
3838 int using_afx = -1;
3839 // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
3840 // But without #including ace/Thread_Manager.h, we don't know that.
3841 ACE_OS_Thread_Descriptor *td =
3842 ACE_Base_Thread_Adapter::thr_desc_log_msg ();
3843 if (td)
3844 using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
3845 # endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
3847 // Call TSS destructors.
3848 ACE_OS::cleanup_tss (0 /* not main thread */);
3850 // Exit the thread.
3851 // Allow CWinThread-destructor to be invoked from AfxEndThread.
3852 // _endthreadex will be called from AfxEndThread so don't exit the
3853 // thread now if we are running an MFC thread.
3854 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
3855 if (using_afx != -1)
3857 if (using_afx)
3858 ::AfxEndThread (status);
3859 else
3860 ACE_ENDTHREADEX (status);
3862 else
3864 // Not spawned by ACE_Thread_Manager, use the old buggy
3865 // version. You should seriously consider using
3866 // ACE_Thread_Manager to spawn threads. The following code is
3867 // know to cause some problem.
3868 CWinThread *pThread = ::AfxGetThread ();
3869 if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
3870 ACE_ENDTHREADEX (status);
3871 else
3872 ::AfxEndThread (status);
3874 # else
3875 ACE_ENDTHREADEX (status);
3876 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
3878 # elif defined (ACE_HAS_VXTHREADS)
3879 ACE_UNUSED_ARG (status);
3880 ::taskDelete (ACE_OS::thr_self ());
3881 # else
3882 ACE_UNUSED_ARG (status);
3883 # endif /* ACE_HAS_PTHREADS */
3884 #else
3885 ACE_UNUSED_ARG (status);
3886 #endif /* ACE_HAS_THREADS */
3889 #if defined (ACE_HAS_VXTHREADS)
3890 // Leave this in the global scope to allow
3891 // users to adjust the delay value.
3892 int ACE_THR_JOIN_DELAY = 5;
3895 ACE_OS::thr_join (ACE_hthread_t thr_handle,
3896 ACE_THR_FUNC_RETURN *status)
3898 // We can't get the status of the thread
3899 if (status != 0)
3901 *status = 0;
3904 // This method can not support joining all threads
3905 if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
3907 ACE_NOTSUP_RETURN (-1);
3910 int retval = ESRCH;
3911 ACE_thread_t current = ACE_OS::thr_self ();
3913 // Make sure we are not joining ourself
3914 if (ACE_OS::thr_cmp (thr_handle, current))
3916 retval = EDEADLK;
3918 else
3920 // Whether the task exists or not
3921 // we will return a successful value
3922 retval = 0;
3924 // Verify that the task id still exists
3925 while (taskIdVerify (thr_handle) == OK)
3927 // Wait a bit to see if the task is still active.
3928 ACE_OS::sleep (ACE_THR_JOIN_DELAY);
3932 // Adapt the return value into errno and return value.
3933 // The ACE_ADAPT_RETVAL macro doesn't exactly do what
3934 // we need to do here, so we do it manually.
3935 if (retval != 0)
3937 errno = retval;
3938 retval = -1;
3941 return retval;
3945 ACE_OS::thr_join (ACE_thread_t waiter_id,
3946 ACE_thread_t *thr_id,
3947 ACE_THR_FUNC_RETURN *status)
3949 thr_id = 0;
3950 return ACE_OS::thr_join (waiter_id, status);
3952 #endif /* ACE_HAS_VXTHREADS */
3955 ACE_OS::thr_key_detach (ACE_thread_key_t key)
3957 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
3958 TSS_Cleanup_Instance cleanup;
3959 if (cleanup.valid ())
3961 return cleanup->thread_detach_key (key);
3963 else
3965 return -1;
3967 #else
3968 ACE_UNUSED_ARG (key);
3969 ACE_NOTSUP_RETURN (-1);
3970 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
3974 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id,
3975 size_t cpu_set_size,
3976 cpu_set_t * cpu_mask)
3978 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
3979 // Handle of the thread, which is NPTL thread-id, normally a big number
3980 if (::pthread_getaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
3982 return -1;
3984 return 0;
3985 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
3986 // The process-id is expected as <thr_id>, which can be a thread-id of
3987 // linux-thread, thus making binding to cpu of that particular thread only.
3988 // If you are using this flag for NPTL-threads, however, please pass as a
3989 // thr_id process id obtained by ACE_OS::getpid ()
3990 ACE_UNUSED_ARG (cpu_set_size);
3991 if (::sched_getaffinity(thr_id, cpu_mask) == -1)
3993 return -1;
3995 return 0;
3996 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
3997 // The process-id is expected as <thr_id>, which can be a thread-id of
3998 // linux-thread, thus making binding to cpu of that particular thread only.
3999 // If you are using this flag for NPTL-threads, however, please pass as a
4000 // thr_id process id obtained by ACE_OS::getpid ()
4001 if (::sched_getaffinity(thr_id, cpu_set_size, cpu_mask) == -1)
4003 return -1;
4005 return 0;
4006 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4007 ACE_UNUSED_ARG (cpu_set_size);
4008 int result = 0;
4009 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id, *cpu_mask), result) == -1)
4011 return -1;
4013 return 0;
4014 #else
4015 ACE_UNUSED_ARG (thr_id);
4016 ACE_UNUSED_ARG (cpu_set_size);
4017 ACE_UNUSED_ARG (cpu_mask);
4018 ACE_NOTSUP_RETURN (-1);
4019 #endif
4023 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id,
4024 size_t cpu_set_size,
4025 const cpu_set_t * cpu_mask)
4027 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
4028 if (::pthread_setaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4030 return -1;
4032 return 0;
4033 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
4034 // The process-id is expected as <thr_id>, which can be a thread-id of
4035 // linux-thread, thus making binding to cpu of that particular thread only.
4036 // If you are using this flag for NPTL-threads, however, please pass as a
4037 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4039 ACE_UNUSED_ARG (cpu_set_size);
4040 if (::sched_setaffinity (thr_id, cpu_mask) == -1)
4042 return -1;
4044 return 0;
4045 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
4046 // The process-id is expected as <thr_id>, which can be a thread-id of
4047 // linux-thread, thus making binding to cpu of that particular thread only.
4048 // If you are using this flag for NPTL-threads, however, please pass as a
4049 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4051 if (::sched_setaffinity (thr_id, cpu_set_size, cpu_mask) == -1)
4053 return -1;
4055 return 0;
4056 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4057 ACE_UNUSED_ARG (cpu_set_size);
4058 int result = 0;
4059 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id, *cpu_mask), result) == -1)
4061 return -1;
4063 return 0;
4064 #else
4065 ACE_UNUSED_ARG (thr_id);
4066 ACE_UNUSED_ARG (cpu_set_size);
4067 ACE_UNUSED_ARG (cpu_mask);
4068 ACE_NOTSUP_RETURN (-1);
4069 #endif
4073 ACE_OS::thr_key_used (ACE_thread_key_t key)
4075 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
4076 TSS_Cleanup_Instance cleanup;
4077 if (cleanup.valid ())
4079 cleanup->thread_use_key (key);
4080 return 0;
4082 return -1;
4083 #else
4084 ACE_UNUSED_ARG (key);
4085 ACE_NOTSUP_RETURN (-1);
4086 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
4089 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4091 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t *key,
4092 # if defined (ACE_HAS_THR_C_DEST)
4093 ACE_THR_C_DEST dest
4094 # else
4095 ACE_THR_DEST dest
4096 # endif /* ACE_HAS_THR_C_DEST */
4099 // can't trace here. Trace uses TSS
4100 // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
4101 # if defined (ACE_HAS_THREADS)
4102 # if defined (ACE_HAS_PTHREADS)
4103 int result;
4104 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
4105 result),
4106 int);
4107 # elif defined (ACE_HAS_WTHREADS)
4108 ACE_UNUSED_ARG (dest);
4109 *key = ::TlsAlloc ();
4111 if (*key == ACE_SYSCALL_FAILED)
4112 ACE_FAIL_RETURN (-1);
4113 return 0;
4114 # endif /* ACE_HAS_PTHREADS */
4115 # else
4116 ACE_UNUSED_ARG (key);
4117 ACE_UNUSED_ARG (dest);
4118 ACE_NOTSUP_RETURN (-1);
4119 # endif /* ACE_HAS_THREADS */
4121 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4124 ACE_OS::thr_keycreate (ACE_thread_key_t *key,
4125 # if defined (ACE_HAS_THR_C_DEST)
4126 ACE_THR_C_DEST dest)
4127 # else
4128 ACE_THR_DEST dest)
4129 # endif /* ACE_HAS_THR_C_DEST */
4131 // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
4132 #if defined (ACE_HAS_THREADS)
4133 # if defined (ACE_HAS_TSS_EMULATION)
4134 if (ACE_TSS_Emulation::next_key (*key) == 0)
4136 ACE_TSS_Emulation::tss_destructor (*key, dest);
4138 // Extract out the thread-specific table instance and stash away
4139 // the key and destructor so that we can free it up later on...
4140 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4141 if (cleanup.valid ())
4143 return cleanup->insert (*key, dest);
4145 else
4147 return -1;
4150 else
4151 return -1;
4152 # elif defined (ACE_HAS_WTHREADS)
4153 if (ACE_OS::thr_keycreate_native (key, dest) == 0)
4155 // Extract out the thread-specific table instance and stash away
4156 // the key and destructor so that we can free it up later on...
4157 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4158 if (cleanup.valid ())
4160 return cleanup->insert (*key, dest);
4162 else
4164 return -1;
4167 else
4168 return -1;
4169 /* NOTREACHED */
4170 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4171 return ACE_OS::thr_keycreate_native (key, dest);
4172 # else
4173 ACE_UNUSED_ARG (key);
4174 ACE_UNUSED_ARG (dest);
4175 ACE_NOTSUP_RETURN (-1);
4176 # endif /* ACE_HAS_TSS_EMULATION */
4177 # else /* ACE_HAS_THREADS */
4178 ACE_UNUSED_ARG (key);
4179 ACE_UNUSED_ARG (dest);
4180 ACE_NOTSUP_RETURN (-1);
4181 # endif /* ACE_HAS_THREADS */
4184 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4186 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key)
4188 ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
4189 # if defined (ACE_HAS_THREADS)
4190 # if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
4191 // For some systems, e.g. LynxOS, we need to ensure that
4192 // any registered thread destructor action for this slot
4193 // is now disabled. Otherwise in the event of a dynamic library
4194 // unload of libACE, by a program not linked with libACE,
4195 // ACE_TSS_cleanup will be invoked again at the thread exit
4196 // after libACE has been actually been unmapped from memory.
4197 (void) ACE_OS::thr_setspecific_native (key, 0);
4198 # endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
4199 # if defined (ACE_HAS_PTHREADS)
4200 # if defined (ACE_LACKS_PTHREAD_KEY_DELETE)
4201 ACE_UNUSED_ARG (key);
4202 ACE_NOTSUP_RETURN (-1);
4203 # else
4204 return ::pthread_key_delete (key);
4205 # endif /* ACE_LACKS_PTHREAD_KEY_DELETE */
4206 # elif defined (ACE_HAS_THR_KEYDELETE)
4207 return ::thr_keydelete (key);
4208 # elif defined (ACE_HAS_WTHREADS)
4209 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
4210 # else
4211 ACE_UNUSED_ARG (key);
4212 ACE_NOTSUP_RETURN (-1);
4213 # endif /* ACE_HAS_PTHREADS */
4214 # else
4215 ACE_UNUSED_ARG (key);
4216 ACE_NOTSUP_RETURN (-1);
4217 # endif /* ACE_HAS_THREADS */
4219 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4222 ACE_OS::thr_keyfree (ACE_thread_key_t key)
4224 ACE_OS_TRACE ("ACE_OS::thr_keyfree");
4225 # if defined (ACE_HAS_THREADS)
4226 # if defined (ACE_HAS_TSS_EMULATION)
4227 // Release the key in the TSS_Emulation administration
4228 ACE_TSS_Emulation::release_key (key);
4229 TSS_Cleanup_Instance cleanup;
4230 if (cleanup.valid ())
4232 return cleanup->free_key (key);
4234 return -1;
4235 # elif defined (ACE_HAS_WTHREADS)
4236 // Extract out the thread-specific table instance and free up
4237 // the key and destructor.
4238 TSS_Cleanup_Instance cleanup;
4239 if (cleanup.valid ())
4241 return cleanup->free_key (key);
4243 return -1;
4244 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4245 return ACE_OS::thr_keyfree_native (key);
4246 # else
4247 ACE_UNUSED_ARG (key);
4248 ACE_NOTSUP_RETURN (-1);
4249 # endif /* ACE_HAS_TSS_EMULATION */
4250 # else /* ACE_HAS_THREADS */
4251 ACE_UNUSED_ARG (key);
4252 ACE_NOTSUP_RETURN (-1);
4253 return 0;
4254 # endif /* ACE_HAS_THREADS */
4258 ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
4260 // Set the thread priority on the current thread.
4261 ACE_hthread_t my_thread_id;
4262 ACE_OS::thr_self (my_thread_id);
4264 return ACE_OS::thr_setprio (my_thread_id, prio);
4267 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4269 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key, void *data)
4271 // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
4272 # if defined (ACE_HAS_THREADS)
4273 # if defined (ACE_HAS_PTHREADS)
4274 int result;
4275 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key, data),
4276 result),
4277 int);
4278 # elif defined (ACE_HAS_WTHREADS)
4279 ::TlsSetValue (key, data);
4280 return 0;
4281 # else /* ACE_HAS_PTHREADS */
4282 ACE_UNUSED_ARG (key);
4283 ACE_UNUSED_ARG (data);
4284 ACE_NOTSUP_RETURN (-1);
4285 # endif /* ACE_HAS_PTHREADS */
4286 # else
4287 ACE_UNUSED_ARG (key);
4288 ACE_UNUSED_ARG (data);
4289 ACE_NOTSUP_RETURN (-1);
4290 # endif /* ACE_HAS_THREADS */
4292 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4295 ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
4297 // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
4298 #if defined (ACE_HAS_THREADS)
4299 # if defined (ACE_HAS_TSS_EMULATION)
4300 if (ACE_TSS_Emulation::is_key (key) == 0)
4302 errno = EINVAL;
4303 data = 0;
4304 return -1;
4306 else
4308 ACE_TSS_Emulation::ts_object (key) = data;
4309 TSS_Cleanup_Instance cleanup;
4310 if (cleanup.valid ())
4312 cleanup->thread_use_key (key);
4313 // for TSS_Cleanup purposes treat stetting data to zero
4314 // like detaching. This is a consequence of POSIX allowing
4315 // deletion of a "used" key.
4316 if (data == 0)
4318 cleanup->thread_detach_key (key);
4320 return 0;
4322 else
4324 return -1;
4327 # elif defined (ACE_HAS_WTHREADS)
4328 if (ACE_OS::thr_setspecific_native (key, data) == 0)
4330 TSS_Cleanup_Instance cleanup;
4331 if (cleanup.valid ())
4333 cleanup->thread_use_key (key);
4334 // for TSS_Cleanup purposes treat stetting data to zero
4335 // like detaching. This is a consequence of POSIX allowing
4336 // deletion of a "used" key.
4337 if (data == 0)
4339 cleanup->thread_detach_key (key);
4341 return 0;
4343 return -1;
4345 return -1;
4346 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4347 return ACE_OS::thr_setspecific_native (key, data);
4348 # else /* ACE_HAS_TSS_EMULATION */
4349 ACE_UNUSED_ARG (key);
4350 ACE_UNUSED_ARG (data);
4351 ACE_NOTSUP_RETURN (-1);
4352 # endif /* ACE_HAS_TSS_EMULATION */
4353 # else /* ACE_HAS_THREADS */
4354 ACE_UNUSED_ARG (key);
4355 ACE_UNUSED_ARG (data);
4356 ACE_NOTSUP_RETURN (-1);
4357 # endif /* ACE_HAS_THREADS */
4360 void
4361 ACE_OS::unique_name (const void *object,
4362 char *name,
4363 size_t length)
4365 // The process ID will provide uniqueness between processes on the
4366 // same machine. The "this" pointer of the <object> will provide
4367 // uniqueness between other "live" objects in the same process. The
4368 // uniqueness of this name is therefore only valid for the life of
4369 // <object>.
4370 ACE_OS::snprintf (name, length, "%p%d", object,
4371 static_cast<int> (ACE_OS::getpid ()));
4374 #if defined (ACE_USES_WCHAR)
4375 void
4376 ACE_OS::unique_name (const void *object,
4377 wchar_t *name,
4378 size_t length)
4380 // The process ID will provide uniqueness between processes on the
4381 // same machine. The "this" pointer of the <object> will provide
4382 // uniqueness between other "live" objects in the same process. The
4383 // uniqueness of this name is therefore only valid for the life of
4384 // <object>.
4385 ACE_OS::snprintf (name, length, ACE_TEXT ("%p%d"), object,
4386 static_cast<int> (ACE_OS::getpid ()));
4388 #endif
4390 ACE_END_VERSIONED_NAMESPACE_DECL
4392 #if defined (ACE_VXWORKS) && !defined (__RTP__)
4393 # include /**/ <usrLib.h> /* for ::sp() */
4394 # include /**/ <sysLib.h> /* for ::sysClkRateGet() */
4395 # include "ace/Service_Config.h"
4397 #if !defined (ACE_LACKS_VA_FUNCTIONS)
4399 // This global function can be used from the VxWorks shell to pass
4400 // arguments to a C main () function.
4402 // usage: -> spa main, "arg1", "arg2"
4404 // All arguments must be quoted, even numbers.
4406 spa (FUNCPTR entry, ...)
4408 // The called entrypoint can get the function name plus the normal 10
4409 // optional arguments.
4410 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 1 + 10;
4411 static char *argv[ACE_MAX_ARGS] = { 0 };
4412 va_list pvar;
4413 ACE_VX_USR_ARG_T argc;
4415 // Hardcode a program name because the real one isn't available
4416 // through the VxWorks shell.
4417 argv[0] = const_cast<char*> ("ace_main");
4419 // Peel off arguments to spa () and put into argv. va_arg () isn't
4420 // necessarily supposed to return 0 when done, though since the
4421 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4422 // the unused ones. This function could be used to increase that
4423 // limit, but then it couldn't depend on the trailing 0. So, the
4424 // number of arguments would have to be passed.
4425 va_start (pvar, entry);
4427 for (argc = 1; argc < ACE_MAX_ARGS; ++argc)
4429 argv[argc] = va_arg (pvar, char *);
4431 if (argv[argc] == 0)
4432 break;
4435 if (argc >= ACE_MAX_ARGS && argv[ACE_MAX_ARGS - 1] != 0)
4437 // Try to read another arg, and warn user if the limit was exceeded.
4439 // Note that the VxWorks shell arguments change from int to long when
4440 // using a 64bit compiler. Cast the argument up so that the format
4441 // specifier remains correct for either build type.
4442 if (va_arg (pvar, char *) != 0)
4443 ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %ld\n",
4444 (long)ACE_MAX_ARGS);
4446 else
4448 // fill unused argv slots with 0 to get rid of leftovers
4449 // from previous invocations
4450 for (ACE_VX_USR_ARG_T i = argc; i < ACE_MAX_ARGS; ++i)
4451 argv[i] = 0;
4454 // The hard-coded options are what ::sp () uses, except for the
4455 // larger stack size (instead of ::sp ()'s 20000).
4456 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
4457 100, // task priority
4458 VX_FP_TASK, // task options
4459 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
4460 entry, // entry point
4461 argc, // first argument to main ()
4462 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
4463 0, 0, 0, 0, 0, 0, 0, 0);
4464 va_end (pvar);
4466 // ::taskSpawn () returns TASK_ID_ERROR on
4467 // error
4468 return ret == ACE_VX_TASK_ID_ERROR ? -1 : 0;
4470 #endif /* !ACE_LACKS_VA_FUNCTIONS */
4472 // A helper function for the extended spa functions
4473 static void
4474 add_to_argv (ACE_VX_USR_ARG_T& argc, char** argv, int max_args, char* string)
4476 char indouble = 0;
4477 size_t previous = 0;
4478 size_t length = ACE_OS::strlen (string);
4480 if (length > 0)
4482 // We use <= to make sure that we get the last argument
4483 for (size_t i = 0; i <= length; i++)
4485 // Is it a double quote that hasn't been escaped?
4486 if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
4488 indouble ^= 1;
4489 if (indouble)
4491 // We have just entered a double quoted string, so
4492 // save the starting position of the contents.
4493 previous = i + 1;
4495 else
4497 // We have just left a double quoted string, so
4498 // zero out the ending double quote.
4499 string[i] = '\0';
4502 else if (string[i] == '\\') // Escape the next character
4504 // The next character is automatically skipped because
4505 // of the memmove().
4506 ACE_OS::memmove (string + i, string + i + 1, length);
4507 --length;
4509 else if (!indouble &&
4510 (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
4512 string[i] = '\0';
4513 if (argc < max_args)
4515 argv[argc] = string + previous;
4516 ++argc;
4518 else
4520 ACE_OS::fprintf (stderr, "spae(): number of arguments "
4521 "limited to %d\n", max_args);
4524 // Skip over whitespace in between arguments
4525 for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
4529 // Save the starting point for the next time around
4530 previous = i;
4532 // Make sure we don't skip over a character due
4533 // to the above loop to skip over whitespace
4534 --i;
4540 // This global function can be used from the VxWorks shell to pass
4541 // arguments to a C main () function.
4543 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
4545 // All arguments must be within double quotes, even numbers.
4547 spae (FUNCPTR entry, ...)
4549 static int const WINDSH_ARGS = 10;
4550 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
4551 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
4552 va_list pvar;
4553 ACE_VX_USR_ARG_T argc = 1;
4555 // Peel off arguments to spa () and put into argv. va_arg () isn't
4556 // necessarily supposed to return 0 when done, though since the
4557 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4558 // the unused ones.
4559 va_start (pvar, entry);
4561 int i = 0;
4562 for (char* str = va_arg (pvar, char*);
4563 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
4565 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
4568 // fill unused argv slots with 0 to get rid of leftovers
4569 // from previous invocations
4570 for (i = argc; i < ACE_MAX_ARGS; ++i)
4571 argv[i] = 0;
4573 // The hard-coded options are what ::sp () uses, except for the
4574 // larger stack size (instead of ::sp ()'s 20000).
4575 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
4576 100, // task priority
4577 VX_FP_TASK, // task options
4578 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
4579 entry, // entry point
4580 argc, // first argument to main ()
4581 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
4582 0, 0, 0, 0, 0, 0, 0, 0);
4583 va_end (pvar);
4585 // ::taskSpawn () returns the taskID on success: return 0 instead if
4586 // successful
4587 return ret == ACE_VX_TASK_ID_ERROR ? -1 : 0;
4590 // This global function can be used from the VxWorks shell to pass
4591 // arguments to a C main () function. The function will be run
4592 // within the shells task.
4594 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
4596 // All arguments must be within double quotes, even numbers.
4597 // Unlike the spae function, this fuction executes the supplied
4598 // routine in the foreground, rather than spawning it in a separate
4599 // task.
4601 spaef (FUNCPTR entry, ...)
4603 static int const WINDSH_ARGS = 10;
4604 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
4605 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
4606 va_list pvar;
4607 ACE_VX_USR_ARG_T argc = 1;
4609 // Peel off arguments to spa () and put into argv. va_arg () isn't
4610 // necessarily supposed to return 0 when done, though since the
4611 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4612 // the unused ones.
4613 va_start (pvar, entry);
4615 int i = 0;
4616 for (char* str = va_arg (pvar, char*);
4617 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
4619 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
4622 // fill unused argv slots with 0 to get rid of leftovers
4623 // from previous invocations
4624 for (i = argc; i < ACE_MAX_ARGS; ++i)
4625 argv[i] = 0;
4627 int const ret = entry (argc, argv);
4629 va_end (pvar);
4631 // Return the return value of the invoked ace_main routine.
4632 return ret;
4635 // This global function can be used from the VxWorks shell to pass
4636 // arguments to and run a main () function (i.e. ace_main).
4638 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
4640 // All arguments must be within double quotes, even numbers.
4641 // This routine spawns the main () function in a separate task and waits till the
4642 // task has finished.
4643 static int _vx_call_rc = 0;
4645 static int
4646 _vx_call_entry(FUNCPTR entry, int argc, char* argv[])
4648 ACE_Service_Config::current (ACE_Service_Config::global());
4649 _vx_call_rc = entry (argc, argv);
4650 return _vx_call_rc;
4654 vx_execae (FUNCPTR entry, char* arg, int prio, int opt, size_t stacksz, ...)
4656 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
4657 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
4658 ACE_VX_USR_ARG_T argc = 1;
4660 // Peel off arguments to run_main () and put into argv.
4661 if (arg)
4663 add_to_argv(argc, argv, ACE_MAX_ARGS, arg);
4666 // fill unused argv slots with 0 to get rid of leftovers
4667 // from previous invocations
4668 for (ACE_VX_USR_ARG_T i = argc; i < ACE_MAX_ARGS; ++i)
4669 argv[i] = 0;
4671 // The hard-coded options are what ::sp () uses, except for the
4672 // larger stack size (instead of ::sp ()'s 20000).
4673 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
4674 prio==0 ? 100 : prio, // task priority
4675 opt==0 ? VX_FP_TASK : opt, // task options
4676 stacksz==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE : stacksz, // stack size
4677 (FUNCPTR)_vx_call_entry, // entrypoint caller
4678 (ACE_VX_USR_ARG_T)entry, // entry point
4679 argc, // first argument to main ()
4680 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
4681 0, 0, 0, 0, 0, 0, 0);
4683 if (ret == ACE_VX_TASK_ID_ERROR)
4684 return 255;
4686 while( ::taskIdVerify (ret) != ERROR )
4687 ::taskDelay (3 * ::sysClkRateGet ());
4689 // ::taskSpawn () returns TASK_ID_ERROR on failure: return _vx_call_rc instead if
4690 // successful
4691 return ret == ACE_VX_TASK_ID_ERROR ? 255 : _vx_call_rc;
4694 #if defined(ACE_AS_STATIC_LIBS) && defined (ACE_VXWORKS_DEBUGGING_HELPER)
4695 /** Wind River workbench allows the user to spawn a kernel task as a
4696 "Debug Configuration". Use this function as the entrypoint so that
4697 the arguments are translated into the form that ace_main() requires.
4699 int ace_wb_exec (int arg0, int arg1, int arg2, int arg3, int arg4,
4700 int arg5, int arg6, int arg7, int arg8, int arg9)
4702 return spaef ((FUNCPTR) ace_main, arg0, arg1, arg2, arg3, arg4,
4703 arg5, arg6, arg7, arg8, arg9);
4705 #endif /* ACE_AS_STATIC_LIBS && ... */
4707 #endif /* ACE_VXWORKS && !__RTP__ */