Revert to Current Include Style
[ACE_TAO.git] / ACE / ace / OS_NS_Thread.cpp
blob4c94dd1312055f0a73465fab320a00a92cb5f468
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/Auto_Ptr.h"
17 #include "ace/Thread_Mutex.h"
18 #include "ace/Condition_Thread_Mutex.h"
19 #include "ace/Guard_T.h"
20 #ifdef ACE_HAS_GETTID
21 # include "ace/OS_NS_sys_resource.h" // syscall for gettid impl
22 #endif
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_WINCE)
34 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
35 CreateThread (0, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & (CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION), (unsigned long *) THR_ID)
36 #elif defined(ACE_HAS_WTHREADS)
37 // Green Hills compiler gets confused when __stdcall is embedded in
38 // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
39 // instead.
40 typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*);
41 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
42 ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
43 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
45 /*****************************************************************************/
47 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
49 void
50 ACE_Thread_ID::to_string (char *thr_string, size_t thr_string_len) const
52 #if defined (ACE_WIN32)
53 ACE_OS::snprintf (thr_string, thr_string_len, "%u",
54 static_cast <unsigned> (this->thread_id_));
55 #else
56 // Yes, this is an ugly C-style cast, but the correct C++ cast is
57 // different depending on whether the t_id is an integral type or a
58 // pointer type. FreeBSD uses a pointer type, but doesn't have a _np
59 // function to get an integral type like other OSes, so use the
60 // bigger hammer.
61 ACE_OS::snprintf (thr_string, thr_string_len, "%lu",
62 # ifdef ACE_THREAD_T_IS_A_STRUCT
63 *reinterpret_cast<const unsigned long *> (&
64 # else
65 (unsigned long) (
66 # endif // ACE_THREAD_T_IS_A_STRUCT
67 thread_handle_));
69 #endif /* ACE_WIN32 */
72 /*****************************************************************************/
74 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
76 #if defined (ACE_HAS_TSS_EMULATION)
77 u_int ACE_TSS_Emulation::total_keys_ = 0;
79 ACE_TSS_Keys* ACE_TSS_Emulation::tss_keys_used_ = 0;
81 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
82 ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]
83 = { 0 };
85 # if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) && defined (ACE_HAS_VXTHREADS)
87 # if (defined (_WRS_CONFIG_SMP) || defined (INCLUDE_AMP_CPU))
88 __thread void* ACE_TSS_Emulation::ace_tss_keys = 0;
89 # else /* ! VxWorks SMP */
90 void* ACE_TSS_Emulation::ace_tss_keys = 0;
91 # endif /* ! VxWorks SMP */
93 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
95 bool ACE_TSS_Emulation::key_created_ = false;
97 ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_;
99 /* static */
100 # if defined (ACE_HAS_THR_C_FUNC)
101 extern "C"
102 void
103 ACE_TSS_Emulation_cleanup (void *)
105 // Really this must be used for ACE_TSS_Emulation code to make the TSS
106 // cleanup
108 # else
109 void
110 ACE_TSS_Emulation_cleanup (void *)
112 // Really this must be used for ACE_TSS_Emulation code to make the TSS
113 // cleanup
115 # endif /* ACE_HAS_THR_C_FUNC */
117 void **
118 ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created)
120 // TSS Singleton implementation.
122 // Create the one native TSS key, if necessary.
123 if (!key_created_)
125 // Double-checked lock . . .
126 ACE_TSS_BASE_GUARD
128 if (!key_created_)
130 if (ACE_OS::thr_keycreate_native (&native_tss_key_,
131 &ACE_TSS_Emulation_cleanup) != 0)
133 ACE_ASSERT (0);
134 return 0; // Major problems, this should *never* happen!
136 key_created_ = true;
140 void **old_ts_storage = 0;
142 // Get the tss_storage from thread-OS specific storage.
143 if (ACE_OS::thr_getspecific_native (native_tss_key_,
144 (void **) &old_ts_storage) == -1)
146 ACE_ASSERT (false);
147 return 0; // This should not happen!
150 // Check to see if this is the first time in for this thread.
151 // This block can also be entered after a fork () in the child process.
152 if (old_ts_storage == 0)
154 if (ts_created)
155 *ts_created = 1u;
157 // Use the ts_storage passed as argument, if non-zero. It is
158 // possible that this has been implemented in the stack. At the
159 // moment, this is unknown. The cleanup must not do nothing.
160 // If ts_storage is zero, allocate (and eventually leak) the
161 // storage array.
162 if (ts_storage == 0)
164 #ifdef ACE_HAS_ALLOC_HOOKS
165 const size_t n = ACE_TSS_THREAD_KEYS_MAX * sizeof (void *);
166 ACE_Allocator *const alloc = ACE_Allocator::instance ();
167 ACE_ALLOCATOR_RETURN (ts_storage,
168 static_cast<void **> (alloc->malloc (n)), 0);
169 #else
170 ACE_NEW_RETURN (ts_storage,
171 void*[ACE_TSS_THREAD_KEYS_MAX],
173 #endif
175 // Zero the entire TSS array. Do it manually instead of
176 // using memset, for optimum speed. Though, memset may be
177 // faster :-)
178 void **tss_base_p = ts_storage;
180 for (u_int i = 0;
181 i < ACE_TSS_THREAD_KEYS_MAX;
182 ++i)
183 *tss_base_p++ = 0;
186 // Store the pointer in thread-specific storage. It gets
187 // deleted via the ACE_TSS_Emulation_cleanup function when the
188 // thread terminates.
189 if (ACE_OS::thr_setspecific_native (native_tss_key_,
190 (void *) ts_storage) != 0)
192 ACE_ASSERT (false);
193 return 0; // This should not happen!
196 else
197 if (ts_created)
198 ts_created = 0;
200 return ts_storage ? ts_storage : old_ts_storage;
202 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
204 u_int
205 ACE_TSS_Emulation::total_keys ()
207 ACE_OS_Recursive_Thread_Mutex_Guard (
208 *static_cast <ACE_recursive_thread_mutex_t *>
209 (ACE_OS_Object_Manager::preallocated_object[
210 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
212 return total_keys_;
216 ACE_TSS_Emulation::next_key (ACE_thread_key_t &key)
218 ACE_OS_Recursive_Thread_Mutex_Guard (
219 *static_cast <ACE_recursive_thread_mutex_t *>
220 (ACE_OS_Object_Manager::preallocated_object[
221 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
223 // Initialize the tss_keys_used_ pointer on first use.
224 if (tss_keys_used_ == 0)
226 ACE_NEW_RETURN (tss_keys_used_, ACE_TSS_Keys, -1);
229 if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX)
231 u_int counter = 0;
232 // Loop through all possible keys and check whether a key is free
233 for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++)
235 ACE_thread_key_t localkey = counter;
236 // If the key is not set as used, we can give out this key, if not
237 // we have to search further
238 if (tss_keys_used_->is_set(localkey) == 0)
240 tss_keys_used_->test_and_set(localkey);
241 key = localkey;
242 break;
246 ++total_keys_;
247 return 0;
249 else
251 key = ACE_OS::NULL_key;
252 return -1;
257 ACE_TSS_Emulation::release_key (ACE_thread_key_t key)
259 ACE_OS_Recursive_Thread_Mutex_Guard (
260 *static_cast <ACE_recursive_thread_mutex_t *>
261 (ACE_OS_Object_Manager::preallocated_object[
262 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
264 if (tss_keys_used_ != 0 &&
265 tss_keys_used_->test_and_clear (key) == 0)
267 --total_keys_;
268 return 0;
270 return 1;
274 ACE_TSS_Emulation::is_key (ACE_thread_key_t key)
276 ACE_OS_Recursive_Thread_Mutex_Guard (
277 *static_cast <ACE_recursive_thread_mutex_t *>
278 (ACE_OS_Object_Manager::preallocated_object[
279 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
281 if (tss_keys_used_ != 0 &&
282 tss_keys_used_->is_set (key) == 1)
284 return 1;
286 return 0;
289 void *
290 ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX])
292 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
293 // On VxWorks, in particular, don't check to see if the field
294 // is 0. It isn't always, specifically, when a program is run
295 // directly by the shell (without spawning a new task) after
296 // another program has been run.
298 u_int ts_created = 0;
299 tss_base (ts_storage, &ts_created);
300 if (ts_created)
302 # else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
303 tss_base () = ts_storage;
304 # endif
306 // Zero the entire TSS array. Do it manually instead of using
307 // memset, for optimum speed. Though, memset may be faster :-)
308 void **tss_base_p = tss_base ();
309 for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
311 *tss_base_p = 0;
314 return tss_base ();
315 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
317 else
319 return 0;
321 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
324 void
325 ACE_TSS_Emulation::tss_close ()
327 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
328 ACE_OS::thr_keyfree_native (native_tss_key_);
329 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
332 #endif /* ACE_HAS_TSS_EMULATION */
334 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
336 /*****************************************************************************/
338 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
340 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
341 // the single file of template instantiations.
343 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id)
344 : tid_(id)
346 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
349 ACE_TSS_Ref::ACE_TSS_Ref (void)
351 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
354 // Check for equality.
355 bool
356 ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const
358 ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
360 #ifdef ACE_THREAD_T_IS_A_STRUCT
361 return 0 == ACE_OS::memcmp (&this->tid_, &info.tid_, sizeof tid_);
362 #else
363 return this->tid_ == info.tid_;
364 #endif
367 // Check for inequality.
368 bool
369 ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
371 ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
373 return !(*this == tss_ref);
376 // moved class ACE_TSS_Info declaration
377 // to OS.h so it can be visible to the
378 // single file of template instantiations
380 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
381 ACE_TSS_Info::Destructor dest)
382 : key_ (key),
383 destructor_ (dest),
384 thread_count_ (-1)
386 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
389 ACE_TSS_Info::ACE_TSS_Info (void)
390 : key_ (ACE_OS::NULL_key),
391 destructor_ (0),
392 thread_count_ (-1)
394 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
397 // Check for equality.
398 bool
399 ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const
401 ACE_OS_TRACE ("ACE_TSS_Info::operator==");
403 return this->key_ == info.key_;
406 // Check for inequality.
407 bool
408 ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const
410 ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
412 return !(*this == info);
415 void
416 ACE_TSS_Info::dump (void)
418 # if defined (ACE_HAS_DUMP)
419 // ACE_OS_TRACE ("ACE_TSS_Info::dump");
421 # if 0
422 ACELIB_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
423 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %u\n"), this->key_));
424 ACELIB_DEBUG ((LM_DEBUG, ACE_TEXT ("destructor_ = %u\n"), this->destructor_));
425 ACELIB_DEBUG ((LM_DEBUG, ACE_END_DUMP));
426 # endif /* 0 */
427 # endif /* ACE_HAS_DUMP */
430 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
431 // to the single file of template instantiations.
433 ACE_TSS_Keys::ACE_TSS_Keys (void)
435 for (u_int i = 0; i < ACE_WORDS; ++i)
437 key_bit_words_[i] = 0;
442 void
443 ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit)
445 word = key / ACE_BITS_PER_WORD;
446 bit = key % ACE_BITS_PER_WORD;
450 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key)
452 u_int word, bit;
453 find (key, word, bit);
455 if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
457 return 1;
459 else
461 ACE_SET_BITS (key_bit_words_[word], 1 << bit);
462 return 0;
467 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key)
469 u_int word, bit;
470 find (key, word, bit);
472 if (word < ACE_WORDS && ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
474 ACE_CLR_BITS (key_bit_words_[word], 1 << bit);
475 return 0;
477 else
479 return 1;
484 ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
486 u_int word, bit;
487 find (key, word, bit);
489 return word < ACE_WORDS ? ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit) : 0;
493 * @class ACE_TSS_Cleanup
494 * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
496 class ACE_TSS_Cleanup
498 public:
499 ACE_ALLOC_HOOK_DECLARE;
501 /// Register a newly-allocated key
502 /// @param key the key to be monitored
503 /// @param destructor the function to call to delete objects stored via this key
504 int insert (ACE_thread_key_t key, void (*destructor)(void *));
506 /// Mark a key as being used by this thread.
507 void thread_use_key (ACE_thread_key_t key);
509 /// This thread is no longer using this key
510 /// call destructor if appropriate
511 int thread_detach_key (ACE_thread_key_t key);
513 /// This key is no longer used
514 /// Release key if use count == 0
515 /// fail if use_count != 0;
516 /// @param key the key to be released
517 int free_key (ACE_thread_key_t key);
519 /// Cleanup the thread-specific objects. Does _NOT_ exit the thread.
520 /// For each used key perform the same actions as free_key.
521 void thread_exit (void);
523 private:
524 void dump (void);
526 /// Release a key used by this thread
527 /// @param info reference to the info for this key
528 /// @param destructor out arg to receive destructor function ptr
529 /// @param tss_obj out arg to receive pointer to deletable object
530 void thread_release (
531 ACE_TSS_Info &info,
532 ACE_TSS_Info::Destructor & destructor,
533 void *& tss_obj);
535 /// remove key if it's unused (thread_count == 0)
536 /// @param info reference to the info for this key
537 int remove_key (ACE_TSS_Info &info);
539 /// Find the TSS keys (if any) for this thread.
540 /// @param thread_keys reference to pointer to be filled in by this function.
541 /// @return false if keys don't exist.
542 bool find_tss_keys (ACE_TSS_Keys *& thread_keys) const;
544 /// Accessor for this threads ACE_TSS_Keys instance.
545 /// Creates the keys if necessary.
546 ACE_TSS_Keys *tss_keys ();
548 /// Ensure singleton.
549 ACE_TSS_Cleanup (void);
550 ~ACE_TSS_Cleanup (void);
552 /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
553 friend class TSS_Cleanup_Instance;
555 private:
556 // Array of <ACE_TSS_Info> objects.
557 typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS];
558 typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR;
560 /// Table of <ACE_TSS_Info>'s.
561 ACE_TSS_TABLE table_;
563 /// Key for the thread-specific ACE_TSS_Keys
564 /// Used by find_tss_keys() or tss_keys() to find the
565 /// bit array that records whether each TSS key is in
566 /// use by this thread.
567 ACE_thread_key_t in_use_;
570 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Cleanup);
571 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Keys);
573 /*****************************************************************************/
575 * @class TSS_Cleanup_Instance
576 * @A class to manage an instance pointer to ACE_TSS_Cleanup.
577 * Note: that the double checked locking pattern doesn't allow
578 * safe deletion.
579 * Callers who wish to access the singleton ACE_TSS_Cleanup must
580 * do so by instantiating a TSS_Cleanup_Instance, calling the valid
581 * method to be sure the ACE_TSS_Cleanup is available, then using
582 * the TSS_Cleanup_Instance as a pointer to the instance.
583 * Construction argument to the TSS_Cleanup_Instance determines how
584 * it is to be used:
585 * CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
586 * USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
587 * DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
588 * delete it when the TSS_Cleanup_Instance goes out of scope.
591 class TSS_Cleanup_Instance
593 public:
594 enum Purpose
596 CREATE,
597 USE,
598 DESTROY
600 explicit TSS_Cleanup_Instance (Purpose purpose = USE);
601 ~TSS_Cleanup_Instance();
603 bool valid();
604 ACE_TSS_Cleanup * operator ->();
606 private:
608 ACE_TSS_Cleanup * operator *();
610 private:
611 static unsigned int reference_count_;
612 static ACE_TSS_Cleanup * instance_;
613 static ACE_Thread_Mutex* mutex_;
614 static ACE_Condition_Thread_Mutex* condition_;
616 private:
617 ACE_TSS_Cleanup * ptr_;
618 unsigned short flags_;
619 enum
621 FLAG_DELETING = 1,
622 FLAG_VALID_CHECKED = 2
626 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose)
627 : ptr_(0)
628 , flags_(0)
630 // During static construction or construction of the ACE_Object_Manager,
631 // there can be only one thread in this constructor at any one time, so
632 // it's safe to check for a zero mutex_. If it's zero, we create a new
633 // mutex and condition variable.
634 if (mutex_ == 0)
636 ACE_NEW (mutex_, ACE_Thread_Mutex ());
637 ACE_NEW (condition_, ACE_Condition_Thread_Mutex (*mutex_));
640 ACE_GUARD (ACE_Thread_Mutex, m, *mutex_);
642 if (purpose == CREATE)
644 if (instance_ == 0)
646 instance_ = new ACE_TSS_Cleanup();
648 ptr_ = instance_;
649 ++reference_count_;
651 else if(purpose == DESTROY)
653 if (instance_ != 0)
655 ptr_ = instance_;
656 instance_ = 0;
657 ACE_SET_BITS(flags_, FLAG_DELETING);
658 while (reference_count_ > 0)
660 condition_->wait();
664 else // must be normal use
666 ACE_ASSERT(purpose == USE);
667 if (instance_ != 0)
669 ptr_ = instance_;
670 ++reference_count_;
675 TSS_Cleanup_Instance::~TSS_Cleanup_Instance (void)
677 // Variable to hold the mutex_ to delete outside the scope of the
678 // guard.
679 ACE_Thread_Mutex *del_mutex = 0;
681 // scope the guard
683 ACE_GUARD (ACE_Thread_Mutex, guard, *mutex_);
684 if (ptr_ != 0)
686 if (ACE_BIT_ENABLED (flags_, FLAG_DELETING))
688 ACE_ASSERT(instance_ == 0);
689 ACE_ASSERT(reference_count_ == 0);
690 delete ptr_;
691 del_mutex = mutex_ ;
692 mutex_ = 0;
694 else
696 ACE_ASSERT (reference_count_ > 0);
697 --reference_count_;
698 if (reference_count_ == 0 && instance_ == 0)
699 condition_->signal ();
702 }// end of guard scope
704 if (del_mutex != 0)
706 delete condition_;
707 condition_ = 0;
708 delete del_mutex;
712 bool
713 TSS_Cleanup_Instance::valid()
715 ACE_SET_BITS(flags_, FLAG_VALID_CHECKED);
716 return (this->instance_ != 0);
719 ACE_TSS_Cleanup *
720 TSS_Cleanup_Instance::operator *()
722 ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
723 return instance_;
726 ACE_TSS_Cleanup *
727 TSS_Cleanup_Instance::operator ->()
729 ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
730 return instance_;
733 // = Static object initialization.
734 unsigned int TSS_Cleanup_Instance::reference_count_ = 0;
735 ACE_TSS_Cleanup * TSS_Cleanup_Instance::instance_ = 0;
736 ACE_Thread_Mutex* TSS_Cleanup_Instance::mutex_ = 0;
737 ACE_Condition_Thread_Mutex* TSS_Cleanup_Instance::condition_ = 0;
739 ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void)
743 void
744 ACE_TSS_Cleanup::thread_exit (void)
746 ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
747 // variables to hold the destructors, keys
748 // and pointers to the object to be destructed
749 // the actual destruction is deferred until the guard is released
750 ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
751 void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
752 ACE_thread_key_t keys[ACE_DEFAULT_THREAD_KEYS];
753 // count of items to be destroyed
754 unsigned int d_count = 0;
756 // scope the guard
758 ACE_TSS_CLEANUP_GUARD
760 // if not initialized or already cleaned up
761 ACE_TSS_Keys *this_thread_keys = 0;
762 if (! find_tss_keys (this_thread_keys) )
764 return;
767 // Minor hack: Iterating in reverse order means the LOG buffer which is
768 // accidentally allocated first will be accidentally deallocated (almost)
769 // last -- in case someone logs something from the other destructors.
770 // applications should not count on this behavior because platforms which
771 // do not use ACE_TSS_Cleanup may delete objects in other orders.
772 unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
773 while( key_index > 0)
775 --key_index;
776 ACE_TSS_Info & info = this->table_[key_index];
777 // if this key is in use by this thread
778 if (info.key_in_use () && this_thread_keys->is_set(info.key_))
780 // defer deleting the in-use key until all others have been deleted
781 if(info.key_ != this->in_use_)
783 destructor[d_count] = 0;
784 tss_obj[d_count] = 0;
785 keys[d_count] = 0;
786 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
787 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
789 keys[d_count] = info.key_;
790 ++d_count;
796 // remove the in_use bit vector last
797 u_int use_index = this->in_use_;
798 ACE_TSS_Info & info = this->table_[use_index];
799 destructor[d_count] = 0;
800 tss_obj[d_count] = 0;
801 keys[d_count] = 0;
802 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
803 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
805 keys[d_count] = info.key_;
806 ++d_count;
808 } // end of guard scope
809 for (unsigned int d_index = 0; d_index < d_count; ++d_index)
811 (*destructor[d_index])(tss_obj[d_index]);
812 #if defined (ACE_HAS_TSS_EMULATION)
813 ACE_TSS_Emulation::ts_object (keys[d_index]) = 0;
814 #else // defined (ACE_HAS_TSS_EMULATION)
815 ACE_OS::thr_setspecific_native (keys[d_index], 0);
816 #endif // defined (ACE_HAS_TSS_EMULATION)
820 extern "C" void
821 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
823 delete static_cast <ACE_TSS_Keys *> (tss_keys);
826 ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
827 : in_use_ (ACE_OS::NULL_key)
829 ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
833 ACE_TSS_Cleanup::insert (ACE_thread_key_t key,
834 void (*destructor)(void *))
836 ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
837 ACE_TSS_CLEANUP_GUARD
839 u_int key_index = key;
840 ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
841 if (key_index < ACE_DEFAULT_THREAD_KEYS)
843 ACE_ASSERT (table_[key_index].thread_count_ == -1);
844 table_[key_index] = ACE_TSS_Info (key, destructor);
845 table_[key_index].thread_count_ = 0; // inserting it does not use it
846 // but it does "allocate" it
847 return 0;
849 else
851 return -1;
856 ACE_TSS_Cleanup::free_key (ACE_thread_key_t key)
858 ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
859 ACE_TSS_CLEANUP_GUARD
860 u_int key_index = key;
861 if (key_index < ACE_DEFAULT_THREAD_KEYS)
863 return remove_key (this->table_ [key_index]);
865 return -1;
869 ACE_TSS_Cleanup::remove_key (ACE_TSS_Info &info)
871 // assume CLEANUP_GUARD is held by caller
872 ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
874 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
875 // When this is done, any existing TSS objects controlled by this key are leaked
876 // There is no "right thing" to do in this case
878 // only remove it if all threads are done with it
879 if (info.thread_count_ != 0)
881 return -1;
883 #endif // 0
885 #if !defined (ACE_HAS_TSS_EMULATION)
886 ACE_OS_thread_key_t temp_key = info.key_;
887 ACE_OS::thr_keyfree_native (temp_key);
888 #endif /* !ACE_HAS_TSS_EMULATION */
889 if (info.key_ == this->in_use_)
891 this->in_use_ = ACE_OS::NULL_key;
893 info.key_in_use (0);
894 info.destructor_ = 0;
895 return 0;
899 ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key)
901 // variables to hold the destructor and the object to be destructed
902 // the actual call is deferred until the guard is released
903 ACE_TSS_Info::Destructor destructor = 0;
904 void * tss_obj = 0;
906 // scope the guard
908 ACE_TSS_CLEANUP_GUARD
910 u_int key_index = key;
911 ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0]));
912 // If this entry was never set, just bug out. If it is set, but is the
913 // wrong key, assert.
914 if (this->table_[key_index].key_ == 0)
915 return 0;
916 ACE_ASSERT (this->table_[key_index].key_ == key);
917 ACE_TSS_Info &info = this->table_ [key_index];
919 // sanity check
920 if (!info.key_in_use ())
922 return -1;
925 this->thread_release (info, destructor, tss_obj);
926 } // end of scope for the Guard
927 // if there's a destructor and an object to be destroyed
928 if (destructor != 0 && tss_obj != 0)
930 (*destructor) (tss_obj);
932 return 0;
935 void
936 ACE_TSS_Cleanup::thread_release (
937 ACE_TSS_Info &info,
938 ACE_TSS_Info::Destructor & destructor,
939 void *& tss_obj)
941 // assume guard is held by caller
942 // Find the TSS keys (if any) for this thread
943 // do not create them if they don't exist
944 ACE_TSS_Keys * thread_keys = 0;
945 if (find_tss_keys (thread_keys))
947 // if this key is in use by this thread
948 if (thread_keys->test_and_clear(info.key_) == 0)
950 // save destructor & pointer to tss object
951 // until after the guard is released
952 destructor = info.destructor_;
953 ACE_OS::thr_getspecific (info.key_, &tss_obj);
954 ACE_ASSERT (info.thread_count_ > 0);
955 --info.thread_count_;
960 void
961 ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key)
963 // If the key's ACE_TSS_Info in-use bit for this thread is not set,
964 // set it and increment the key's thread_count_.
965 if (! tss_keys ()->test_and_set (key))
967 ACE_TSS_CLEANUP_GUARD
969 // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
970 u_int key_index = key;
971 ACE_TSS_Info &key_info = this->table_ [key_index];
973 ACE_ASSERT (key_info.key_in_use ());
974 ++key_info.thread_count_;
978 void
979 ACE_TSS_Cleanup::dump (void)
981 # if defined (ACE_HAS_DUMP)
982 // Iterate through all the thread-specific items and dump them all.
984 ACE_TSS_TABLE_ITERATOR key_info = table_;
985 for (unsigned int i = 0;
986 i < ACE_DEFAULT_THREAD_KEYS;
987 ++key_info, ++i)
988 key_info->dump ();
989 # endif /* ACE_HAS_DUMP */
992 bool
993 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys *& tss_keys) const
995 if (this->in_use_ == ACE_OS::NULL_key)
996 return false;
997 if (ACE_OS::thr_getspecific (in_use_,
998 reinterpret_cast<void **> (&tss_keys)) == -1)
1000 ACE_ASSERT (false);
1001 return false; // This should not happen!
1003 return tss_keys != 0;
1006 ACE_TSS_Keys *
1007 ACE_TSS_Cleanup::tss_keys ()
1009 if (this->in_use_ == ACE_OS::NULL_key)
1011 ACE_TSS_CLEANUP_GUARD
1012 // Double-check;
1013 if (in_use_ == ACE_OS::NULL_key)
1015 // Initialize in_use_ with a new key.
1016 if (ACE_OS::thr_keycreate (&in_use_,
1017 &ACE_TSS_Cleanup_keys_destroyer))
1019 ACE_ASSERT (false);
1020 return 0; // Major problems, this should *never* happen!
1025 void *ts_keys = 0;
1026 if (ACE_OS::thr_getspecific (in_use_, &ts_keys) == -1)
1028 ACE_ASSERT (false);
1029 return 0; // This should not happen!
1032 if (ts_keys == 0)
1034 ACE_NEW_RETURN (ts_keys,
1035 ACE_TSS_Keys,
1037 // Store the dynamically allocated pointer in thread-specific
1038 // storage.
1039 if (ACE_OS::thr_setspecific (in_use_, ts_keys) == -1)
1041 ACE_ASSERT (false);
1042 delete reinterpret_cast <ACE_TSS_Keys*> (ts_keys);
1043 return 0; // Major problems, this should *never* happen!
1047 return reinterpret_cast <ACE_TSS_Keys*>(ts_keys);
1050 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
1052 /*****************************************************************************/
1054 // = Static initialization.
1056 // This is necessary to deal with POSIX pthreads insanity. This
1057 // guarantees that we've got a "zero'd" thread id even when
1058 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
1059 // as structures... Under no circumstances should these be given
1060 // initial values.
1061 // Note: these three objects require static construction.
1062 ACE_thread_t ACE_OS::NULL_thread;
1063 ACE_hthread_t ACE_OS::NULL_hthread;
1064 #if defined (ACE_HAS_TSS_EMULATION)
1065 ACE_thread_key_t ACE_OS::NULL_key = static_cast <ACE_thread_key_t> (-1);
1066 #else /* ! ACE_HAS_TSS_EMULATION */
1067 ACE_thread_key_t ACE_OS::NULL_key;
1068 #endif /* ! ACE_HAS_TSS_EMULATION */
1070 /*****************************************************************************/
1072 void
1073 ACE_OS::cleanup_tss (const u_int main_thread)
1075 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
1076 { // scope the cleanup instance
1077 // Call TSS destructors for current thread.
1078 TSS_Cleanup_Instance cleanup;
1079 if (cleanup.valid ())
1081 cleanup->thread_exit ();
1084 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
1086 if (main_thread)
1088 #if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS)
1089 // Just close the ACE_Log_Msg for the current (which should be
1090 // main) thread. We don't have TSS emulation; if there's native
1091 // TSS, it should call its destructors when the main thread
1092 // exits.
1093 ACE_Base_Thread_Adapter::close_log_msg ();
1094 #endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
1096 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
1097 // Finally, free up the ACE_TSS_Cleanup instance. This method gets
1098 // called by the ACE_Object_Manager.
1099 TSS_Cleanup_Instance cleanup(TSS_Cleanup_Instance::DESTROY);
1100 if (cleanup.valid ())
1102 ; // the pointer deletes the Cleanup when it goes out of scope
1105 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
1107 #if defined (ACE_HAS_TSS_EMULATION)
1108 ACE_TSS_Emulation::tss_close ();
1109 #endif /* ACE_HAS_TSS_EMULATION */
1113 /*****************************************************************************/
1114 // CONDITIONS BEGIN
1115 /*****************************************************************************/
1117 #if defined (ACE_LACKS_COND_T)
1119 ACE_OS::cond_broadcast (ACE_cond_t *cv)
1121 ACE_OS_TRACE ("ACE_OS::cond_broadcast");
1122 # if defined (ACE_HAS_THREADS)
1123 // The <external_mutex> must be locked before this call is made.
1125 // This is needed to ensure that <waiters_> and <was_broadcast_> are
1126 // consistent relative to each other.
1127 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1129 return -1;
1132 bool have_waiters = false;
1134 if (cv->waiters_ > 0)
1136 // We are broadcasting, even if there is just one waiter...
1137 // Record the fact that we are broadcasting. This helps the
1138 // cond_wait() method know how to optimize itself. Be sure to
1139 // set this with the <waiters_lock_> held.
1140 cv->was_broadcast_ = 1;
1141 have_waiters = true;
1144 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1146 // This is really bad, we have the lock but can't release it anymore
1147 return -1;
1150 int result = 0;
1151 if (have_waiters)
1153 // Wake up all the waiters.
1154 if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1)
1155 result = -1;
1156 // Wait for all the awakened threads to acquire their part of
1157 // the counting semaphore.
1158 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1159 else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1)
1160 # else
1161 else if (ACE_OS::event_wait (&cv->waiters_done_) == -1)
1162 # endif /* ACE_VXWORKS */
1163 result = -1;
1164 // This is okay, even without the <waiters_lock_> held because
1165 // no other waiter threads can wake up to access it.
1166 cv->was_broadcast_ = 0;
1168 return result;
1169 # else
1170 ACE_UNUSED_ARG (cv);
1171 ACE_NOTSUP_RETURN (-1);
1172 # endif /* ACE_HAS_THREADS */
1176 ACE_OS::cond_destroy (ACE_cond_t *cv)
1178 ACE_OS_TRACE ("ACE_OS::cond_destroy");
1179 # if defined (ACE_HAS_THREADS)
1180 # if defined (ACE_HAS_WTHREADS)
1181 ACE_OS::event_destroy (&cv->waiters_done_);
1182 # elif defined (ACE_VXWORKS) || defined (ACE_MQX)
1183 ACE_OS::sema_destroy (&cv->waiters_done_);
1184 # endif /* ACE_VXWORKS */
1185 int result = 0;
1186 if (ACE_OS::thread_mutex_destroy (&cv->waiters_lock_) != 0)
1187 result = -1;
1189 if (ACE_OS::sema_destroy (&cv->sema_) != 0)
1190 result = -1;
1192 return result;
1193 # else
1194 ACE_UNUSED_ARG (cv);
1195 ACE_NOTSUP_RETURN (-1);
1196 # endif /* ACE_HAS_THREADS */
1200 ACE_OS::cond_init (ACE_cond_t *cv,
1201 ACE_condattr_t &attributes,
1202 const char *name, void *arg)
1204 return
1205 ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
1208 # if defined (ACE_HAS_WCHAR)
1210 ACE_OS::cond_init (ACE_cond_t *cv,
1211 ACE_condattr_t &attributes,
1212 const wchar_t *name, void *arg)
1214 return
1215 ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
1217 # endif /* ACE_HAS_WCHAR */
1220 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
1222 ACE_OS_TRACE ("ACE_OS::cond_init");
1223 # if defined (ACE_HAS_THREADS)
1224 cv->waiters_ = 0;
1225 cv->was_broadcast_ = 0;
1227 int result = 0;
1228 if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
1229 result = -1;
1230 else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
1231 result = -1;
1232 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1233 else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
1234 # else
1235 else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
1236 # endif /* ACE_VXWORKS */
1237 result = -1;
1238 return result;
1239 # else
1240 ACE_UNUSED_ARG (cv);
1241 ACE_UNUSED_ARG (type);
1242 ACE_UNUSED_ARG (name);
1243 ACE_UNUSED_ARG (arg);
1244 ACE_NOTSUP_RETURN (-1);
1245 # endif /* ACE_HAS_THREADS */
1248 # if defined (ACE_HAS_WCHAR)
1250 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
1252 ACE_OS_TRACE ("ACE_OS::cond_init");
1253 # if defined (ACE_HAS_THREADS)
1254 cv->waiters_ = 0;
1255 cv->was_broadcast_ = 0;
1257 int result = 0;
1258 if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
1259 result = -1;
1260 else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
1261 result = -1;
1262 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1263 else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
1264 # else
1265 else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
1266 # endif /* ACE_VXWORKS */
1267 result = -1;
1268 return result;
1269 # else
1270 ACE_UNUSED_ARG (cv);
1271 ACE_UNUSED_ARG (type);
1272 ACE_UNUSED_ARG (name);
1273 ACE_UNUSED_ARG (arg);
1274 ACE_NOTSUP_RETURN (-1);
1275 # endif /* ACE_HAS_THREADS */
1277 # endif /* ACE_HAS_WCHAR */
1280 ACE_OS::cond_signal (ACE_cond_t *cv)
1282 ACE_OS_TRACE ("ACE_OS::cond_signal");
1283 # if defined (ACE_HAS_THREADS)
1284 // If there aren't any waiters, then this is a no-op. Note that
1285 // this function *must* be called with the <external_mutex> held
1286 // since other wise there is a race condition that can lead to the
1287 // lost wakeup bug... This is needed to ensure that the <waiters_>
1288 // value is not in an inconsistent internal state while being
1289 // updated by another thread.
1290 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1291 return -1;
1292 bool const have_waiters = cv->waiters_ > 0;
1293 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1294 return -1;
1296 if (have_waiters)
1297 return ACE_OS::sema_post (&cv->sema_);
1298 else
1299 return 0; // No-op
1300 # else
1301 ACE_UNUSED_ARG (cv);
1302 ACE_NOTSUP_RETURN (-1);
1303 # endif /* ACE_HAS_THREADS */
1307 ACE_OS::cond_wait (ACE_cond_t *cv,
1308 ACE_mutex_t *external_mutex)
1310 ACE_OS_TRACE ("ACE_OS::cond_wait");
1311 # if defined (ACE_HAS_THREADS)
1312 // Prevent race conditions on the <waiters_> count.
1313 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1314 return -1;
1316 ++cv->waiters_;
1318 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1319 return -1;
1321 int result = 0;
1323 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1324 if (external_mutex->type_ == USYNC_PROCESS)
1326 // This call will automatically release the mutex and wait on the semaphore.
1327 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_,
1328 cv->sema_, INFINITE, FALSE),
1329 result),
1330 int, -1, result);
1331 if (result == -1)
1332 return result;
1334 else
1335 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1337 // We keep the lock held just long enough to increment the count of
1338 // waiters by one. Note that we can't keep it held across the call
1339 // to ACE_OS::sema_wait() since that will deadlock other calls to
1340 // ACE_OS::cond_signal().
1341 if (ACE_OS::mutex_unlock (external_mutex) != 0)
1342 return -1;
1344 // Wait to be awakened by a ACE_OS::cond_signal() or
1345 // ACE_OS::cond_broadcast().
1346 result = ACE_OS::sema_wait (&cv->sema_);
1349 // Reacquire lock to avoid race conditions on the <waiters_> count.
1350 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1351 return -1;
1353 // We're ready to return, so there's one less waiter.
1354 --cv->waiters_;
1356 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1358 // Release the lock so that other collaborating threads can make
1359 // progress.
1360 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1361 return -1;
1363 if (result == -1)
1364 // Bad things happened, so let's just return below.
1365 /* NOOP */;
1366 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1367 else if (external_mutex->type_ == USYNC_PROCESS)
1369 if (last_waiter)
1371 // This call atomically signals the <waiters_done_> event and
1372 // waits until it can acquire the mutex. This is important to
1373 // prevent unfairness.
1374 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
1375 external_mutex->proc_mutex_,
1376 INFINITE, FALSE),
1377 result),
1378 int, -1, result);
1379 else
1380 // We must always regain the <external_mutex>, even when
1381 // errors occur because that's the guarantee that we give to
1382 // our callers.
1383 if (ACE_OS::mutex_lock (external_mutex) != 0)
1384 return -1;
1386 return result;
1387 /* NOTREACHED */
1389 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1390 // If we're the last waiter thread during this particular broadcast
1391 // then let all the other threads proceed.
1392 else if (last_waiter)
1393 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1394 ACE_OS::sema_post (&cv->waiters_done_);
1395 # else
1396 ACE_OS::event_signal (&cv->waiters_done_);
1397 # endif /* ACE_VXWORKS */
1399 // We must always regain the <external_mutex>, even when errors
1400 // occur because that's the guarantee that we give to our callers.
1401 ACE_OS::mutex_lock (external_mutex);
1403 return result;
1404 # else
1405 ACE_UNUSED_ARG (cv);
1406 ACE_UNUSED_ARG (external_mutex);
1407 ACE_NOTSUP_RETURN (-1);
1408 # endif /* ACE_HAS_THREADS */
1412 ACE_OS::cond_timedwait (ACE_cond_t *cv,
1413 ACE_mutex_t *external_mutex,
1414 ACE_Time_Value *timeout)
1416 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1417 # if defined (ACE_HAS_THREADS)
1418 // Handle the easy case first.
1419 if (timeout == 0)
1420 return ACE_OS::cond_wait (cv, external_mutex);
1421 # if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS) || defined (ACE_MQX)
1423 // Prevent race conditions on the <waiters_> count.
1424 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1425 return -1;
1427 ++cv->waiters_;
1429 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1430 return -1;
1432 int result = 0;
1433 ACE_Errno_Guard error (errno, 0);
1434 int msec_timeout = 0;
1436 if (timeout != 0 && *timeout != ACE_Time_Value::zero)
1438 // Note that we must convert between absolute time (which is
1439 // passed as a parameter) and relative time (which is what
1440 // WaitForSingleObjects() expects).
1441 ACE_Time_Value relative_time = timeout->to_relative_time ();
1443 // Watchout for situations where a context switch has caused the
1444 // current time to be > the timeout.
1445 if (relative_time > ACE_Time_Value::zero)
1446 msec_timeout = relative_time.msec ();
1449 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1450 if (external_mutex->type_ == USYNC_PROCESS)
1451 // This call will automatically release the mutex and wait on the
1452 // semaphore.
1453 result = ::SignalObjectAndWait (external_mutex->proc_mutex_,
1454 cv->sema_,
1455 msec_timeout,
1456 FALSE);
1457 else
1458 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1460 // We keep the lock held just long enough to increment the count
1461 // of waiters by one. Note that we can't keep it held across
1462 // the call to WaitForSingleObject since that will deadlock
1463 // other calls to ACE_OS::cond_signal().
1464 if (ACE_OS::mutex_unlock (external_mutex) != 0)
1465 return -1;
1467 // Wait to be awakened by a ACE_OS::signal() or
1468 // ACE_OS::broadcast().
1469 # if defined (ACE_WIN32)
1470 # if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1471 result = ::WaitForSingleObject (cv->sema_, msec_timeout);
1472 # else /* ACE_USES_WINCE_SEMA_SIMULATION */
1473 // Can't use Win32 API on our simulated semaphores.
1474 result = ACE_OS::sema_wait (&cv->sema_,
1475 timeout);
1476 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1477 # elif defined (ACE_VXWORKS)
1478 // Inline the call to ACE_OS::sema_wait () because it takes an
1479 // ACE_Time_Value argument. Avoid the cost of that conversion . . .
1480 int const ticks_per_sec = ::sysClkRateGet ();
1481 int const ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS;
1482 result = ::semTake (cv->sema_.sema_, ticks);
1483 # else
1484 result = ACE_OS::sema_wait (&cv->sema_, timeout);
1485 # endif /* ACE_WIN32 || VXWORKS */
1488 // Reacquire lock to avoid race conditions.
1489 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1490 return -1;
1492 --cv->waiters_;
1494 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1496 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1497 return -1;
1499 # if defined (ACE_WIN32)
1500 if (result != (int)WAIT_OBJECT_0)
1502 switch (result)
1504 case WAIT_TIMEOUT:
1505 error = ETIME;
1506 break;
1507 default:
1508 error = ::GetLastError ();
1509 break;
1511 result = -1;
1513 # elif defined (ACE_VXWORKS)
1514 if (result == ERROR)
1516 switch (errno)
1518 case S_objLib_OBJ_TIMEOUT:
1519 error = ETIME;
1520 break;
1521 case S_objLib_OBJ_UNAVAILABLE:
1522 if (msec_timeout == 0)
1523 error = ETIME;
1524 break;
1525 default:
1526 error = errno;
1527 break;
1529 result = -1;
1531 # endif /* ACE_WIN32 || VXWORKS */
1532 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1533 if (external_mutex->type_ == USYNC_PROCESS)
1535 if (last_waiter)
1536 // This call atomically signals the <waiters_done_> event and
1537 // waits until it can acquire the mutex. This is important to
1538 // prevent unfairness.
1539 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
1540 external_mutex->proc_mutex_,
1541 INFINITE, FALSE),
1542 result),
1543 int, -1, result);
1544 else
1546 // We must always regain the <external_Mutex>, even when
1547 // errors occur because that's the guarantee that we give to
1548 // our callers.
1549 if (ACE_OS::mutex_lock (external_mutex) != 0)
1550 return -1;
1553 return result;
1554 /* NOTREACHED */
1556 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1557 // Note that this *must* be an "if" statement rather than an "else
1558 // if" statement since the caller may have timed out and hence the
1559 // result would have been -1 above.
1560 if (last_waiter)
1562 // Release the signaler/broadcaster if we're the last waiter.
1563 # if defined (ACE_WIN32)
1564 if (ACE_OS::event_signal (&cv->waiters_done_) != 0)
1565 # else
1566 if (ACE_OS::sema_post (&cv->waiters_done_) != 0)
1567 # endif /* ACE_WIN32 */
1568 return -1;
1571 // We must always regain the <external_mutex>, even when errors
1572 // occur because that's the guarantee that we give to our callers.
1573 if (ACE_OS::mutex_lock (external_mutex) != 0)
1574 return -1;
1576 return result;
1577 # endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
1578 # else
1579 ACE_UNUSED_ARG (cv);
1580 ACE_UNUSED_ARG (external_mutex);
1581 ACE_UNUSED_ARG (timeout);
1582 ACE_NOTSUP_RETURN (-1);
1583 # endif /* ACE_HAS_THREADS */
1585 #else
1587 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
1589 ACE_condattr_t attributes;
1590 if (ACE_OS::condattr_init (attributes, type) == 0
1591 && ACE_OS::cond_init (cv, attributes, name, arg) == 0)
1593 (void) ACE_OS::condattr_destroy (attributes);
1594 return 0;
1596 return -1;
1598 #endif /* ACE_LACKS_COND_T */
1600 #if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS)
1602 ACE_OS::cond_timedwait (ACE_cond_t *cv,
1603 ACE_thread_mutex_t *external_mutex,
1604 ACE_Time_Value *timeout)
1606 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1607 # if defined (ACE_HAS_THREADS)
1608 // Handle the easy case first.
1609 if (timeout == 0)
1610 return ACE_OS::cond_wait (cv, external_mutex);
1612 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1613 int msec_timeout = 0;
1614 int result = 0;
1616 ACE_Time_Value relative_time = timeout->to_relative_time ();
1617 // Watchout for situations where a context switch has caused the
1618 // current time to be > the timeout.
1619 if (relative_time > ACE_Time_Value::zero)
1620 msec_timeout = relative_time.msec ();
1622 ACE_OSCALL (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, external_mutex, msec_timeout),
1623 result),
1624 int, -1, result);
1625 return result;
1626 #else
1627 // Prevent race conditions on the <waiters_> count.
1628 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1629 return -1;
1631 ++cv->waiters_;
1633 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1634 return -1;
1636 int result = 0;
1637 int error = 0;
1638 int msec_timeout = 0;
1640 if (timeout != 0 && *timeout != ACE_Time_Value::zero)
1642 // Note that we must convert between absolute time (which is
1643 // passed as a parameter) and relative time (which is what
1644 // WaitForSingleObjects() expects).
1645 ACE_Time_Value relative_time = timeout->to_relative_time ();
1647 // Watchout for situations where a context switch has caused the
1648 // current time to be > the timeout.
1649 if (relative_time > ACE_Time_Value::zero)
1650 msec_timeout = relative_time.msec ();
1653 // We keep the lock held just long enough to increment the count of
1654 // waiters by one. Note that we can't keep it held across the call
1655 // to WaitForSingleObject since that will deadlock other calls to
1656 // ACE_OS::cond_signal().
1657 if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
1658 return -1;
1660 // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
1661 # if defined (ACE_USES_WINCE_SEMA_SIMULATION)
1662 // Can't use Win32 API on simulated semaphores.
1663 result = ACE_OS::sema_wait (&cv->sema_,
1664 timeout);
1666 if (result == -1 && errno == ETIME)
1667 result = WAIT_TIMEOUT;
1668 # else
1669 result = ::WaitForSingleObject (cv->sema_, msec_timeout);
1670 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1672 // Reacquire lock to avoid race conditions.
1673 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1674 return -1;
1676 --cv->waiters_;
1678 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1680 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1681 return -1;
1683 if (result != (int)WAIT_OBJECT_0)
1685 switch (result)
1687 case WAIT_TIMEOUT:
1688 error = ETIME;
1689 break;
1690 default:
1691 error = ::GetLastError ();
1692 break;
1694 result = -1;
1697 if (last_waiter)
1699 // Release the signaler/broadcaster if we're the last waiter.
1700 if (ACE_OS::event_signal (&cv->waiters_done_) != 0)
1701 return -1;
1704 // We must always regain the <external_mutex>, even when errors
1705 // occur because that's the guarantee that we give to our callers.
1706 if (ACE_OS::thread_mutex_lock (external_mutex) != 0)
1707 result = -1;
1709 if (error != 0)
1711 /* This assignment must only be done if error != 0,
1712 * since writing 0 to errno violates the POSIX specification.
1714 errno = error;
1716 return result;
1717 # endif
1718 # else
1719 ACE_NOTSUP_RETURN (-1);
1720 # endif /* ACE_HAS_THREADS */
1724 ACE_OS::cond_wait (ACE_cond_t *cv,
1725 ACE_thread_mutex_t *external_mutex)
1727 ACE_OS_TRACE ("ACE_OS::cond_wait");
1728 # if defined (ACE_HAS_THREADS)
1729 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1730 int result;
1731 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv, external_mutex, INFINITE), result),
1732 int, -1);
1733 #else
1734 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1735 return -1;
1736 ++cv->waiters_;
1738 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1739 return -1;
1741 int result = 0;
1742 int error = 0;
1744 // We keep the lock held just long enough to increment the count of
1745 // waiters by one. Note that we can't keep it held across the call
1746 // to ACE_OS::sema_wait() since that will deadlock other calls to
1747 // ACE_OS::cond_signal().
1748 if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
1749 return -1;
1751 // Wait to be awakened by a ACE_OS::cond_signal() or
1752 // ACE_OS::cond_broadcast().
1753 # if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1754 result = ::WaitForSingleObject (cv->sema_, INFINITE);
1755 # else
1756 // Can't use Win32 API on simulated semaphores.
1757 result = ACE_OS::sema_wait (&cv->sema_);
1759 if (result != WAIT_OBJECT_0 && errno == ETIME)
1760 result = WAIT_TIMEOUT;
1762 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1764 // Reacquire lock to avoid race conditions.
1765 if (ACE_OS::thread_mutex_lock (&cv->waiters_lock_) != 0)
1766 return -1;
1768 cv->waiters_--;
1770 bool const last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1772 if (ACE_OS::thread_mutex_unlock (&cv->waiters_lock_) != 0)
1773 return -1;
1775 if (result != (int)WAIT_OBJECT_0)
1777 switch (result)
1779 case WAIT_TIMEOUT:
1780 error = ETIME;
1781 break;
1782 default:
1783 error = ::GetLastError ();
1784 break;
1787 else if (last_waiter)
1789 // Release the signaler/broadcaster if we're the last waiter.
1790 if (ACE_OS::event_signal (&cv->waiters_done_) != 0)
1791 return -1;
1794 // We must always regain the <external_mutex>, even when errors
1795 // occur because that's the guarantee that we give to our callers.
1796 if (ACE_OS::thread_mutex_lock (external_mutex) != 0)
1797 result = -1;
1799 // Reset errno in case mutex_lock() also fails...
1800 if (error != 0)
1802 /* This assignment must only be done if error != 0,
1803 * since writing 0 to errno violates the POSIX specification.
1805 errno = error;
1807 return result;
1808 #endif
1809 # else
1810 ACE_NOTSUP_RETURN (-1);
1811 # endif /* ACE_HAS_THREADS */
1813 # endif /* ACE_HAS_WTHREADS */
1815 /*****************************************************************************/
1816 // CONDITIONS END
1817 /*****************************************************************************/
1819 /*****************************************************************************/
1820 // MUTEXES BEGIN
1821 /*****************************************************************************/
1824 ACE_OS::mutex_init (ACE_mutex_t *m,
1825 int lock_scope,
1826 const char *name,
1827 ACE_mutexattr_t *attributes,
1828 LPSECURITY_ATTRIBUTES sa,
1829 int lock_type)
1831 // ACE_OS_TRACE ("ACE_OS::mutex_init");
1832 #if defined (ACE_HAS_THREADS)
1833 # if defined (ACE_HAS_PTHREADS)
1834 ACE_UNUSED_ARG (name);
1835 ACE_UNUSED_ARG (sa);
1837 # if defined (ACE_PTHREAD_MUTEXATTR_T_INITIALIZE)
1838 /* Tests show that VxWorks 6.x pthread lib does not only
1839 * require zeroing of mutex/condition objects to function correctly
1840 * but also of the attribute objects.
1842 pthread_mutexattr_t l_attributes = {0};
1843 # else
1844 pthread_mutexattr_t l_attributes;
1845 # endif
1847 if (attributes == 0)
1848 attributes = &l_attributes;
1849 int result = 0;
1850 int attr_init = 0; // have we initialized the local attributes.
1852 // Only do these initializations if the <attributes> parameter
1853 // wasn't originally set.
1854 if (attributes == &l_attributes)
1856 if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0)
1858 result = 0;
1859 attr_init = 1; // we have initialized these attributes
1861 else
1863 result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
1867 if (result == 0 && lock_scope != 0)
1869 # if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
1870 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes,
1871 lock_scope),
1872 result);
1873 # endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
1876 if (result == 0 && lock_type != 0)
1878 # if defined (ACE_HAS_RECURSIVE_MUTEXES) && !defined (ACE_LACKS_PTHREAD_MUTEXATTR_SETTYPE)
1879 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes,
1880 lock_type),
1881 result);
1882 # endif /* ACE_HAS_RECURSIVE_MUTEXES */
1885 if (result == 0)
1887 # if defined (ACE_PTHREAD_MUTEX_T_INITIALIZE)
1888 /* VxWorks 6.x API reference states:
1889 * If the memory for the mutex variable object has been allocated
1890 * dynamically, it is a good policy to always zero out the
1891 * block of memory so as to avoid spurious EBUSY return code
1892 * when calling this routine.
1893 * Tests shows this to be necessary.
1895 ACE_OS::memset (m, 0, sizeof (*m));
1896 # endif
1897 if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0)
1898 result = 0;
1899 else
1900 result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
1903 // Only do the deletions if the <attributes> parameter wasn't
1904 // originally set.
1905 if (attributes == &l_attributes && attr_init)
1906 ::pthread_mutexattr_destroy (&l_attributes);
1908 return result;
1909 # elif defined (ACE_HAS_STHREADS)
1910 ACE_UNUSED_ARG (name);
1911 ACE_UNUSED_ARG (sa);
1912 ACE_UNUSED_ARG (lock_type);
1913 int result;
1914 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m,
1915 lock_scope,
1916 attributes),
1917 result),
1918 int, -1);
1919 # elif defined (ACE_HAS_WTHREADS)
1920 m->type_ = lock_scope;
1922 SECURITY_ATTRIBUTES sa_buffer;
1923 SECURITY_DESCRIPTOR sd_buffer;
1924 switch (lock_scope)
1926 case USYNC_PROCESS:
1927 # if defined (ACE_HAS_WINCE)
1928 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
1929 m->proc_mutex_ =
1930 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1931 (sa, &sa_buffer, &sd_buffer),
1932 FALSE,
1933 ACE_Ascii_To_Wide (name).wchar_rep ());
1934 # else /* ACE_HAS_WINCE */
1935 m->proc_mutex_ =
1936 ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
1937 (sa, &sa_buffer, &sd_buffer),
1938 FALSE,
1939 name);
1940 # endif /* ACE_HAS_WINCE */
1941 if (m->proc_mutex_ == 0)
1942 ACE_FAIL_RETURN (-1);
1943 else
1945 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1946 ACE_OS::set_errno_to_last_error ();
1947 return 0;
1949 case USYNC_THREAD:
1950 return ACE_OS::thread_mutex_init (&m->thr_mutex_,
1951 lock_type,
1952 name,
1953 attributes);
1954 default:
1955 errno = EINVAL;
1956 return -1;
1958 /* NOTREACHED */
1960 # elif defined (ACE_VXWORKS)
1961 ACE_UNUSED_ARG (name);
1962 ACE_UNUSED_ARG (attributes);
1963 ACE_UNUSED_ARG (sa);
1964 ACE_UNUSED_ARG (lock_type);
1966 return (*m = ::semMCreate (lock_scope)) == 0 ? -1 : 0;
1967 # endif /* ACE_HAS_PTHREADS */
1968 #else
1969 ACE_UNUSED_ARG (m);
1970 ACE_UNUSED_ARG (lock_scope);
1971 ACE_UNUSED_ARG (name);
1972 ACE_UNUSED_ARG (attributes);
1973 ACE_UNUSED_ARG (sa);
1974 ACE_UNUSED_ARG (lock_type);
1975 ACE_NOTSUP_RETURN (-1);
1976 #endif /* ACE_HAS_THREADS */
1980 ACE_OS::mutex_destroy (ACE_mutex_t *m)
1982 ACE_OS_TRACE ("ACE_OS::mutex_destroy");
1983 #if defined (ACE_HAS_THREADS)
1984 # if defined (ACE_HAS_PTHREADS)
1985 # if defined (ACE_LACKS_PTHREAD_MUTEX_DESTROY)
1986 ACE_UNUSED_ARG (m);
1987 ACE_NOTSUP_RETURN (-1);
1988 # else
1989 int result;
1990 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m),
1991 result), int, -1);
1992 # endif /* ACE_LACKS_PTHREAD_MUTEX_DESTROY */
1993 # elif defined (ACE_HAS_STHREADS)
1994 int result;
1995 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), result), int, -1);
1996 # elif defined (ACE_HAS_WTHREADS)
1997 switch (m->type_)
1999 case USYNC_PROCESS:
2000 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_),
2001 ace_result_),
2002 int, -1);
2003 case USYNC_THREAD:
2004 return ACE_OS::thread_mutex_destroy (&m->thr_mutex_);
2005 default:
2006 errno = EINVAL;
2007 return -1;
2009 /* NOTREACHED */
2010 # elif defined (ACE_VXWORKS)
2011 return ::semDelete (*m) == OK ? 0 : -1;
2012 # endif /* Threads variety case */
2013 #else
2014 ACE_UNUSED_ARG (m);
2015 ACE_NOTSUP_RETURN (-1);
2016 #endif /* ACE_HAS_THREADS */
2019 #if defined (ACE_HAS_WCHAR)
2021 ACE_OS::mutex_init (ACE_mutex_t *m,
2022 int lock_scope,
2023 const wchar_t *name,
2024 ACE_mutexattr_t *attributes,
2025 LPSECURITY_ATTRIBUTES sa,
2026 int lock_type)
2028 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2029 m->type_ = lock_scope;
2030 SECURITY_ATTRIBUTES sa_buffer;
2031 SECURITY_DESCRIPTOR sd_buffer;
2032 switch (lock_scope)
2034 case USYNC_PROCESS:
2035 m->proc_mutex_ =
2036 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
2037 (sa, &sa_buffer, &sd_buffer),
2038 FALSE,
2039 name);
2040 if (m->proc_mutex_ == 0)
2041 ACE_FAIL_RETURN (-1);
2042 else
2044 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
2045 ACE_OS::set_errno_to_last_error ();
2046 return 0;
2048 case USYNC_THREAD:
2049 return ACE_OS::thread_mutex_init (&m->thr_mutex_,
2050 lock_type,
2051 name,
2052 attributes);
2055 errno = EINVAL;
2056 return -1;
2057 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2058 return ACE_OS::mutex_init (m,
2059 lock_scope,
2060 ACE_Wide_To_Ascii (name).char_rep (),
2061 attributes,
2063 lock_type);
2064 #endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2066 #endif /* ACE_HAS_WCHAR */
2069 ACE_OS::mutex_lock (ACE_mutex_t *m)
2071 // ACE_OS_TRACE ("ACE_OS::mutex_lock");
2072 #if defined (ACE_HAS_THREADS)
2073 # if defined (ACE_HAS_PTHREADS)
2074 // Note, don't use "::" here since the following call is often a macro.
2075 int result;
2076 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), result),
2077 int, -1);
2078 # elif defined (ACE_HAS_STHREADS)
2079 int result;
2080 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), result), int, -1);
2081 # elif defined (ACE_HAS_WTHREADS)
2082 switch (m->type_)
2084 case USYNC_PROCESS:
2085 switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
2088 // Timeout can't occur, so don't bother checking...
2090 case WAIT_OBJECT_0:
2091 case WAIT_ABANDONED:
2092 // We will ignore abandonments in this method
2093 // Note that we still hold the lock
2094 return 0;
2095 default:
2096 // This is a hack, we need to find an appropriate mapping...
2097 ACE_OS::set_errno_to_last_error ();
2098 return -1;
2100 case USYNC_THREAD:
2101 return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
2102 default:
2103 errno = EINVAL;
2104 return -1;
2106 /* NOTREACHED */
2107 # elif defined (ACE_VXWORKS)
2108 return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1;
2109 # endif /* Threads variety case */
2110 #else
2111 ACE_UNUSED_ARG (m);
2112 ACE_NOTSUP_RETURN (-1);
2113 #endif /* ACE_HAS_THREADS */
2117 ACE_OS::mutex_lock (ACE_mutex_t *m,
2118 int &abandoned)
2120 ACE_OS_TRACE ("ACE_OS::mutex_lock");
2121 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2122 abandoned = 0;
2123 switch (m->type_)
2125 case USYNC_PROCESS:
2126 switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
2129 // Timeout can't occur, so don't bother checking...
2131 case WAIT_OBJECT_0:
2132 return 0;
2133 case WAIT_ABANDONED:
2134 abandoned = 1;
2135 return 0; // something goofed, but we hold the lock ...
2136 default:
2137 // This is a hack, we need to find an appropriate mapping...
2138 ACE_OS::set_errno_to_last_error ();
2139 return -1;
2141 case USYNC_THREAD:
2142 return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
2143 default:
2144 errno = EINVAL;
2145 return -1;
2147 /* NOTREACHED */
2148 #else
2149 ACE_UNUSED_ARG (m);
2150 ACE_UNUSED_ARG (abandoned);
2151 ACE_NOTSUP_RETURN (-1);
2152 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2156 ACE_OS::mutex_lock (ACE_mutex_t *m,
2157 const ACE_Time_Value &timeout)
2159 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
2161 # if defined (ACE_HAS_PTHREADS)
2162 int result;
2164 // "timeout" should be an absolute time.
2166 timespec_t ts = timeout; // Calls ACE_Time_Value::operator timespec_t().
2168 // Note that the mutex should not be a recursive one, i.e., it
2169 // should only be a standard mutex or an error checking mutex.
2171 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, -1, result);
2173 // We need to adjust this to make the errno values consistent.
2174 if (result == -1 && errno == ETIMEDOUT)
2175 errno = ETIME;
2176 return result;
2178 # elif defined (ACE_HAS_WTHREADS)
2179 // Note that we must convert between absolute time (which is passed
2180 // as a parameter) and relative time (which is what the system call
2181 // expects).
2182 ACE_Time_Value relative_time = timeout.to_relative_time ();
2184 switch (m->type_)
2186 case USYNC_PROCESS:
2187 switch (::WaitForSingleObject (m->proc_mutex_,
2188 relative_time.msec ()))
2190 case WAIT_OBJECT_0:
2191 case WAIT_ABANDONED:
2192 // We will ignore abandonments in this method
2193 // Note that we still hold the lock
2194 return 0;
2195 case WAIT_TIMEOUT:
2196 errno = ETIME;
2197 return -1;
2198 default:
2199 // This is a hack, we need to find an appropriate mapping...
2200 ACE_OS::set_errno_to_last_error ();
2201 return -1;
2203 case USYNC_THREAD:
2204 ACE_NOTSUP_RETURN (-1);
2205 default:
2206 errno = EINVAL;
2207 return -1;
2209 /* NOTREACHED */
2211 # elif defined (ACE_VXWORKS)
2213 // Note that we must convert between absolute time (which is passed
2214 // as a parameter) and relative time (which is what the system call
2215 // expects).
2216 ACE_Time_Value relative_time = timeout.to_relative_time ();
2218 int ticks_per_sec = ::sysClkRateGet ();
2220 int ticks = relative_time.sec() * ticks_per_sec +
2221 relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
2222 if (::semTake (*m, ticks) == ERROR)
2224 if (errno == S_objLib_OBJ_TIMEOUT)
2225 // Convert the VxWorks errno to one that's common for to ACE
2226 // platforms.
2227 errno = ETIME;
2228 else if (errno == S_objLib_OBJ_UNAVAILABLE)
2229 errno = EBUSY;
2230 return -1;
2232 else
2233 return 0;
2234 # endif /* ACE_HAS_PTHREADS */
2236 #else
2237 ACE_UNUSED_ARG (m);
2238 ACE_UNUSED_ARG (timeout);
2239 ACE_NOTSUP_RETURN (-1);
2240 #endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
2244 ACE_OS::mutex_trylock (ACE_mutex_t *m)
2246 ACE_OS_TRACE ("ACE_OS::mutex_trylock");
2247 #if defined (ACE_HAS_THREADS)
2248 # if defined (ACE_HAS_PTHREADS)
2249 // Note, don't use "::" here since the following call is often a macro.
2250 int result;
2251 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), result),
2252 int, -1);
2253 # elif defined (ACE_HAS_STHREADS)
2254 int result;
2255 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), result), int, -1);
2256 # elif defined (ACE_HAS_WTHREADS)
2257 switch (m->type_)
2259 case USYNC_PROCESS:
2261 // Try for 0 milliseconds - i.e. nonblocking.
2262 switch (::WaitForSingleObject (m->proc_mutex_, 0))
2264 case WAIT_OBJECT_0:
2265 return 0;
2266 case WAIT_ABANDONED:
2267 // We will ignore abandonments in this method. Note that
2268 // we still hold the lock.
2269 return 0;
2270 case WAIT_TIMEOUT:
2271 errno = EBUSY;
2272 return -1;
2273 default:
2274 ACE_OS::set_errno_to_last_error ();
2275 return -1;
2278 case USYNC_THREAD:
2279 return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
2280 default:
2281 errno = EINVAL;
2282 return -1;
2284 /* NOTREACHED */
2285 # elif defined (ACE_VXWORKS)
2286 if (::semTake (*m, NO_WAIT) == ERROR)
2287 if (errno == S_objLib_OBJ_UNAVAILABLE)
2289 // couldn't get the semaphore
2290 errno = EBUSY;
2291 return -1;
2293 else
2294 // error
2295 return -1;
2296 else
2297 // got the semaphore
2298 return 0;
2299 # endif /* Threads variety case */
2300 #else
2301 ACE_UNUSED_ARG (m);
2302 ACE_NOTSUP_RETURN (-1);
2303 #endif /* ACE_HAS_THREADS */
2307 ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned)
2309 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2310 abandoned = 0;
2311 switch (m->type_)
2313 case USYNC_PROCESS:
2315 // Try for 0 milliseconds - i.e. nonblocking.
2316 switch (::WaitForSingleObject (m->proc_mutex_, 0))
2318 case WAIT_OBJECT_0:
2319 return 0;
2320 case WAIT_ABANDONED:
2321 abandoned = 1;
2322 return 0; // something goofed, but we hold the lock ...
2323 case WAIT_TIMEOUT:
2324 errno = EBUSY;
2325 return -1;
2326 default:
2327 ACE_OS::set_errno_to_last_error ();
2328 return -1;
2331 case USYNC_THREAD:
2332 return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
2333 default:
2334 errno = EINVAL;
2335 return -1;
2337 /* NOTREACHED */
2338 #else
2339 ACE_UNUSED_ARG (m);
2340 ACE_UNUSED_ARG (abandoned);
2341 ACE_NOTSUP_RETURN (-1);
2342 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2346 ACE_OS::mutex_unlock (ACE_mutex_t *m)
2348 ACE_OS_TRACE ("ACE_OS::mutex_unlock");
2349 #if defined (ACE_HAS_THREADS)
2350 # if defined (ACE_HAS_PTHREADS)
2351 // Note, don't use "::" here since the following call is often a macro.
2352 int result;
2353 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), result),
2354 int, -1);
2355 # elif defined (ACE_HAS_STHREADS)
2356 int result;
2357 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), result), int, -1);
2358 # elif defined (ACE_HAS_WTHREADS)
2359 switch (m->type_)
2361 case USYNC_PROCESS:
2362 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_),
2363 ace_result_),
2364 int, -1);
2365 case USYNC_THREAD:
2366 return ACE_OS::thread_mutex_unlock (&m->thr_mutex_);
2367 default:
2368 errno = EINVAL;
2369 return -1;
2371 /* NOTREACHED */
2372 # elif defined (ACE_VXWORKS)
2373 return ::semGive (*m) == OK ? 0 : -1;
2374 # endif /* Threads variety case */
2375 #else
2376 ACE_UNUSED_ARG (m);
2377 ACE_NOTSUP_RETURN (-1);
2378 #endif /* ACE_HAS_THREADS */
2381 void
2382 ACE_OS::mutex_lock_cleanup (void *mutex)
2384 ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
2385 #if defined (ACE_HAS_THREADS)
2386 # if defined (ACE_HAS_PTHREADS)
2387 ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex;
2388 ACE_OS::mutex_unlock (p_lock);
2389 # else
2390 ACE_UNUSED_ARG (mutex);
2391 # endif /* ACE_HAS_PTHREADS */
2392 #else
2393 ACE_UNUSED_ARG (mutex);
2394 #endif /* ACE_HAS_THREADS */
2397 /*****************************************************************************/
2398 // MUTEXES END
2399 /*****************************************************************************/
2401 /*****************************************************************************/
2402 // EVENTS BEGIN
2403 /*****************************************************************************/
2405 #ifndef ACE_WIN32
2407 int ACE_event_t::lock ()
2409 # if !ACE_EVENT_USE_MUTEX_PSHARED
2410 if (this->eventdata_->type_ == USYNC_PROCESS)
2411 return ACE_OS::sema_wait (&this->lock_);
2412 # endif
2413 return ACE_OS::mutex_lock (&this->eventdata_->lock_);
2416 int ACE_event_t::unlock ()
2418 # if !ACE_EVENT_USE_MUTEX_PSHARED
2419 if (this->eventdata_->type_ == USYNC_PROCESS)
2420 return ACE_OS::sema_post (&this->lock_);
2421 # endif
2422 return ACE_OS::mutex_unlock (&this->eventdata_->lock_);
2425 int ACE_event_t::wake_one ()
2427 # if !ACE_EVENT_USE_COND_PSHARED
2428 if (this->eventdata_->type_ == USYNC_PROCESS)
2430 if (ACE_OS::sema_post (&this->semaphore_) != 0)
2431 return -1;
2433 else
2434 # endif
2435 if (ACE_OS::cond_signal (&this->eventdata_->condition_) != 0)
2436 return -1;
2437 return 0;
2440 #endif /* ACE_WIN32 */
2443 ACE_OS::event_destroy (ACE_event_t *event)
2445 #if defined (ACE_WIN32)
2446 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1);
2447 #elif defined (ACE_HAS_THREADS)
2448 if (!event->eventdata_)
2450 errno = EINVAL;
2451 return -1;
2454 // mutex_destroy()/cond_destroy() are called in a loop if the object
2455 // is BUSY. This avoids conditions where we fail to destroy these
2456 // objects because at time of destroy they were just being used in
2457 // another thread possibly causing deadlocks later on if they keep
2458 // being used after we're gone.
2460 if (event->eventdata_->type_ == USYNC_PROCESS)
2462 if (event->name_)
2464 int r1, r2;
2465 # if ACE_EVENT_USE_MUTEX_PSHARED
2466 // First destroy the mutex so locking after this will return
2467 // errors.
2468 while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
2469 && errno == EBUSY)
2470 ACE_OS::thr_yield ();
2471 # else
2472 r1 = ACE_OS::sema_destroy (&event->lock_);
2473 # endif
2475 # if ACE_EVENT_USE_COND_PSHARED
2476 // Now fix event to manual reset, raise signal and broadcast
2477 // until is's possible to destroy the condition.
2478 event->eventdata_->manual_reset_ = 1;
2479 while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_))
2480 == -1 && errno == EBUSY)
2482 event->eventdata_->is_signaled_ = 1;
2483 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2484 return -1;
2485 ACE_OS::thr_yield ();
2487 # else
2488 r2 = ACE_OS::sema_destroy (&event->semaphore_);
2489 # endif
2490 ACE_OS::munmap (event->eventdata_, sizeof (ACE_eventdata_t));
2491 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (event->name_));
2492 # if defined (ACE_HAS_ALLOC_HOOKS)
2493 ACE_Allocator::instance ()->free (event->name_);
2494 # else
2495 ACE_OS::free (event->name_);
2496 # endif /* ACE_HAS_ALLOC_HOOKS */
2497 return r1 != 0 || r2 != 0 ? -1 : 0;
2499 else // !name_ (not owned by this process)
2501 ACE_OS::munmap (event->eventdata_, sizeof (ACE_eventdata_t));
2503 # if !ACE_EVENT_USE_MUTEX_PSHARED
2504 ACE_OS::sema_destroy (&event->lock_);
2505 # endif
2507 # if !ACE_EVENT_USE_COND_PSHARED
2508 return ACE_OS::sema_destroy (&event->semaphore_);
2509 # endif
2512 else // USYNC_THREAD:
2514 int r1, r2;
2515 // First destroy the mutex so locking after this will return errors.
2516 while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
2517 && errno == EBUSY)
2518 ACE_OS::thr_yield ();
2520 // Now fix event to manual reset, raise signal and broadcast until
2521 // it's possible to destroy the condition.
2522 event->eventdata_->manual_reset_ = 1;
2523 while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
2524 && errno == EBUSY)
2526 event->eventdata_->is_signaled_ = 1;
2527 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2528 return -1;
2529 ACE_OS::thr_yield ();
2532 delete event->eventdata_;
2533 return r1 != 0 || r2 != 0 ? -1 : 0;
2536 return 0;
2537 #else
2538 ACE_UNUSED_ARG (event);
2539 ACE_NOTSUP_RETURN (-1);
2540 #endif /* ACE_WIN32 */
2543 ACE_ALLOC_HOOK_DEFINE (ACE_eventdata_t)
2545 #ifndef ACE_WIN32
2546 namespace {
2547 int eventdata_init (ACE_eventdata_t *evtdata, int type, int manual_reset,
2548 int initial_state, ACE_condattr_t *attributes,
2549 const char *name, void *arg, int init_condition = 1,
2550 int init_mutex = 1)
2552 evtdata->type_ = type;
2553 evtdata->manual_reset_ = manual_reset;
2554 evtdata->is_signaled_ = initial_state;
2555 evtdata->auto_event_signaled_ = false;
2556 evtdata->waiting_threads_ = 0;
2557 evtdata->signal_count_ = 0;
2559 if (init_condition)
2561 const int result = attributes ?
2562 ACE_OS::cond_init (&evtdata->condition_, *attributes, name, arg) :
2563 ACE_OS::cond_init (&evtdata->condition_, type, name, arg);
2565 if (result != 0)
2566 return result;
2569 return init_mutex ? ACE_OS::mutex_init (&evtdata->lock_, type, name,
2570 (ACE_mutexattr_t *) arg) : 0;
2573 template <size_t N, size_t M>
2574 void format_name (char (&str)[N], const char *name, const char (&suffix)[M])
2576 ACE_OS::strncpy (str, name, N - M);
2577 ACE_OS::strcat (str, suffix);
2580 #endif /* ACE_WIN32 */
2583 ACE_OS::event_init (ACE_event_t *event,
2584 int type,
2585 ACE_condattr_t *attributes,
2586 int manual_reset,
2587 int initial_state,
2588 const char *name,
2589 void *arg,
2590 LPSECURITY_ATTRIBUTES sa)
2592 #if defined (ACE_WIN32)
2593 ACE_UNUSED_ARG (type);
2594 ACE_UNUSED_ARG (attributes);
2595 ACE_UNUSED_ARG (arg);
2596 SECURITY_ATTRIBUTES sa_buffer;
2597 SECURITY_DESCRIPTOR sd_buffer;
2598 # if defined (ACE_HAS_WINCE)
2599 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
2600 *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
2601 (sa, &sa_buffer, &sd_buffer),
2602 manual_reset,
2603 initial_state,
2604 ACE_Ascii_To_Wide (name).wchar_rep ());
2605 # else /* ACE_HAS_WINCE */
2606 *event = ::CreateEventA (ACE_OS::default_win32_security_attributes_r
2607 (sa, &sa_buffer, &sd_buffer),
2608 manual_reset,
2609 initial_state,
2610 name);
2611 # endif /* ACE_HAS_WINCE */
2612 if (*event == 0)
2613 ACE_FAIL_RETURN (-1);
2614 else
2616 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
2617 ACE_OS::set_errno_to_last_error ();
2618 return 0;
2620 #elif defined (ACE_HAS_THREADS)
2621 ACE_UNUSED_ARG (sa);
2622 event->name_ = 0;
2623 event->eventdata_ = 0;
2625 if (type == USYNC_PROCESS)
2627 const char *name_p = name;
2628 # if defined (ACE_SHM_OPEN_REQUIRES_ONE_SLASH)
2629 char adj_name[MAXPATHLEN];
2630 if (name[0] != '/')
2632 adj_name[0] = '/';
2633 ACE_OS::strsncpy (&adj_name[1], name, MAXPATHLEN-1);
2634 name_p = adj_name;
2636 # endif /* ACE_SHM_OPEN_REQUIRES_ONE_SLASH */
2638 bool owner = false;
2639 // Let's see if the shared memory entity already exists.
2640 ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
2641 O_RDWR | O_CREAT | O_EXCL,
2642 ACE_DEFAULT_FILE_PERMS);
2643 if (fd == ACE_INVALID_HANDLE)
2645 if (errno == EEXIST)
2646 fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
2647 O_RDWR | O_CREAT,
2648 ACE_DEFAULT_FILE_PERMS);
2649 if (fd == ACE_INVALID_HANDLE) // Still can't get it.
2650 return -1;
2652 else
2654 // We own this shared memory object! Let's set its size.
2655 if (ACE_OS::ftruncate (fd, sizeof (ACE_eventdata_t)) == -1)
2657 ACE_OS::close (fd);
2658 return -1;
2660 owner = true;
2663 void *const mapped = ACE_OS::mmap (0, sizeof (ACE_eventdata_t),
2664 PROT_RDWR, MAP_SHARED, fd);
2665 ACE_eventdata_t *evtdata = reinterpret_cast<ACE_eventdata_t *> (mapped);
2666 ACE_OS::close (fd);
2667 if (evtdata == MAP_FAILED)
2669 if (owner)
2670 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2671 return -1;
2674 event->eventdata_ = evtdata;
2676 if (owner)
2678 event->name_ = ACE_OS::strdup (name_p);
2679 if (event->name_ == 0 ||
2680 eventdata_init (event->eventdata_, USYNC_PROCESS, manual_reset,
2681 initial_state, attributes, name, arg,
2682 ACE_EVENT_USE_COND_PSHARED,
2683 ACE_EVENT_USE_MUTEX_PSHARED) != 0)
2685 ACE_OS::munmap (evtdata, sizeof (ACE_eventdata_t));
2686 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2687 return -1;
2691 int result = 0;
2692 # if !ACE_EVENT_USE_COND_PSHARED
2693 char sem_name[128] = {};
2694 format_name (sem_name, name, "._ACE_EVTSEM_");
2695 result = ACE_OS::sema_init (&event->semaphore_, 0, type, attributes,
2696 sem_name, arg);
2697 # endif
2699 # if !ACE_EVENT_USE_MUTEX_PSHARED
2700 if (result == 0)
2702 char lck_name[128] = {};
2703 format_name (lck_name, name, "._ACE_EVTLCK_");
2704 result = ACE_OS::sema_init (&event->lock_, owner, type, attributes,
2705 lck_name, arg);
2707 # endif
2709 # if !ACE_EVENT_USE_COND_PSHARED || !ACE_EVENT_USE_MUTEX_PSHARED
2710 if (result != 0 && owner)
2711 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2712 # endif
2714 return result;
2716 else
2718 ACE_NEW_RETURN (event->eventdata_, ACE_eventdata_t, -1);
2719 return eventdata_init (event->eventdata_, USYNC_THREAD, manual_reset,
2720 initial_state, attributes, name, arg);
2722 #else
2723 ACE_UNUSED_ARG (event);
2724 ACE_UNUSED_ARG (manual_reset);
2725 ACE_UNUSED_ARG (initial_state);
2726 ACE_UNUSED_ARG (type);
2727 ACE_UNUSED_ARG (attributes);
2728 ACE_UNUSED_ARG (name);
2729 ACE_UNUSED_ARG (arg);
2730 ACE_UNUSED_ARG (sa);
2731 ACE_NOTSUP_RETURN (-1);
2732 #endif /* ACE_WIN32 */
2736 ACE_OS::event_pulse (ACE_event_t *event)
2738 #if defined (ACE_WIN32)
2739 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), ace_result_), int, -1);
2740 #elif defined (ACE_HAS_THREADS)
2741 int error = 0;
2742 int result = event->lock ();
2743 if (result != 0)
2744 return result;
2746 if (event->eventdata_->waiting_threads_ > 0)
2748 if (event->eventdata_->manual_reset_ == 1)
2750 // Wakeup all waiters.
2751 # if !ACE_EVENT_USE_COND_PSHARED
2752 if (event->eventdata_->type_ == USYNC_PROCESS)
2754 event->eventdata_->signal_count_ =
2755 event->eventdata_->waiting_threads_;
2756 for (unsigned long i = 0;
2757 i < event->eventdata_->signal_count_; ++i)
2758 if (ACE_OS::sema_post (&event->semaphore_) != 0)
2760 event->eventdata_->signal_count_ = 0;
2761 result = -1;
2762 error = errno;
2765 if (result == 0)
2766 while (event->eventdata_->signal_count_ != 0 &&
2767 event->eventdata_->waiting_threads_ != 0)
2768 ACE_OS::thr_yield ();
2770 else
2771 #endif
2772 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2774 result = -1;
2775 error = errno;
2777 else
2778 event->eventdata_->signal_count_ =
2779 event->eventdata_->waiting_threads_;
2781 else // Auto-reset event: wakeup one waiter.
2783 if (event->wake_one () != 0)
2785 result = -1;
2786 error = errno;
2789 event->eventdata_->auto_event_signaled_ = true;
2793 event->eventdata_->is_signaled_ = 0;
2795 if (event->unlock () != 0)
2796 return -1;
2798 if (result == -1)
2799 errno = error;
2801 return result;
2802 #else
2803 ACE_UNUSED_ARG (event);
2804 ACE_NOTSUP_RETURN (-1);
2805 #endif /* ACE_WIN32 */
2809 ACE_OS::event_reset (ACE_event_t *event)
2811 #if defined (ACE_WIN32)
2812 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1);
2813 #elif defined (ACE_HAS_THREADS)
2814 if (event->lock () != 0)
2815 return -1;
2817 event->eventdata_->is_signaled_ = 0;
2818 event->eventdata_->auto_event_signaled_ = false;
2820 return event->unlock ();
2821 #else
2822 ACE_UNUSED_ARG (event);
2823 ACE_NOTSUP_RETURN (-1);
2824 #endif /* ACE_WIN32 */
2828 ACE_OS::event_signal (ACE_event_t *event)
2830 #if defined (ACE_WIN32)
2831 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1);
2832 #elif defined (ACE_HAS_THREADS)
2833 int error = 0;
2834 int result = event->lock ();
2836 if (result != 0)
2837 return result;
2839 if (event->eventdata_->manual_reset_ == 1)
2841 // wakeup all
2842 # if !ACE_EVENT_USE_COND_PSHARED
2843 if (event->eventdata_->type_ == USYNC_PROCESS)
2845 if (ACE_OS::sema_post (&event->semaphore_) != 0)
2847 result = -1;
2848 error = errno;
2851 else
2852 #endif
2853 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2855 result = -1;
2856 error = errno;
2859 if (result == 0)
2860 event->eventdata_->is_signaled_ = 1;
2862 else // Auto-reset event
2864 if (event->eventdata_->waiting_threads_ == 0)
2865 event->eventdata_->is_signaled_ = 1;
2866 else if (event->wake_one () != 0)
2868 result = -1;
2869 error = errno;
2872 event->eventdata_->auto_event_signaled_ = true;
2875 if (event->unlock () != 0)
2876 return -1;
2878 if (result == -1)
2879 errno = error;
2881 return result;
2882 #else
2883 ACE_UNUSED_ARG (event);
2884 ACE_NOTSUP_RETURN (-1);
2885 #endif /* ACE_WIN32 */
2889 ACE_OS::event_timedwait (ACE_event_t *event,
2890 ACE_Time_Value *timeout,
2891 int use_absolute_time)
2893 #if defined (ACE_WIN32)
2894 DWORD result;
2896 if (timeout && *timeout == ACE_Time_Value::zero)
2897 // Do a "poll".
2898 result = ::WaitForSingleObject (*event, 0);
2899 else
2901 // Wait for upto <relative_time> number of milliseconds. Note
2902 // that we must convert between absolute time (which is passed
2903 // as a parameter) and relative time (which is what
2904 // WaitForSingleObjects() expects).
2905 // <timeout> parameter is given in absolute or relative value
2906 // depending on parameter <use_absolute_time>.
2907 int msec_timeout = 0;
2908 if (!timeout)
2910 msec_timeout = INFINITE;
2912 else if (use_absolute_time)
2914 // Time is given in absolute time, we should use
2915 // gettimeofday() to calculate relative time
2916 ACE_Time_Value relative_time = timeout->to_relative_time ();
2918 // Watchout for situations where a context switch has caused
2919 // the current time to be > the timeout. Thanks to Norbert
2920 // Rapp <NRapp@nexus-informatics.de> for pointing this.
2921 if (relative_time > ACE_Time_Value::zero)
2922 msec_timeout = relative_time.msec ();
2924 else
2925 // time is given in relative time, just convert it into
2926 // milliseconds and use it
2927 msec_timeout = timeout->msec ();
2928 result = ::WaitForSingleObject (*event, msec_timeout);
2931 switch (result)
2933 case WAIT_OBJECT_0:
2934 return 0;
2935 case WAIT_TIMEOUT:
2936 errno = ETIME;
2937 return -1;
2938 default:
2939 // This is a hack, we need to find an appropriate mapping...
2940 ACE_OS::set_errno_to_last_error ();
2941 return -1;
2943 #elif defined (ACE_HAS_THREADS)
2944 int error = 0;
2945 int result = event->lock ();
2947 if (result != 0)
2948 return result;
2950 if (event->eventdata_->is_signaled_ == 1)
2952 if (event->eventdata_->manual_reset_ == 0)
2954 // AUTO: reset state
2955 event->eventdata_->is_signaled_ = 0;
2956 event->eventdata_->auto_event_signaled_ = false;
2959 else // event is currently not signaled
2961 ++event->eventdata_->waiting_threads_;
2963 ACE_Time_Value *absolute_timeout = timeout, converted_time;
2965 // cond_timedwait() expects absolute time, check <use_absolute_time> flag
2966 if (timeout && use_absolute_time == 0)
2968 converted_time = timeout->to_absolute_time ();
2969 absolute_timeout = &converted_time;
2972 while (event->eventdata_->is_signaled_ == 0 &&
2973 !event->eventdata_->auto_event_signaled_)
2974 # if !ACE_EVENT_USE_COND_PSHARED
2975 if (event->eventdata_->type_ == USYNC_PROCESS)
2977 if (event->unlock () != 0)
2979 --event->eventdata_->waiting_threads_;
2980 return -1;
2983 if (ACE_OS::sema_wait (&event->semaphore_, absolute_timeout) != 0)
2985 result = -1;
2986 error = (errno == ETIMEDOUT) // Semaphores use ETIMEDOUT (POSIX)
2987 ? ETIME : errno;
2990 bool signalled = false;
2991 if (result == 0 && event->eventdata_->signal_count_ > 0)
2993 --event->eventdata_->signal_count_;
2994 signalled = true;
2997 if (event->lock () != 0)
2999 --event->eventdata_->waiting_threads_;
3000 return -1;
3003 if (result != 0)
3004 break;
3006 if (event->eventdata_->manual_reset_ == 1 &&
3007 event->eventdata_->is_signaled_ == 1 &&
3008 ACE_OS::sema_post (&event->semaphore_) != 0)
3010 result = -1;
3011 error = errno;
3012 break;
3015 if (signalled)
3016 break;
3018 else
3019 #endif
3021 if (ACE_OS::cond_timedwait (&event->eventdata_->condition_,
3022 &event->eventdata_->lock_,
3023 absolute_timeout) != 0)
3025 result = -1;
3026 error = errno;
3027 break;
3030 if (event->eventdata_->signal_count_ > 0)
3032 --event->eventdata_->signal_count_;
3033 break;
3037 // Reset the auto_event_signaled_ to false now that we have woken up.
3038 if (event->eventdata_->auto_event_signaled_)
3039 event->eventdata_->auto_event_signaled_ = false;
3041 --event->eventdata_->waiting_threads_;
3044 if (event->unlock () != 0)
3045 return -1;
3047 if (result == -1)
3048 errno = error;
3050 return result;
3051 #else
3052 ACE_UNUSED_ARG (event);
3053 ACE_UNUSED_ARG (timeout);
3054 ACE_UNUSED_ARG (use_absolute_time);
3055 ACE_NOTSUP_RETURN (-1);
3056 #endif /* ACE_WIN32 */
3059 /*****************************************************************************/
3060 // EVENTS END
3061 /*****************************************************************************/
3064 ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params)
3066 #if defined (ACE_HAS_STHREADS) || defined (sun)
3067 // Get the class TS and RT class IDs.
3068 ACE_id_t rt_id;
3069 ACE_id_t ts_id;
3070 if (ACE_OS::scheduling_class ("RT", rt_id) == -1
3071 || ACE_OS::scheduling_class ("TS", ts_id) == -1)
3072 return -1;
3074 // Get this LWP's scheduling parameters.
3075 pcparms_t pcparms;
3076 // The following is just to avoid Purify warnings about unitialized
3077 // memory reads.
3078 ACE_OS::memset (&pcparms, 0, sizeof pcparms);
3079 pcparms.pc_cid = PC_CLNULL;
3081 if (ACE_OS::priority_control (P_LWPID,
3082 P_MYID,
3083 PC_GETPARMS,
3084 (char *) &pcparms) == -1)
3085 return -1;
3086 else if (pcparms.pc_cid == rt_id)
3088 // RT class.
3089 rtparms_t rtparms;
3090 ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms);
3092 sched_params.policy (ACE_SCHED_FIFO);
3093 sched_params.priority (rtparms.rt_pri);
3094 sched_params.scope (ACE_SCOPE_THREAD);
3095 ACE_Time_Value quantum (rtparms.rt_tqsecs,
3096 rtparms.rt_tqnsecs == RT_TQINF
3097 ? 0 : rtparms.rt_tqnsecs * 1000);
3098 sched_params.quantum (quantum);
3099 return 0;
3101 else if (pcparms.pc_cid == ts_id)
3103 /* TS class */
3104 tsparms_t tsparms;
3105 ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms);
3107 sched_params.policy (ACE_SCHED_OTHER);
3108 sched_params.priority (tsparms.ts_upri);
3109 sched_params.scope (ACE_SCOPE_THREAD);
3110 return 0;
3112 else
3113 return -1;
3115 #else /* ! ACE_HAS_STHREADS && ! sun */
3116 ACE_UNUSED_ARG (sched_params);
3117 ACE_NOTSUP_RETURN (-1);
3118 #endif /* ! ACE_HAS_STHREADS && ! sun */
3122 ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params)
3124 #if defined (ACE_HAS_STHREADS) || defined (sun)
3125 ACE_Sched_Params lwp_params (sched_params);
3126 lwp_params.scope (ACE_SCOPE_LWP);
3127 return ACE_OS::sched_params (lwp_params);
3128 #else /* ! ACE_HAS_STHREADS && ! sun */
3129 ACE_UNUSED_ARG (sched_params);
3130 ACE_NOTSUP_RETURN (-1);
3131 #endif /* ! ACE_HAS_STHREADS && ! sun */
3134 #if defined ACE_HAS_THREADS && defined ACE_LACKS_RWLOCK_T
3135 namespace {
3136 struct UniqueName {
3137 UniqueName (int type, const void *addr)
3139 #ifdef ACE_WIN32
3140 if (type == USYNC_THREAD)
3142 this->named_ = false;
3143 return;
3145 this->named_ = true;
3146 #else
3147 ACE_UNUSED_ARG (type);
3148 #endif
3149 ACE_OS::unique_name (addr, &this->buffer_[0], ACE_UNIQUE_NAME_LEN);
3152 operator const ACE_TCHAR * () const
3154 #ifdef ACE_WIN32
3155 if (!this->named_)
3157 return 0;
3159 #endif
3160 return &this->buffer_[0];
3163 ACE_TCHAR buffer_[ACE_UNIQUE_NAME_LEN];
3164 #ifdef ACE_WIN32
3165 bool named_;
3166 #endif
3169 enum RWLockCleanup {RWLC_CondAttr, RWLC_Lock, RWLC_CondReaders, RWLC_CondWriters};
3171 struct RWLockCleaner {
3172 RWLockCleaner (ACE_condattr_t &attr, ACE_rwlock_t *rw)
3173 : state_ (RWLC_CondAttr)
3174 , attr_ (attr)
3175 , rw_ (rw)
3178 ~RWLockCleaner ()
3180 ACE_Errno_Guard error (errno);
3181 switch (this->state_)
3183 case RWLC_CondWriters:
3184 ACE_OS::cond_destroy (&this->rw_->waiting_writers_);
3185 // FALLTHROUGH
3186 case RWLC_CondReaders:
3187 ACE_OS::cond_destroy (&this->rw_->waiting_readers_);
3188 // FALLTHROUGH
3189 case RWLC_Lock:
3190 ACE_OS::mutex_destroy (&this->rw_->lock_);
3191 // FALLTHROUGH
3192 case RWLC_CondAttr:
3193 ACE_OS::condattr_destroy (this->attr_);
3197 RWLockCleanup state_;
3198 ACE_condattr_t &attr_;
3199 ACE_rwlock_t *rw_;
3202 #endif
3204 #if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T)
3206 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
3207 int type,
3208 const ACE_TCHAR *,
3209 void *arg)
3211 // ACE_OS_TRACE ("ACE_OS::rwlock_init");
3212 # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
3213 // NT, POSIX, and VxWorks don't support this natively.
3215 ACE_condattr_t attributes;
3216 if (ACE_OS::condattr_init (attributes, type) != 0)
3217 return -1;
3219 RWLockCleaner cleanup (attributes, rw);
3221 if (ACE_OS::mutex_init (&rw->lock_, type, UniqueName (type, &rw->lock_),
3222 (ACE_mutexattr_t *) arg) != 0)
3223 return -1;
3225 cleanup.state_ = RWLC_Lock;
3226 if (ACE_OS::cond_init (&rw->waiting_readers_, attributes,
3227 UniqueName (type, &rw->waiting_readers_), arg) != 0)
3228 return -1;
3230 cleanup.state_ = RWLC_CondReaders;
3231 if (ACE_OS::cond_init (&rw->waiting_writers_, attributes,
3232 UniqueName (type, &rw->waiting_writers_), arg) != 0)
3233 return -1;
3235 cleanup.state_ = RWLC_CondWriters;
3236 if (ACE_OS::cond_init (&rw->waiting_important_writer_, attributes,
3237 UniqueName (type, &rw->waiting_important_writer_),
3238 arg) != 0)
3239 return -1;
3241 cleanup.state_ = RWLC_CondAttr;
3242 rw->ref_count_ = 0;
3243 rw->num_waiting_writers_ = 0;
3244 rw->num_waiting_readers_ = 0;
3245 rw->important_writer_ = false;
3246 return 0;
3247 # else
3248 ACE_UNUSED_ARG (rw);
3249 ACE_UNUSED_ARG (type);
3250 ACE_UNUSED_ARG (arg);
3251 ACE_NOTSUP_RETURN (-1);
3252 # endif /* ACE_HAS_THREADS */
3254 #endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
3257 ACE_OS::sched_params (const ACE_Sched_Params &sched_params,
3258 ACE_id_t id)
3260 ACE_OS_TRACE ("ACE_OS::sched_params");
3261 #if defined (ACE_HAS_STHREADS)
3262 return ACE_OS::set_scheduling_params (sched_params, id);
3263 #elif defined (ACE_HAS_PTHREADS) && \
3264 (!defined (ACE_LACKS_SETSCHED) || \
3265 defined (ACE_HAS_PTHREAD_SCHEDPARAM))
3266 if (sched_params.quantum () != ACE_Time_Value::zero)
3268 // quantums not supported
3269 errno = EINVAL;
3270 return -1;
3273 // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
3274 // providing this code for 1003.1c PThreads. Please note that this
3275 // has only been tested for POSIX 1003.1c threads, and may cause
3276 // problems with other PThreads flavors!
3278 struct sched_param param;
3279 param.sched_priority = sched_params.priority ();
3281 if (sched_params.scope () == ACE_SCOPE_PROCESS)
3283 # if defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3284 ACE_UNUSED_ARG (id);
3285 ACE_NOTSUP_RETURN (-1);
3286 # else /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3287 int result = ::sched_setscheduler (id == ACE_SELF ? 0 : id,
3288 sched_params.policy (),
3289 &param) == -1 ? -1 : 0;
3290 return result;
3291 # endif /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3293 else if (sched_params.scope () == ACE_SCOPE_THREAD)
3295 ACE_thread_t thr_id = ACE_OS::thr_self ();
3297 int result;
3298 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
3299 sched_params.policy (),
3300 &param),
3301 result),
3302 int, -1);
3304 # if defined (sun)
3305 // We need to be able to set LWP priorities on Suns, even without
3306 // ACE_HAS_STHREADS, to obtain preemption.
3307 else if (sched_params.scope () == ACE_SCOPE_LWP)
3308 return ACE_OS::set_scheduling_params (sched_params, id);
3309 # endif /* sun */
3310 else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
3312 errno = EINVAL;
3313 return -1;
3316 #elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
3318 // PharLap ETS can act on the current thread - it can set the
3319 // quantum also, unlike Win32. All this only works on the RT
3320 // version.
3321 # if defined (ACE_HAS_PHARLAP_RT)
3322 if (id != ACE_SELF)
3323 ACE_NOTSUP_RETURN (-1);
3325 # if !defined (ACE_PHARLAP_LABVIEW_RT)
3326 if (sched_params.quantum() != ACE_Time_Value::zero)
3327 EtsSetTimeSlice (sched_params.quantum().msec());
3328 # endif
3330 # else
3332 if (sched_params.quantum () != ACE_Time_Value::zero)
3334 // I don't know of a way to set the quantum on Win32.
3335 errno = EINVAL;
3336 return -1;
3339 # endif /* ACE_HAS_PHARLAP_RT */
3341 if (sched_params.scope () == ACE_SCOPE_THREAD)
3344 // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
3345 // a VERY BAD THING. This include guard will allow people
3346 // to easily disable this feature in ACE.
3347 // It won't work at all for Pharlap since there's no SetPriorityClass.
3348 #if !defined (ACE_HAS_PHARLAP) && \
3349 !defined (ACE_DISABLE_WIN32_INCREASE_PRIORITY)
3350 // Set the priority class of this process to the REALTIME process class
3351 // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL.
3352 if (!::SetPriorityClass (::GetCurrentProcess (),
3353 (sched_params.policy () == ACE_SCHED_FIFO ||
3354 sched_params.policy () == ACE_SCHED_RR)
3355 ? REALTIME_PRIORITY_CLASS
3356 : NORMAL_PRIORITY_CLASS))
3358 ACE_OS::set_errno_to_last_error ();
3359 return -1;
3361 #endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
3363 // Now that we have set the priority class of the process, set the
3364 // priority of the current thread to the desired value.
3365 return ACE_OS::thr_setprio (sched_params.priority ());
3367 else if (sched_params.scope () == ACE_SCOPE_PROCESS)
3370 # if defined (ACE_HAS_PHARLAP_RT)
3371 ACE_NOTSUP_RETURN (-1);
3372 # else
3373 HANDLE hProcess
3374 = ::OpenProcess (PROCESS_SET_INFORMATION,
3375 FALSE,
3376 id == ACE_SELF ? ::GetCurrentProcessId() : id);
3377 if (!hProcess)
3379 ACE_OS::set_errno_to_last_error();
3380 return -1;
3382 // There is no way for us to set the priority of the thread when we
3383 // are setting the priority of a different process. So just ignore
3384 // the priority argument when ACE_SCOPE_PROCESS is specified.
3385 // Setting the priority class will automatically increase the base
3386 // priority of all the threads within a process while maintaining the
3387 // relative priorities of the threads within it.
3388 if (!::SetPriorityClass (hProcess,
3389 (sched_params.policy () == ACE_SCHED_FIFO ||
3390 sched_params.policy () == ACE_SCHED_RR)
3391 ? REALTIME_PRIORITY_CLASS
3392 : NORMAL_PRIORITY_CLASS))
3394 ACE_OS::set_errno_to_last_error ();
3395 ::CloseHandle (hProcess);
3396 return -1;
3398 ::CloseHandle (hProcess);
3399 return 0;
3400 #endif /* ACE_HAS_PHARLAP_RT */
3403 else
3405 errno = EINVAL;
3406 return -1;
3408 #elif defined (ACE_VXWORKS)
3409 ACE_UNUSED_ARG (id);
3411 // There is only one class of priorities on VxWorks, and no time
3412 // quanta. So, just set the current thread's priority.
3414 if (sched_params.policy () != ACE_SCHED_FIFO
3415 || sched_params.scope () != ACE_SCOPE_PROCESS
3416 || sched_params.quantum () != ACE_Time_Value::zero)
3418 errno = EINVAL;
3419 return -1;
3422 // Set the thread priority on the current thread.
3423 return ACE_OS::thr_setprio (sched_params.priority ());
3424 #else
3425 ACE_UNUSED_ARG (sched_params);
3426 ACE_UNUSED_ARG (id);
3427 ACE_NOTSUP_RETURN (-1);
3428 #endif /* ACE_HAS_STHREADS */
3432 ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id)
3434 #if defined (ACE_HAS_PRIOCNTL)
3435 // Get the priority class ID.
3436 pcinfo_t pcinfo;
3437 // The following is just to avoid Purify warnings about unitialized
3438 // memory reads.
3439 ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
3441 ACE_OS::strcpy (pcinfo.pc_clname, class_name);
3442 if (ACE_OS::priority_control (P_ALL /* ignored */,
3443 P_MYID /* ignored */,
3444 PC_GETCID,
3445 (char *) &pcinfo) == -1)
3447 return -1;
3449 else
3451 id = pcinfo.pc_cid;
3452 return 0;
3454 #else /* ! ACE_HAS_PRIOCNTL */
3455 ACE_UNUSED_ARG (class_name);
3456 ACE_UNUSED_ARG (id);
3457 ACE_NOTSUP_RETURN (-1);
3458 #endif /* ! ACE_HAS_PRIOCNTL */
3462 ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params,
3463 ACE_id_t id)
3465 #if defined (ACE_HAS_PRIOCNTL)
3466 // Set priority class, priority, and quantum of this LWP or process as
3467 // specified in sched_params.
3469 // Get the priority class ID.
3470 ACE_id_t class_id;
3471 if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER ?
3472 "TS" :
3473 "RT", class_id) == -1)
3475 return -1;
3478 pcparms_t pcparms;
3479 // The following is just to avoid Purify warnings about unitialized
3480 // memory reads.
3481 ACE_OS::memset (&pcparms, 0, sizeof pcparms);
3483 pcparms.pc_cid = class_id;
3485 if (sched_params.policy () == ACE_SCHED_OTHER &&
3486 sched_params.quantum () == ACE_Time_Value::zero)
3487 // SunOS doesn't support non-zero quantums in time-sharing class: use
3488 // real-time class instead.
3490 tsparms_t tsparms;
3491 // The following is just to avoid Purify warnings about unitialized
3492 // memory reads.
3493 ACE_OS::memset (&tsparms, 0, sizeof tsparms);
3495 // Don't change ts_uprilim (user priority limit)
3496 tsparms.ts_uprilim = TS_NOCHANGE;
3497 tsparms.ts_upri = sched_params.priority ();
3499 // Package up the TS class ID and parameters for the
3500 // priority_control () call.
3501 ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms);
3503 else if (sched_params.policy () == ACE_SCHED_FIFO ||
3504 (sched_params.policy () == ACE_SCHED_RR &&
3505 sched_params.quantum () != ACE_Time_Value::zero))
3506 // must have non-zero quantum for RR, to make it meaningful
3507 // A zero quantum with FIFO has special significance: it actually
3508 // means infinite time quantum, i.e., run-to-completion.
3510 rtparms_t rtparms;
3511 // The following is just to avoid Purify warnings about unitialized
3512 // memory reads.
3513 ACE_OS::memset (&rtparms, 0, sizeof rtparms);
3515 rtparms.rt_pri = sched_params.priority ();
3517 if (sched_params.quantum () == ACE_Time_Value::zero)
3519 // rtparms.rt_tqsecs is ignored with RT_TQINF
3520 rtparms.rt_tqnsecs = RT_TQINF;
3522 else
3524 rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec ();
3525 rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000;
3528 // Package up the RT class ID and parameters for the
3529 // priority_control () call.
3530 ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms);
3532 else
3534 errno = EINVAL;
3535 return -1;
3538 if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD
3539 ? ACE_SCOPE_PROCESS
3540 : sched_params.scope ()),
3542 PC_SETPARMS,
3543 (char *) &pcparms) < 0)
3545 return ACE_OS::last_error ();
3548 return 0;
3549 #else /* ! ACE_HAS_PRIOCNTL */
3550 ACE_UNUSED_ARG (sched_params);
3551 ACE_UNUSED_ARG (id);
3552 ACE_NOTSUP_RETURN (-1);
3553 #endif /* ! ACE_HAS_PRIOCNTL */
3557 ACE_OS::thr_create (ACE_THR_FUNC func,
3558 void *args,
3559 long flags,
3560 ACE_thread_t *thr_id,
3561 ACE_hthread_t *thr_handle,
3562 long priority,
3563 void *stack,
3564 size_t stacksize,
3565 ACE_Base_Thread_Adapter *thread_adapter,
3566 const char** thr_name)
3568 ACE_OS_TRACE ("ACE_OS::thr_create");
3570 if (ACE_BIT_DISABLED (flags, THR_DETACHED) &&
3571 ACE_BIT_DISABLED (flags, THR_JOINABLE))
3572 ACE_SET_BITS (flags, THR_JOINABLE);
3574 #if defined (ACE_NO_THREAD_ADAPTER)
3575 # define ACE_THREAD_FUNCTION func
3576 # define ACE_THREAD_ARGUMENT args
3577 #else /* ! defined (ACE_NO_THREAD_ADAPTER) */
3578 # define ACE_THREAD_FUNCTION thread_args->entry_point ()
3579 # define ACE_THREAD_ARGUMENT thread_args
3580 #endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
3582 ACE_Base_Thread_Adapter *thread_args = 0;
3583 if (thread_adapter == 0)
3584 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
3585 ACE_NEW_RETURN (thread_args,
3586 ACE_OS_Thread_Adapter (func, args,
3587 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
3588 ACE_OS_Object_Manager::seh_except_selector(),
3589 ACE_OS_Object_Manager::seh_except_handler(),
3590 flags),
3591 -1);
3592 #else
3593 ACE_NEW_RETURN (thread_args,
3594 ACE_OS_Thread_Adapter (func, args,
3595 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
3596 flags),
3597 -1);
3599 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
3600 else
3601 thread_args = thread_adapter;
3603 std::unique_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
3605 if (thread_adapter == 0)
3606 ACE_auto_ptr_reset (auto_thread_args,
3607 thread_args);
3609 #if defined (ACE_HAS_THREADS)
3611 // *** Set Stack Size
3612 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3613 if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3614 stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
3615 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
3617 ACE_thread_t tmp_thr;
3618 if (thr_id == 0)
3619 thr_id = &tmp_thr;
3621 ACE_hthread_t tmp_handle;
3622 if (thr_handle == 0)
3623 thr_handle = &tmp_handle;
3625 # if defined (ACE_HAS_PTHREADS)
3626 int result;
3627 # if defined (ACE_PTHREAD_ATTR_T_INITIALIZE)
3628 /* Tests show that VxWorks 6.x pthread lib does not only
3629 * require zeroing of mutex/condition objects to function correctly
3630 * but also of the attribute objects.
3632 pthread_attr_t attr = {0};
3633 # else
3634 pthread_attr_t attr;
3635 # endif
3636 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr), result) != 0)
3637 return -1;
3639 if (stacksize != 0)
3641 size_t size = stacksize;
3643 # if defined (PTHREAD_STACK_MIN)
3644 if (size < static_cast <size_t> (PTHREAD_STACK_MIN))
3645 size = PTHREAD_STACK_MIN;
3646 # endif /* PTHREAD_STACK_MIN */
3648 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
3649 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3650 int result;
3651 if (stack != 0)
3652 result = ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr, stack, size), result);
3653 else
3654 result = ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result);
3655 if (result == -1)
3656 # else
3657 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result) == -1)
3658 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3660 ::pthread_attr_destroy (&attr);
3661 return -1;
3663 # else
3664 ACE_UNUSED_ARG (size);
3665 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
3668 // *** Set Stack Address
3669 # if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3670 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
3671 if (stack != 0)
3673 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr, stack), result) != 0)
3675 ::pthread_attr_destroy (&attr);
3676 return -1;
3679 # else
3680 ACE_UNUSED_ARG (stack);
3681 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3682 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3684 // *** Deal with various attributes
3685 if (flags != 0)
3687 // *** Set Detach state
3688 # if !defined (ACE_LACKS_SETDETACH)
3689 if (ACE_BIT_ENABLED (flags, THR_DETACHED)
3690 || ACE_BIT_ENABLED (flags, THR_JOINABLE))
3692 int dstate = PTHREAD_CREATE_JOINABLE;
3694 if (ACE_BIT_ENABLED (flags, THR_DETACHED))
3695 dstate = PTHREAD_CREATE_DETACHED;
3697 if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
3698 result) != 0)
3700 ::pthread_attr_destroy (&attr);
3701 return -1;
3705 // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
3706 // call ::pthread_detach () below. If THR_DETACHED is not
3707 // enabled, we call ::pthread_detach () in the Thread_Manager,
3708 // after joining with the thread.
3709 # endif /* ACE_LACKS_SETDETACH */
3711 // *** Set Policy
3712 # if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3713 // If we wish to set the priority explicitly, we have to enable
3714 // explicit scheduling, and a policy, too.
3715 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3717 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3718 if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
3719 && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
3720 && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
3721 ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
3724 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3725 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3726 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3728 int spolicy;
3730 # if defined (ACE_HAS_ONLY_SCHED_OTHER)
3731 // SunOS, thru version 5.6, only supports SCHED_OTHER.
3732 spolicy = SCHED_OTHER;
3733 # elif defined (ACE_HAS_ONLY_SCHED_FIFO)
3734 // NonStop OSS standard pthread supports only SCHED_FIFO.
3735 spolicy = SCHED_FIFO;
3736 # else
3737 // Make sure to enable explicit scheduling, in case we didn't
3738 // enable it above (for non-default priority).
3739 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3741 if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3742 spolicy = SCHED_OTHER;
3743 else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3744 spolicy = SCHED_FIFO;
3745 # if defined (SCHED_IO)
3746 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3747 spolicy = SCHED_IO;
3748 # else
3749 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3751 errno = ENOSYS;
3752 return -1;
3754 # endif /* SCHED_IO */
3755 else
3756 spolicy = SCHED_RR;
3758 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3760 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
3761 result);
3762 if (result != 0)
3764 ::pthread_attr_destroy (&attr);
3765 return -1;
3769 // *** Set Priority (use reasonable default priorities)
3770 # if defined(ACE_HAS_PTHREADS)
3771 // If we wish to explicitly set a scheduling policy, we also
3772 // have to specify a priority. We choose a "middle" priority as
3773 // default. Maybe this is also necessary on other POSIX'ish
3774 // implementations?
3775 if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3776 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3777 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3778 && priority == ACE_DEFAULT_THREAD_PRIORITY)
3780 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3781 priority = ACE_THR_PRI_FIFO_DEF;
3782 else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
3783 priority = ACE_THR_PRI_RR_DEF;
3784 else // THR_SCHED_DEFAULT
3785 priority = ACE_THR_PRI_OTHER_DEF;
3787 # endif /* ACE_HAS_PTHREADS */
3788 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3790 struct sched_param sparam;
3791 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
3793 # if defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
3794 /* For MIT pthreads... */
3795 sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
3796 # elif defined(ACE_HAS_PTHREADS) && !defined (ACE_HAS_STHREADS)
3797 // The following code forces priority into range.
3798 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3799 sparam.sched_priority =
3800 ACE_MIN (ACE_THR_PRI_FIFO_MAX,
3801 ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
3802 else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
3803 sparam.sched_priority =
3804 ACE_MIN (ACE_THR_PRI_RR_MAX,
3805 ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
3806 else // Default policy, whether set or not
3807 sparam.sched_priority =
3808 ACE_MIN (ACE_THR_PRI_OTHER_MAX,
3809 ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
3810 # elif defined (PRIORITY_MAX)
3811 sparam.sched_priority = ACE_MIN (priority,
3812 (long) PRIORITY_MAX);
3813 # else
3814 sparam.sched_priority = priority;
3815 # endif /* PTHREAD_MAX_PRIORITY */
3818 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
3819 // SunOS, through 5.6, POSIX only allows priorities > 0 to
3820 // ::pthread_attr_setschedparam. If a priority of 0 was
3821 // requested, set the thread priority after creating it, below.
3822 if (priority > 0)
3823 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
3825 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
3826 result);
3827 if (result != 0)
3829 ::pthread_attr_destroy (&attr);
3830 return -1;
3836 # if !defined (ACE_LACKS_SETINHERITSCHED)
3837 // *** Set scheduling explicit or inherited
3838 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
3839 || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
3841 int sched = PTHREAD_EXPLICIT_SCHED;
3842 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
3843 sched = PTHREAD_INHERIT_SCHED;
3844 if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr, sched), result) != 0)
3846 ::pthread_attr_destroy (&attr);
3847 return -1;
3850 # endif /* ACE_LACKS_SETINHERITSCHED */
3851 # else /* ACE_LACKS_SETSCHED */
3852 ACE_UNUSED_ARG (priority);
3853 # endif /* ACE_LACKS_SETSCHED */
3855 // *** Set pthread name
3856 # if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3857 if (thr_name && *thr_name)
3859 if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr, const_cast<char*>(*thr_name)), result) != 0)
3861 ::pthread_attr_destroy (&attr);
3862 return -1;
3865 #else
3866 ACE_UNUSED_ARG (thr_name);
3867 # endif
3869 // *** Set Scope
3870 # if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
3871 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
3872 || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
3874 # if defined (ACE_LACKS_PTHREAD_SCOPE_PROCESS)
3875 int scope = PTHREAD_SCOPE_SYSTEM;
3876 # else /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3877 int scope = PTHREAD_SCOPE_PROCESS;
3878 # endif /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3879 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
3880 scope = PTHREAD_SCOPE_SYSTEM;
3882 if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr, scope), result) != 0)
3884 ::pthread_attr_destroy (&attr);
3885 return -1;
3888 # endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
3890 # ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
3891 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED))
3893 if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr), result) != 0)
3896 ::pthread_attr_destroy (&attr);
3897 return -1;
3900 # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
3902 # if ! defined(ACE_LACKS_THR_CONCURRENCY_FUNCS)
3903 if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
3905 // Increment the number of LWPs by one to emulate the
3906 // SunOS semantics.
3907 int lwps = ACE_OS::thr_getconcurrency ();
3908 if (lwps == -1)
3910 if (errno == ENOTSUP)
3911 // Suppress the ENOTSUP because it's harmless.
3912 errno = 0;
3913 else
3914 // This should never happen on SunOS:
3915 // ::thr_getconcurrency () should always succeed.
3916 return -1;
3918 else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
3920 if (errno == ENOTSUP)
3922 // Unlikely: ::thr_getconcurrency () is supported
3923 // but ::thr_setconcurrency () is not?
3925 else
3926 return -1;
3929 # endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */
3932 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
3933 &attr,
3934 thread_args->entry_point (),
3935 thread_args),
3936 result),
3937 int, -1, result);
3938 ::pthread_attr_destroy (&attr);
3940 // This is a SunOS or POSIX implementation of pthreads, where we
3941 // assume that ACE_thread_t and ACE_hthread_t are the same. If this
3942 // *isn't* correct on some platform, please let us know.
3943 if (result != -1)
3944 *thr_handle = *thr_id;
3946 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
3947 // SunOS prior to 5.7:
3949 // If the priority is 0, then we might have to set it now because we
3950 // couldn't set it with ::pthread_attr_setschedparam, as noted
3951 // above. This doesn't provide strictly correct behavior, because
3952 // the thread was created (above) with the priority of its parent.
3953 // (That applies regardless of the inherit_sched attribute: if it
3954 // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
3955 // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then "attr"
3956 // was initialized by the SunOS ::pthread_attr_init () to contain
3957 // NULL for the priority, which indicated to SunOS ::pthread_create
3958 // () to inherit the parent priority.)
3959 if (priority == 0)
3961 // Check the priority of this thread, which is the parent
3962 // of the newly created thread. If it is 0, then the
3963 // newly created thread will have inherited the priority
3964 // of 0, so there's no need to explicitly set it.
3965 struct sched_param sparam;
3966 int policy = 0;
3967 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
3968 &policy,
3969 &sparam),
3970 result), int,
3971 -1, result);
3973 // The only policy supported by by SunOS, thru version 5.6,
3974 // is SCHED_OTHER, so that's hard-coded here.
3975 policy = ACE_SCHED_OTHER;
3977 if (sparam.sched_priority != 0)
3979 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
3980 // The memset to 0 sets the priority to 0, so we don't need
3981 // to explicitly set sparam.sched_priority.
3983 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id,
3984 policy,
3985 &sparam),
3986 result),
3987 int, -1);
3991 # if defined (ACE_NEEDS_LWP_PRIO_SET)
3992 # if 0
3993 // It would be useful if we could make this work. But, it requires
3994 // a mechanism for determining the ID of an LWP to which another
3995 // thread is bound. Is there a way to do that? Instead, just rely
3996 // on the code in ACE_Thread_Adapter::invoke () to set the LWP
3997 // priority.
3999 // If the thread is bound, then set the priority on its LWP.
4000 if (ACE_BIT_ENABLED (flags, THR_BOUND))
4002 ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) ||
4003 ACE_BIT_ENABLED (flags, THR_SCHED_RR) ?
4004 ACE_SCHED_FIFO :
4005 ACE_SCHED_OTHER,
4006 priority);
4007 result = ACE_OS::lwp_setparams (sched_params,
4008 /* ? How do we find the ID of the LWP
4009 to which *thr_id is bound? */);
4011 # endif /* 0 */
4012 # endif /* ACE_NEEDS_LWP_PRIO_SET */
4014 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4015 auto_thread_args.release ();
4016 return result;
4017 # elif defined (ACE_HAS_STHREADS)
4018 int result;
4019 int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
4021 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4022 // If we need to set the priority, then we need to start the
4023 // thread in a suspended mode.
4024 ACE_SET_BITS (flags, THR_SUSPENDED);
4026 ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize,
4027 thread_args->entry_point (),
4028 thread_args,
4029 flags, thr_id), result),
4030 int, -1, result);
4032 if (result != -1)
4034 // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
4035 *thr_handle = *thr_id;
4037 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4039 // Set the priority of the new thread and then let it
4040 // continue, but only if the user didn't start it suspended
4041 // in the first place!
4042 result = ACE_OS::thr_setprio (*thr_id, priority);
4043 if (result != 0)
4045 errno = result;
4046 return -1;
4049 if (start_suspended == 0)
4051 result = ACE_OS::thr_continue (*thr_id);
4052 if (result != 0)
4054 errno = result;
4055 return -1;
4060 auto_thread_args.release ();
4061 return result;
4062 # elif defined (ACE_HAS_WTHREADS)
4063 ACE_UNUSED_ARG (thr_name);
4064 ACE_UNUSED_ARG (stack);
4065 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4066 if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
4068 CWinThread *cwin_thread =
4069 ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
4070 thread_args,
4071 priority,
4073 flags | THR_SUSPENDED);
4074 // Have to duplicate the handle because
4075 // CWinThread::~CWinThread() closes the original handle.
4076 # if !defined (ACE_HAS_WINCE)
4077 (void) ::DuplicateHandle (::GetCurrentProcess (),
4078 cwin_thread->m_hThread,
4079 ::GetCurrentProcess (),
4080 thr_handle,
4082 TRUE,
4083 DUPLICATE_SAME_ACCESS);
4084 # endif /* ! ACE_HAS_WINCE */
4085 *thr_id = cwin_thread->m_nThreadID;
4087 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
4088 cwin_thread->ResumeThread ();
4089 // cwin_thread will be deleted in AfxThreadExit()
4090 // Warning: If AfxThreadExit() is called from within the
4091 // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
4093 else
4094 # endif /* ACE_HAS_MFC */
4096 int const start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
4098 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4099 // If we need to set the priority, then we need to start the
4100 // thread in a suspended mode.
4101 ACE_SET_BITS (flags, THR_SUSPENDED);
4103 *thr_handle = (void *) ACE_BEGINTHREADEX (0,
4104 static_cast <u_int> (stacksize),
4105 thread_args->entry_point (),
4106 thread_args,
4107 flags,
4108 thr_id);
4110 if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
4112 // Set the priority of the new thread and then let it
4113 // continue, but only if the user didn't start it suspended
4114 // in the first place!
4115 if (ACE_OS::thr_setprio (*thr_handle, priority) != 0)
4117 return -1;
4120 if (start_suspended == 0)
4122 ACE_OS::thr_continue (*thr_handle);
4127 // Close down the handle if no one wants to use it.
4128 if (thr_handle == &tmp_handle && tmp_handle != 0)
4129 ::CloseHandle (tmp_handle);
4131 if (*thr_handle != 0)
4133 auto_thread_args.release ();
4134 return 0;
4136 else
4137 ACE_FAIL_RETURN (-1);
4138 /* NOTREACHED */
4140 # elif defined (ACE_VXWORKS)
4141 // The hard-coded values below are what ::sp () would use. (::sp ()
4142 // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
4143 // 20,000.) stacksize should be an even integer. If a stack is not
4144 // specified, ::taskSpawn () is used so that we can set the
4145 // priority, flags, and stacksize. If a stack is specified,
4146 // ::taskInit ()/::taskActivate() are used.
4148 // If called with thr_create() defaults, use same default values as ::sp ():
4149 if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
4150 // Assumes that there is a floating point coprocessor. As noted
4151 // above, ::sp () hardcodes this, so we should be safe with it.
4152 if (flags == 0) flags = VX_FP_TASK;
4153 if (stacksize == 0) stacksize = 20000;
4155 ACE_thread_t tid;
4156 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4157 if (stack == 0)
4159 # else
4160 ACE_UNUSED_ARG (stack);
4161 # endif /* 0 */
4162 // The call below to ::taskSpawn () causes VxWorks to assign a
4163 // unique task name of the form: "t" + an integer, because the
4164 // first argument is 0.
4165 tid = ::taskSpawn (thr_name && *thr_name ? const_cast <char*> (*thr_name) : 0,
4166 priority,
4167 (int) flags,
4168 stacksize,
4169 thread_args->entry_point (),
4170 (ACE_VX_USR_ARG_T) thread_args,
4171 0, 0, 0, 0, 0, 0, 0, 0, 0);
4172 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4174 else
4176 // If a task name (thr_id) was not supplied, then the task will
4177 // not have a unique name. That's VxWorks' behavior.
4179 // Carve out a TCB at the beginning of the stack space. The TCB
4180 // occupies 400 bytes with VxWorks 5.3.1/I386.
4181 WIND_TCB *tcb = (WIND_TCB *) stack;
4183 // The TID is defined to be the address of the TCB.
4184 int status = ::taskInit (tcb,
4185 thr_name && *thr_name ? const_cast <char*>(*thr_name) : 0,
4186 priority,
4187 (int) flags,
4188 (char *) stack + sizeof (WIND_TCB),
4189 (int) (stacksize - sizeof (WIND_TCB)),
4190 thread_args->entry_point (),
4191 (int) thread_args,
4192 0, 0, 0, 0, 0, 0, 0, 0, 0);
4194 if (status == OK)
4196 // The task was successfully initialized, now activate it.
4197 status = ::taskActivate ((ACE_hthread_t) tcb);
4200 tid = status == OK ? (ACE_thread_t) tcb : ERROR;
4202 # endif /* 0 */
4204 if (tid == ACE_VX_TASK_ID_ERROR)
4205 return -1;
4206 else
4208 if (thr_id)
4209 *thr_id = tid;
4211 if (thr_handle)
4212 *thr_handle = tid;
4214 if (thr_name && !(*thr_name))
4215 *thr_name = ::taskName (tid);
4217 auto_thread_args.release ();
4218 return 0;
4221 # endif /* ACE_HAS_STHREADS */
4222 #else
4223 ACE_UNUSED_ARG (func);
4224 ACE_UNUSED_ARG (args);
4225 ACE_UNUSED_ARG (flags);
4226 ACE_UNUSED_ARG (thr_id);
4227 ACE_UNUSED_ARG (thr_handle);
4228 ACE_UNUSED_ARG (priority);
4229 ACE_UNUSED_ARG (stack);
4230 ACE_UNUSED_ARG (stacksize);
4231 ACE_UNUSED_ARG (thr_name);
4232 ACE_NOTSUP_RETURN (-1);
4233 #endif /* ACE_HAS_THREADS */
4236 void
4237 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
4239 ACE_OS_TRACE ("ACE_OS::thr_exit");
4240 #if defined (ACE_HAS_THREADS)
4241 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_EXIT)
4242 ::pthread_exit (status);
4243 # elif defined (ACE_HAS_STHREADS)
4244 ::thr_exit (status);
4245 # elif defined (ACE_HAS_WTHREADS)
4246 // Can't call it here because on NT, the thread is exited
4247 // directly by ACE_Thread_Adapter::invoke ().
4248 // ACE_TSS_Cleanup::instance ()->thread_exit (status);
4250 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4251 int using_afx = -1;
4252 // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
4253 // But without #including ace/Thread_Manager.h, we don't know that.
4254 ACE_OS_Thread_Descriptor *td =
4255 ACE_Base_Thread_Adapter::thr_desc_log_msg ();
4256 if (td)
4257 using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
4258 # endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
4260 // Call TSS destructors.
4261 ACE_OS::cleanup_tss (0 /* not main thread */);
4263 // Exit the thread.
4264 // Allow CWinThread-destructor to be invoked from AfxEndThread.
4265 // _endthreadex will be called from AfxEndThread so don't exit the
4266 // thread now if we are running an MFC thread.
4267 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4268 if (using_afx != -1)
4270 if (using_afx)
4271 ::AfxEndThread (status);
4272 else
4273 ACE_ENDTHREADEX (status);
4275 else
4277 // Not spawned by ACE_Thread_Manager, use the old buggy
4278 // version. You should seriously consider using
4279 // ACE_Thread_Manager to spawn threads. The following code is
4280 // know to cause some problem.
4281 CWinThread *pThread = ::AfxGetThread ();
4282 if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
4283 ACE_ENDTHREADEX (status);
4284 else
4285 ::AfxEndThread (status);
4287 # else
4288 ACE_ENDTHREADEX (status);
4289 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
4291 # elif defined (ACE_HAS_VXTHREADS)
4292 ACE_UNUSED_ARG (status);
4293 ::taskDelete (ACE_OS::thr_self ());
4294 # else
4295 ACE_UNUSED_ARG (status);
4296 # endif /* ACE_HAS_PTHREADS */
4297 #else
4298 ACE_UNUSED_ARG (status);
4299 #endif /* ACE_HAS_THREADS */
4302 #if defined (ACE_HAS_VXTHREADS)
4303 // Leave this in the global scope to allow
4304 // users to adjust the delay value.
4305 int ACE_THR_JOIN_DELAY = 5;
4308 ACE_OS::thr_join (ACE_hthread_t thr_handle,
4309 ACE_THR_FUNC_RETURN *status)
4311 // We can't get the status of the thread
4312 if (status != 0)
4314 *status = 0;
4317 // This method can not support joining all threads
4318 if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
4320 ACE_NOTSUP_RETURN (-1);
4323 int retval = ESRCH;
4324 ACE_thread_t current = ACE_OS::thr_self ();
4326 // Make sure we are not joining ourself
4327 if (ACE_OS::thr_cmp (thr_handle, current))
4329 retval = EDEADLK;
4331 else
4333 // Whether the task exists or not
4334 // we will return a successful value
4335 retval = 0;
4337 // Verify that the task id still exists
4338 while (taskIdVerify (thr_handle) == OK)
4340 // Wait a bit to see if the task is still active.
4341 ACE_OS::sleep (ACE_THR_JOIN_DELAY);
4345 // Adapt the return value into errno and return value.
4346 // The ACE_ADAPT_RETVAL macro doesn't exactly do what
4347 // we need to do here, so we do it manually.
4348 if (retval != 0)
4350 errno = retval;
4351 retval = -1;
4354 return retval;
4358 ACE_OS::thr_join (ACE_thread_t waiter_id,
4359 ACE_thread_t *thr_id,
4360 ACE_THR_FUNC_RETURN *status)
4362 thr_id = 0;
4363 return ACE_OS::thr_join (waiter_id, status);
4365 #endif /* ACE_HAS_VXTHREADS */
4368 ACE_OS::thr_key_detach (ACE_thread_key_t key)
4370 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
4371 TSS_Cleanup_Instance cleanup;
4372 if (cleanup.valid ())
4374 return cleanup->thread_detach_key (key);
4376 else
4378 return -1;
4380 #else
4381 ACE_UNUSED_ARG (key);
4382 ACE_NOTSUP_RETURN (-1);
4383 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
4387 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id,
4388 size_t cpu_set_size,
4389 cpu_set_t * cpu_mask)
4391 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
4392 // Handle of the thread, which is NPTL thread-id, normally a big number
4393 if (::pthread_getaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4395 return -1;
4397 return 0;
4398 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
4399 // The process-id is expected as <thr_id>, which can be a thread-id of
4400 // linux-thread, thus making binding to cpu of that particular thread only.
4401 // If you are using this flag for NPTL-threads, however, please pass as a
4402 // thr_id process id obtained by ACE_OS::getpid ()
4403 ACE_UNUSED_ARG (cpu_set_size);
4404 if (::sched_getaffinity(thr_id, cpu_mask) == -1)
4406 return -1;
4408 return 0;
4409 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
4410 // The process-id is expected as <thr_id>, which can be a thread-id of
4411 // linux-thread, thus making binding to cpu of that particular thread only.
4412 // If you are using this flag for NPTL-threads, however, please pass as a
4413 // thr_id process id obtained by ACE_OS::getpid ()
4414 if (::sched_getaffinity(thr_id, cpu_set_size, cpu_mask) == -1)
4416 return -1;
4418 return 0;
4419 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4420 ACE_UNUSED_ARG (cpu_set_size);
4421 int result = 0;
4422 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id, *cpu_mask), result) == -1)
4424 return -1;
4426 return 0;
4427 #else
4428 ACE_UNUSED_ARG (thr_id);
4429 ACE_UNUSED_ARG (cpu_set_size);
4430 ACE_UNUSED_ARG (cpu_mask);
4431 ACE_NOTSUP_RETURN (-1);
4432 #endif
4436 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id,
4437 size_t cpu_set_size,
4438 const cpu_set_t * cpu_mask)
4440 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
4441 if (::pthread_setaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4443 return -1;
4445 return 0;
4446 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
4447 // The process-id is expected as <thr_id>, which can be a thread-id of
4448 // linux-thread, thus making binding to cpu of that particular thread only.
4449 // If you are using this flag for NPTL-threads, however, please pass as a
4450 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4452 ACE_UNUSED_ARG (cpu_set_size);
4453 if (::sched_setaffinity (thr_id, cpu_mask) == -1)
4455 return -1;
4457 return 0;
4458 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
4459 // The process-id is expected as <thr_id>, which can be a thread-id of
4460 // linux-thread, thus making binding to cpu of that particular thread only.
4461 // If you are using this flag for NPTL-threads, however, please pass as a
4462 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4464 if (::sched_setaffinity (thr_id, cpu_set_size, cpu_mask) == -1)
4466 return -1;
4468 return 0;
4469 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4470 ACE_UNUSED_ARG (cpu_set_size);
4471 int result = 0;
4472 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id, *cpu_mask), result) == -1)
4474 return -1;
4476 return 0;
4477 #else
4478 ACE_UNUSED_ARG (thr_id);
4479 ACE_UNUSED_ARG (cpu_set_size);
4480 ACE_UNUSED_ARG (cpu_mask);
4481 ACE_NOTSUP_RETURN (-1);
4482 #endif
4486 ACE_OS::thr_key_used (ACE_thread_key_t key)
4488 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
4489 TSS_Cleanup_Instance cleanup;
4490 if (cleanup.valid ())
4492 cleanup->thread_use_key (key);
4493 return 0;
4495 return -1;
4496 #else
4497 ACE_UNUSED_ARG (key);
4498 ACE_NOTSUP_RETURN (-1);
4499 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
4502 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4504 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t *key,
4505 # if defined (ACE_HAS_THR_C_DEST)
4506 ACE_THR_C_DEST dest
4507 # else
4508 ACE_THR_DEST dest
4509 # endif /* ACE_HAS_THR_C_DEST */
4512 // can't trace here. Trace uses TSS
4513 // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
4514 # if defined (ACE_HAS_THREADS)
4515 # if defined (ACE_HAS_PTHREADS)
4516 int result;
4517 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
4518 result),
4519 int, -1);
4520 # elif defined (ACE_HAS_STHREADS)
4521 int result;
4522 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
4523 result),
4524 int, -1);
4525 # elif defined (ACE_HAS_WTHREADS)
4526 ACE_UNUSED_ARG (dest);
4527 *key = ::TlsAlloc ();
4529 if (*key == ACE_SYSCALL_FAILED)
4530 ACE_FAIL_RETURN (-1);
4531 return 0;
4532 # endif /* ACE_HAS_STHREADS */
4533 # else
4534 ACE_UNUSED_ARG (key);
4535 ACE_UNUSED_ARG (dest);
4536 ACE_NOTSUP_RETURN (-1);
4537 # endif /* ACE_HAS_THREADS */
4539 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4542 ACE_OS::thr_keycreate (ACE_thread_key_t *key,
4543 # if defined (ACE_HAS_THR_C_DEST)
4544 ACE_THR_C_DEST dest)
4545 # else
4546 ACE_THR_DEST dest)
4547 # endif /* ACE_HAS_THR_C_DEST */
4549 // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
4550 #if defined (ACE_HAS_THREADS)
4551 # if defined (ACE_HAS_TSS_EMULATION)
4552 if (ACE_TSS_Emulation::next_key (*key) == 0)
4554 ACE_TSS_Emulation::tss_destructor (*key, dest);
4556 // Extract out the thread-specific table instance and stash away
4557 // the key and destructor so that we can free it up later on...
4558 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4559 if (cleanup.valid ())
4561 return cleanup->insert (*key, dest);
4563 else
4565 return -1;
4568 else
4569 return -1;
4570 # elif defined (ACE_HAS_WTHREADS)
4571 if (ACE_OS::thr_keycreate_native (key, dest) == 0)
4573 // Extract out the thread-specific table instance and stash away
4574 // the key and destructor so that we can free it up later on...
4575 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4576 if (cleanup.valid ())
4578 return cleanup->insert (*key, dest);
4580 else
4582 return -1;
4585 else
4586 return -1;
4587 /* NOTREACHED */
4588 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4589 return ACE_OS::thr_keycreate_native (key, dest);
4590 # else
4591 ACE_UNUSED_ARG (key);
4592 ACE_UNUSED_ARG (dest);
4593 ACE_NOTSUP_RETURN (-1);
4594 # endif /* ACE_HAS_TSS_EMULATION */
4595 # else /* ACE_HAS_THREADS */
4596 ACE_UNUSED_ARG (key);
4597 ACE_UNUSED_ARG (dest);
4598 ACE_NOTSUP_RETURN (-1);
4599 # endif /* ACE_HAS_THREADS */
4602 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4604 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key)
4606 ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
4607 # if defined (ACE_HAS_THREADS)
4608 # if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
4609 // For some systems, e.g. LynxOS, we need to ensure that
4610 // any registered thread destructor action for this slot
4611 // is now disabled. Otherwise in the event of a dynamic library
4612 // unload of libACE, by a program not linked with libACE,
4613 // ACE_TSS_cleanup will be invoked again at the thread exit
4614 // after libACE has been actually been unmapped from memory.
4615 (void) ACE_OS::thr_setspecific_native (key, 0);
4616 # endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
4617 # if defined (ACE_HAS_PTHREADS)
4618 # if defined (ACE_LACKS_PTHREAD_KEY_DELETE)
4619 ACE_UNUSED_ARG (key);
4620 ACE_NOTSUP_RETURN (-1);
4621 # else
4622 return ::pthread_key_delete (key);
4623 # endif /* ACE_LACKS_PTHREAD_KEY_DELETE */
4624 # elif defined (ACE_HAS_THR_KEYDELETE)
4625 return ::thr_keydelete (key);
4626 # elif defined (ACE_HAS_STHREADS)
4627 ACE_UNUSED_ARG (key);
4628 ACE_NOTSUP_RETURN (-1);
4629 # elif defined (ACE_HAS_WTHREADS)
4630 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
4631 # else
4632 ACE_UNUSED_ARG (key);
4633 ACE_NOTSUP_RETURN (-1);
4634 # endif /* ACE_HAS_PTHREADS */
4635 # else
4636 ACE_UNUSED_ARG (key);
4637 ACE_NOTSUP_RETURN (-1);
4638 # endif /* ACE_HAS_THREADS */
4640 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4643 ACE_OS::thr_keyfree (ACE_thread_key_t key)
4645 ACE_OS_TRACE ("ACE_OS::thr_keyfree");
4646 # if defined (ACE_HAS_THREADS)
4647 # if defined (ACE_HAS_TSS_EMULATION)
4648 // Release the key in the TSS_Emulation administration
4649 ACE_TSS_Emulation::release_key (key);
4650 TSS_Cleanup_Instance cleanup;
4651 if (cleanup.valid ())
4653 return cleanup->free_key (key);
4655 return -1;
4656 # elif defined (ACE_HAS_WTHREADS)
4657 // Extract out the thread-specific table instance and free up
4658 // the key and destructor.
4659 TSS_Cleanup_Instance cleanup;
4660 if (cleanup.valid ())
4662 return cleanup->free_key (key);
4664 return -1;
4665 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4666 return ACE_OS::thr_keyfree_native (key);
4667 # else
4668 ACE_UNUSED_ARG (key);
4669 ACE_NOTSUP_RETURN (-1);
4670 # endif /* ACE_HAS_TSS_EMULATION */
4671 # else /* ACE_HAS_THREADS */
4672 ACE_UNUSED_ARG (key);
4673 ACE_NOTSUP_RETURN (-1);
4674 return 0;
4675 # endif /* ACE_HAS_THREADS */
4679 ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
4681 // Set the thread priority on the current thread.
4682 ACE_hthread_t my_thread_id;
4683 ACE_OS::thr_self (my_thread_id);
4685 int const status = ACE_OS::thr_setprio (my_thread_id, prio);
4687 #if defined (ACE_NEEDS_LWP_PRIO_SET)
4688 // If the thread is in the RT class, then set the priority on its
4689 // LWP. (Instead of doing this if the thread is in the RT class, it
4690 // should be done for all bound threads. But, there doesn't appear
4691 // to be an easy way to determine if the thread is bound.)
4693 if (status == 0)
4695 // Find what scheduling class the thread's LWP is in.
4696 ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0);
4697 if (ACE_OS::lwp_getparams (sched_params) == -1)
4699 return -1;
4701 else if (sched_params.policy () == ACE_SCHED_FIFO ||
4702 sched_params.policy () == ACE_SCHED_RR)
4704 // This thread's LWP is in the RT class, so we need to set
4705 // its priority.
4706 sched_params.priority (prio);
4707 return ACE_OS::lwp_setparams (sched_params);
4709 // else this is not an RT thread. Nothing more needs to be
4710 // done.
4712 #endif /* ACE_NEEDS_LWP_PRIO_SET */
4714 return status;
4717 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4719 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key, void *data)
4721 // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
4722 # if defined (ACE_HAS_THREADS)
4723 # if defined (ACE_HAS_PTHREADS)
4724 int result;
4725 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key, data),
4726 result),
4727 int, -1);
4728 # elif defined (ACE_HAS_STHREADS)
4729 int result;
4730 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), result), int, -1);
4731 # elif defined (ACE_HAS_WTHREADS)
4732 ::TlsSetValue (key, data);
4733 return 0;
4734 # else /* ACE_HAS_STHREADS */
4735 ACE_UNUSED_ARG (key);
4736 ACE_UNUSED_ARG (data);
4737 ACE_NOTSUP_RETURN (-1);
4738 # endif /* ACE_HAS_STHREADS */
4739 # else
4740 ACE_UNUSED_ARG (key);
4741 ACE_UNUSED_ARG (data);
4742 ACE_NOTSUP_RETURN (-1);
4743 # endif /* ACE_HAS_THREADS */
4745 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4748 ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
4750 // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
4751 #if defined (ACE_HAS_THREADS)
4752 # if defined (ACE_HAS_TSS_EMULATION)
4753 if (ACE_TSS_Emulation::is_key (key) == 0)
4755 errno = EINVAL;
4756 data = 0;
4757 return -1;
4759 else
4761 ACE_TSS_Emulation::ts_object (key) = data;
4762 TSS_Cleanup_Instance cleanup;
4763 if (cleanup.valid ())
4765 cleanup->thread_use_key (key);
4766 // for TSS_Cleanup purposes treat stetting data to zero
4767 // like detaching. This is a consequence of POSIX allowing
4768 // deletion of a "used" key.
4769 if (data == 0)
4771 cleanup->thread_detach_key (key);
4773 return 0;
4775 else
4777 return -1;
4780 # elif defined (ACE_HAS_WTHREADS)
4781 if (ACE_OS::thr_setspecific_native (key, data) == 0)
4783 TSS_Cleanup_Instance cleanup;
4784 if (cleanup.valid ())
4786 cleanup->thread_use_key (key);
4787 // for TSS_Cleanup purposes treat stetting data to zero
4788 // like detaching. This is a consequence of POSIX allowing
4789 // deletion of a "used" key.
4790 if (data == 0)
4792 cleanup->thread_detach_key (key);
4794 return 0;
4796 return -1;
4798 return -1;
4799 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4800 return ACE_OS::thr_setspecific_native (key, data);
4801 # else /* ACE_HAS_TSS_EMULATION */
4802 ACE_UNUSED_ARG (key);
4803 ACE_UNUSED_ARG (data);
4804 ACE_NOTSUP_RETURN (-1);
4805 # endif /* ACE_HAS_TSS_EMULATION */
4806 # else /* ACE_HAS_THREADS */
4807 ACE_UNUSED_ARG (key);
4808 ACE_UNUSED_ARG (data);
4809 ACE_NOTSUP_RETURN (-1);
4810 # endif /* ACE_HAS_THREADS */
4813 void
4814 ACE_OS::unique_name (const void *object,
4815 char *name,
4816 size_t length)
4818 // The process ID will provide uniqueness between processes on the
4819 // same machine. The "this" pointer of the <object> will provide
4820 // uniqueness between other "live" objects in the same process. The
4821 // uniqueness of this name is therefore only valid for the life of
4822 // <object>.
4823 ACE_OS::snprintf (name, length, "%p%d", object,
4824 static_cast<int> (ACE_OS::getpid ()));
4827 #if defined (ACE_USES_WCHAR)
4828 void
4829 ACE_OS::unique_name (const void *object,
4830 wchar_t *name,
4831 size_t length)
4833 // The process ID will provide uniqueness between processes on the
4834 // same machine. The "this" pointer of the <object> will provide
4835 // uniqueness between other "live" objects in the same process. The
4836 // uniqueness of this name is therefore only valid for the life of
4837 // <object>.
4838 ACE_OS::snprintf (name, length, ACE_TEXT ("%p%d"), object,
4839 static_cast<int> (ACE_OS::getpid ()));
4841 #endif
4843 pid_t
4844 ACE_OS::thr_gettid ()
4846 #ifdef ACE_HAS_GETTID
4847 return syscall (SYS_gettid);
4848 #else
4849 ACE_NOTSUP_RETURN (-1);
4850 #endif
4853 ACE_END_VERSIONED_NAMESPACE_DECL
4855 #if defined (ACE_VXWORKS) && !defined (__RTP__)
4856 # include /**/ <usrLib.h> /* for ::sp() */
4857 # include /**/ <sysLib.h> /* for ::sysClkRateGet() */
4858 # include "ace/Service_Config.h"
4860 #if !defined (ACE_LACKS_VA_FUNCTIONS)
4862 // This global function can be used from the VxWorks shell to pass
4863 // arguments to a C main () function.
4865 // usage: -> spa main, "arg1", "arg2"
4867 // All arguments must be quoted, even numbers.
4869 spa (FUNCPTR entry, ...)
4871 // The called entrypoint can get the function name plus the normal 10
4872 // optional arguments.
4873 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 1 + 10;
4874 static char *argv[ACE_MAX_ARGS] = { 0 };
4875 va_list pvar;
4876 ACE_VX_USR_ARG_T argc;
4878 // Hardcode a program name because the real one isn't available
4879 // through the VxWorks shell.
4880 argv[0] = const_cast<char*> ("ace_main");
4882 // Peel off arguments to spa () and put into argv. va_arg () isn't
4883 // necessarily supposed to return 0 when done, though since the
4884 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4885 // the unused ones. This function could be used to increase that
4886 // limit, but then it couldn't depend on the trailing 0. So, the
4887 // number of arguments would have to be passed.
4888 va_start (pvar, entry);
4890 for (argc = 1; argc < ACE_MAX_ARGS; ++argc)
4892 argv[argc] = va_arg (pvar, char *);
4894 if (argv[argc] == 0)
4895 break;
4898 if (argc >= ACE_MAX_ARGS && argv[ACE_MAX_ARGS - 1] != 0)
4900 // Try to read another arg, and warn user if the limit was exceeded.
4902 // Note that the VxWorks shell arguments change from int to long when
4903 // using a 64bit compiler. Cast the argument up so that the format
4904 // specifier remains correct for either build type.
4905 if (va_arg (pvar, char *) != 0)
4906 ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %ld\n",
4907 (long)ACE_MAX_ARGS);
4909 else
4911 // fill unused argv slots with 0 to get rid of leftovers
4912 // from previous invocations
4913 for (ACE_VX_USR_ARG_T i = argc; i < ACE_MAX_ARGS; ++i)
4914 argv[i] = 0;
4917 // The hard-coded options are what ::sp () uses, except for the
4918 // larger stack size (instead of ::sp ()'s 20000).
4919 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
4920 100, // task priority
4921 VX_FP_TASK, // task options
4922 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
4923 entry, // entry point
4924 argc, // first argument to main ()
4925 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
4926 0, 0, 0, 0, 0, 0, 0, 0);
4927 va_end (pvar);
4929 // ::taskSpawn () returns the taskID on success: return 0 instead if
4930 // successful
4931 return ret > 0 ? 0 : -1;
4933 #endif /* !ACE_LACKS_VA_FUNCTIONS */
4935 // A helper function for the extended spa functions
4936 static void
4937 add_to_argv (ACE_VX_USR_ARG_T& argc, char** argv, int max_args, char* string)
4939 char indouble = 0;
4940 size_t previous = 0;
4941 size_t length = ACE_OS::strlen (string);
4943 if (length > 0)
4945 // We use <= to make sure that we get the last argument
4946 for (size_t i = 0; i <= length; i++)
4948 // Is it a double quote that hasn't been escaped?
4949 if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
4951 indouble ^= 1;
4952 if (indouble)
4954 // We have just entered a double quoted string, so
4955 // save the starting position of the contents.
4956 previous = i + 1;
4958 else
4960 // We have just left a double quoted string, so
4961 // zero out the ending double quote.
4962 string[i] = '\0';
4965 else if (string[i] == '\\') // Escape the next character
4967 // The next character is automatically skipped because
4968 // of the memmove().
4969 ACE_OS::memmove (string + i, string + i + 1, length);
4970 --length;
4972 else if (!indouble &&
4973 (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
4975 string[i] = '\0';
4976 if (argc < max_args)
4978 argv[argc] = string + previous;
4979 ++argc;
4981 else
4983 ACE_OS::fprintf (stderr, "spae(): number of arguments "
4984 "limited to %d\n", max_args);
4987 // Skip over whitespace in between arguments
4988 for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
4992 // Save the starting point for the next time around
4993 previous = i;
4995 // Make sure we don't skip over a character due
4996 // to the above loop to skip over whitespace
4997 --i;
5003 #if !defined (ACE_LACKS_VA_FUNCTIONS)
5005 // This global function can be used from the VxWorks shell to pass
5006 // arguments to a C main () function.
5008 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
5010 // All arguments must be within double quotes, even numbers.
5012 spae (FUNCPTR entry, ...)
5014 static int const WINDSH_ARGS = 10;
5015 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
5016 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
5017 va_list pvar;
5018 ACE_VX_USR_ARG_T argc = 1;
5020 // Peel off arguments to spa () and put into argv. va_arg () isn't
5021 // necessarily supposed to return 0 when done, though since the
5022 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5023 // the unused ones.
5024 va_start (pvar, entry);
5026 int i = 0;
5027 for (char* str = va_arg (pvar, char*);
5028 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
5030 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
5033 // fill unused argv slots with 0 to get rid of leftovers
5034 // from previous invocations
5035 for (i = argc; i < ACE_MAX_ARGS; ++i)
5036 argv[i] = 0;
5038 // The hard-coded options are what ::sp () uses, except for the
5039 // larger stack size (instead of ::sp ()'s 20000).
5040 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
5041 100, // task priority
5042 VX_FP_TASK, // task options
5043 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
5044 entry, // entry point
5045 argc, // first argument to main ()
5046 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
5047 0, 0, 0, 0, 0, 0, 0, 0);
5048 va_end (pvar);
5050 // ::taskSpawn () returns the taskID on success: return 0 instead if
5051 // successful
5052 return ret > 0 ? 0 : -1;
5055 // This global function can be used from the VxWorks shell to pass
5056 // arguments to a C main () function. The function will be run
5057 // within the shells task.
5059 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
5061 // All arguments must be within double quotes, even numbers.
5062 // Unlike the spae function, this fuction executes the supplied
5063 // routine in the foreground, rather than spawning it in a separate
5064 // task.
5066 spaef (FUNCPTR entry, ...)
5068 static int const WINDSH_ARGS = 10;
5069 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
5070 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
5071 va_list pvar;
5072 ACE_VX_USR_ARG_T argc = 1;
5074 // Peel off arguments to spa () and put into argv. va_arg () isn't
5075 // necessarily supposed to return 0 when done, though since the
5076 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5077 // the unused ones.
5078 va_start (pvar, entry);
5080 int i = 0;
5081 for (char* str = va_arg (pvar, char*);
5082 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
5084 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
5087 // fill unused argv slots with 0 to get rid of leftovers
5088 // from previous invocations
5089 for (i = argc; i < ACE_MAX_ARGS; ++i)
5090 argv[i] = 0;
5092 int ret = entry (argc, argv);
5094 va_end (pvar);
5096 // Return the return value of the invoked ace_main routine.
5097 return ret;
5099 #endif /* !ACE_LACKS_VA_FUNCTIONS */
5101 // This global function can be used from the VxWorks shell to pass
5102 // arguments to and run a main () function (i.e. ace_main).
5104 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
5106 // All arguments must be within double quotes, even numbers.
5107 // This routine spawns the main () function in a separate task and waits till the
5108 // task has finished.
5109 static int _vx_call_rc = 0;
5111 static int
5112 _vx_call_entry(FUNCPTR entry, int argc, char* argv[])
5114 ACE_Service_Config::current (ACE_Service_Config::global());
5115 _vx_call_rc = entry (argc, argv);
5116 return _vx_call_rc;
5120 vx_execae (FUNCPTR entry, char* arg, int prio, int opt, size_t stacksz, ...)
5122 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
5123 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
5124 ACE_VX_USR_ARG_T argc = 1;
5126 // Peel off arguments to run_main () and put into argv.
5127 if (arg)
5129 add_to_argv(argc, argv, ACE_MAX_ARGS, arg);
5132 // fill unused argv slots with 0 to get rid of leftovers
5133 // from previous invocations
5134 for (ACE_VX_USR_ARG_T i = argc; i < ACE_MAX_ARGS; ++i)
5135 argv[i] = 0;
5137 // The hard-coded options are what ::sp () uses, except for the
5138 // larger stack size (instead of ::sp ()'s 20000).
5139 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
5140 prio==0 ? 100 : prio, // task priority
5141 opt==0 ? VX_FP_TASK : opt, // task options
5142 stacksz==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE : stacksz, // stack size
5143 (FUNCPTR)_vx_call_entry, // entrypoint caller
5144 (ACE_VX_USR_ARG_T)entry, // entry point
5145 argc, // first argument to main ()
5146 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
5147 0, 0, 0, 0, 0, 0, 0);
5149 if (ret == ACE_VX_TASK_ID_ERROR)
5150 return 255;
5152 while( ret > 0 && ::taskIdVerify (ret) != ERROR )
5153 ::taskDelay (3 * ::sysClkRateGet ());
5155 // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
5156 // successful
5157 return ret > 0 ? _vx_call_rc : 255;
5160 #if defined(ACE_AS_STATIC_LIBS) && defined (ACE_VXWORKS_DEBUGGING_HELPER)
5161 /** Wind River workbench allows the user to spawn a kernel task as a
5162 "Debug Configuration". Use this function as the entrypoint so that
5163 the arguments are translated into the form that ace_main() requires.
5165 int ace_wb_exec (int arg0, int arg1, int arg2, int arg3, int arg4,
5166 int arg5, int arg6, int arg7, int arg8, int arg9)
5168 return spaef ((FUNCPTR) ace_main, arg0, arg1, arg2, arg3, arg4,
5169 arg5, arg6, arg7, arg8, arg9);
5171 #endif /* ACE_AS_STATIC_LIBS && ... */
5173 #endif /* ACE_VXWORKS && !__RTP__ */