Correct feature names
[ACE_TAO.git] / ACE / ace / OS_NS_Thread.cpp
blobb7af169c91d450825d14b43bca2a9c4cddabcb0e
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 (void)
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 (void)
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 (void)
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 #if defined (ACE_HAS_CPP11)
3604 std::unique_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
3605 #else
3606 auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
3607 #endif /* ACE_HAS_CPP11 */
3609 if (thread_adapter == 0)
3610 ACE_auto_ptr_reset (auto_thread_args,
3611 thread_args);
3613 #if defined (ACE_HAS_THREADS)
3615 // *** Set Stack Size
3616 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3617 if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3618 stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
3619 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
3621 ACE_thread_t tmp_thr;
3622 if (thr_id == 0)
3623 thr_id = &tmp_thr;
3625 ACE_hthread_t tmp_handle;
3626 if (thr_handle == 0)
3627 thr_handle = &tmp_handle;
3629 # if defined (ACE_HAS_PTHREADS)
3630 int result;
3631 # if defined (ACE_PTHREAD_ATTR_T_INITIALIZE)
3632 /* Tests show that VxWorks 6.x pthread lib does not only
3633 * require zeroing of mutex/condition objects to function correctly
3634 * but also of the attribute objects.
3636 pthread_attr_t attr = {0};
3637 # else
3638 pthread_attr_t attr;
3639 # endif
3640 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr), result) != 0)
3641 return -1;
3643 if (stacksize != 0)
3645 size_t size = stacksize;
3647 # if defined (PTHREAD_STACK_MIN)
3648 if (size < static_cast <size_t> (PTHREAD_STACK_MIN))
3649 size = PTHREAD_STACK_MIN;
3650 # endif /* PTHREAD_STACK_MIN */
3652 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
3653 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3654 int result;
3655 if (stack != 0)
3656 result = ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr, stack, size), result);
3657 else
3658 result = ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result);
3659 if (result == -1)
3660 # else
3661 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result) == -1)
3662 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3664 ::pthread_attr_destroy (&attr);
3665 return -1;
3667 # else
3668 ACE_UNUSED_ARG (size);
3669 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
3672 // *** Set Stack Address
3673 # if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3674 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
3675 if (stack != 0)
3677 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr, stack), result) != 0)
3679 ::pthread_attr_destroy (&attr);
3680 return -1;
3683 # else
3684 ACE_UNUSED_ARG (stack);
3685 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3686 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3688 // *** Deal with various attributes
3689 if (flags != 0)
3691 // *** Set Detach state
3692 # if !defined (ACE_LACKS_SETDETACH)
3693 if (ACE_BIT_ENABLED (flags, THR_DETACHED)
3694 || ACE_BIT_ENABLED (flags, THR_JOINABLE))
3696 int dstate = PTHREAD_CREATE_JOINABLE;
3698 if (ACE_BIT_ENABLED (flags, THR_DETACHED))
3699 dstate = PTHREAD_CREATE_DETACHED;
3701 if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
3702 result) != 0)
3704 ::pthread_attr_destroy (&attr);
3705 return -1;
3709 // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
3710 // call ::pthread_detach () below. If THR_DETACHED is not
3711 // enabled, we call ::pthread_detach () in the Thread_Manager,
3712 // after joining with the thread.
3713 # endif /* ACE_LACKS_SETDETACH */
3715 // *** Set Policy
3716 # if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3717 // If we wish to set the priority explicitly, we have to enable
3718 // explicit scheduling, and a policy, too.
3719 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3721 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3722 if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
3723 && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
3724 && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
3725 ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
3728 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3729 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3730 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3732 int spolicy;
3734 # if defined (ACE_HAS_ONLY_SCHED_OTHER)
3735 // SunOS, thru version 5.6, only supports SCHED_OTHER.
3736 spolicy = SCHED_OTHER;
3737 # elif defined (ACE_HAS_ONLY_SCHED_FIFO)
3738 // NonStop OSS standard pthread supports only SCHED_FIFO.
3739 spolicy = SCHED_FIFO;
3740 # else
3741 // Make sure to enable explicit scheduling, in case we didn't
3742 // enable it above (for non-default priority).
3743 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3745 if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3746 spolicy = SCHED_OTHER;
3747 else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3748 spolicy = SCHED_FIFO;
3749 # if defined (SCHED_IO)
3750 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3751 spolicy = SCHED_IO;
3752 # else
3753 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3755 errno = ENOSYS;
3756 return -1;
3758 # endif /* SCHED_IO */
3759 else
3760 spolicy = SCHED_RR;
3762 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3764 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
3765 result);
3766 if (result != 0)
3768 ::pthread_attr_destroy (&attr);
3769 return -1;
3773 // *** Set Priority (use reasonable default priorities)
3774 # if defined(ACE_HAS_PTHREADS)
3775 // If we wish to explicitly set a scheduling policy, we also
3776 // have to specify a priority. We choose a "middle" priority as
3777 // default. Maybe this is also necessary on other POSIX'ish
3778 // implementations?
3779 if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3780 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3781 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3782 && priority == ACE_DEFAULT_THREAD_PRIORITY)
3784 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3785 priority = ACE_THR_PRI_FIFO_DEF;
3786 else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
3787 priority = ACE_THR_PRI_RR_DEF;
3788 else // THR_SCHED_DEFAULT
3789 priority = ACE_THR_PRI_OTHER_DEF;
3791 # endif /* ACE_HAS_PTHREADS */
3792 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3794 struct sched_param sparam;
3795 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
3797 # if defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
3798 /* For MIT pthreads... */
3799 sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
3800 # elif defined(ACE_HAS_PTHREADS) && !defined (ACE_HAS_STHREADS)
3801 // The following code forces priority into range.
3802 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3803 sparam.sched_priority =
3804 ACE_MIN (ACE_THR_PRI_FIFO_MAX,
3805 ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
3806 else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
3807 sparam.sched_priority =
3808 ACE_MIN (ACE_THR_PRI_RR_MAX,
3809 ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
3810 else // Default policy, whether set or not
3811 sparam.sched_priority =
3812 ACE_MIN (ACE_THR_PRI_OTHER_MAX,
3813 ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
3814 # elif defined (PRIORITY_MAX)
3815 sparam.sched_priority = ACE_MIN (priority,
3816 (long) PRIORITY_MAX);
3817 # else
3818 sparam.sched_priority = priority;
3819 # endif /* PTHREAD_MAX_PRIORITY */
3822 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
3823 // SunOS, through 5.6, POSIX only allows priorities > 0 to
3824 // ::pthread_attr_setschedparam. If a priority of 0 was
3825 // requested, set the thread priority after creating it, below.
3826 if (priority > 0)
3827 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
3829 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
3830 result);
3831 if (result != 0)
3833 ::pthread_attr_destroy (&attr);
3834 return -1;
3840 # if !defined (ACE_LACKS_SETINHERITSCHED)
3841 // *** Set scheduling explicit or inherited
3842 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
3843 || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
3845 int sched = PTHREAD_EXPLICIT_SCHED;
3846 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
3847 sched = PTHREAD_INHERIT_SCHED;
3848 if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr, sched), result) != 0)
3850 ::pthread_attr_destroy (&attr);
3851 return -1;
3854 # endif /* ACE_LACKS_SETINHERITSCHED */
3855 # else /* ACE_LACKS_SETSCHED */
3856 ACE_UNUSED_ARG (priority);
3857 # endif /* ACE_LACKS_SETSCHED */
3859 // *** Set pthread name
3860 # if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3861 if (thr_name && *thr_name)
3863 if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr, const_cast<char*>(*thr_name)), result) != 0)
3865 ::pthread_attr_destroy (&attr);
3866 return -1;
3869 #else
3870 ACE_UNUSED_ARG (thr_name);
3871 # endif
3873 // *** Set Scope
3874 # if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
3875 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
3876 || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
3878 # if defined (ACE_LACKS_PTHREAD_SCOPE_PROCESS)
3879 int scope = PTHREAD_SCOPE_SYSTEM;
3880 # else /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3881 int scope = PTHREAD_SCOPE_PROCESS;
3882 # endif /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3883 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
3884 scope = PTHREAD_SCOPE_SYSTEM;
3886 if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr, scope), result) != 0)
3888 ::pthread_attr_destroy (&attr);
3889 return -1;
3892 # endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
3894 # ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
3895 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED))
3897 if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr), result) != 0)
3900 ::pthread_attr_destroy (&attr);
3901 return -1;
3904 # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
3906 # if ! defined(ACE_LACKS_THR_CONCURRENCY_FUNCS)
3907 if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
3909 // Increment the number of LWPs by one to emulate the
3910 // SunOS semantics.
3911 int lwps = ACE_OS::thr_getconcurrency ();
3912 if (lwps == -1)
3914 if (errno == ENOTSUP)
3915 // Suppress the ENOTSUP because it's harmless.
3916 errno = 0;
3917 else
3918 // This should never happen on SunOS:
3919 // ::thr_getconcurrency () should always succeed.
3920 return -1;
3922 else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
3924 if (errno == ENOTSUP)
3926 // Unlikely: ::thr_getconcurrency () is supported
3927 // but ::thr_setconcurrency () is not?
3929 else
3930 return -1;
3933 # endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */
3936 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
3937 &attr,
3938 thread_args->entry_point (),
3939 thread_args),
3940 result),
3941 int, -1, result);
3942 ::pthread_attr_destroy (&attr);
3944 // This is a SunOS or POSIX implementation of pthreads, where we
3945 // assume that ACE_thread_t and ACE_hthread_t are the same. If this
3946 // *isn't* correct on some platform, please let us know.
3947 if (result != -1)
3948 *thr_handle = *thr_id;
3950 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
3951 // SunOS prior to 5.7:
3953 // If the priority is 0, then we might have to set it now because we
3954 // couldn't set it with ::pthread_attr_setschedparam, as noted
3955 // above. This doesn't provide strictly correct behavior, because
3956 // the thread was created (above) with the priority of its parent.
3957 // (That applies regardless of the inherit_sched attribute: if it
3958 // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
3959 // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then "attr"
3960 // was initialized by the SunOS ::pthread_attr_init () to contain
3961 // NULL for the priority, which indicated to SunOS ::pthread_create
3962 // () to inherit the parent priority.)
3963 if (priority == 0)
3965 // Check the priority of this thread, which is the parent
3966 // of the newly created thread. If it is 0, then the
3967 // newly created thread will have inherited the priority
3968 // of 0, so there's no need to explicitly set it.
3969 struct sched_param sparam;
3970 int policy = 0;
3971 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
3972 &policy,
3973 &sparam),
3974 result), int,
3975 -1, result);
3977 // The only policy supported by by SunOS, thru version 5.6,
3978 // is SCHED_OTHER, so that's hard-coded here.
3979 policy = ACE_SCHED_OTHER;
3981 if (sparam.sched_priority != 0)
3983 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
3984 // The memset to 0 sets the priority to 0, so we don't need
3985 // to explicitly set sparam.sched_priority.
3987 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id,
3988 policy,
3989 &sparam),
3990 result),
3991 int, -1);
3995 # if defined (ACE_NEEDS_LWP_PRIO_SET)
3996 # if 0
3997 // It would be useful if we could make this work. But, it requires
3998 // a mechanism for determining the ID of an LWP to which another
3999 // thread is bound. Is there a way to do that? Instead, just rely
4000 // on the code in ACE_Thread_Adapter::invoke () to set the LWP
4001 // priority.
4003 // If the thread is bound, then set the priority on its LWP.
4004 if (ACE_BIT_ENABLED (flags, THR_BOUND))
4006 ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) ||
4007 ACE_BIT_ENABLED (flags, THR_SCHED_RR) ?
4008 ACE_SCHED_FIFO :
4009 ACE_SCHED_OTHER,
4010 priority);
4011 result = ACE_OS::lwp_setparams (sched_params,
4012 /* ? How do we find the ID of the LWP
4013 to which *thr_id is bound? */);
4015 # endif /* 0 */
4016 # endif /* ACE_NEEDS_LWP_PRIO_SET */
4018 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4019 auto_thread_args.release ();
4020 return result;
4021 # elif defined (ACE_HAS_STHREADS)
4022 int result;
4023 int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
4025 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4026 // If we need to set the priority, then we need to start the
4027 // thread in a suspended mode.
4028 ACE_SET_BITS (flags, THR_SUSPENDED);
4030 ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize,
4031 thread_args->entry_point (),
4032 thread_args,
4033 flags, thr_id), result),
4034 int, -1, result);
4036 if (result != -1)
4038 // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
4039 *thr_handle = *thr_id;
4041 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4043 // Set the priority of the new thread and then let it
4044 // continue, but only if the user didn't start it suspended
4045 // in the first place!
4046 result = ACE_OS::thr_setprio (*thr_id, priority);
4047 if (result != 0)
4049 errno = result;
4050 return -1;
4053 if (start_suspended == 0)
4055 result = ACE_OS::thr_continue (*thr_id);
4056 if (result != 0)
4058 errno = result;
4059 return -1;
4064 auto_thread_args.release ();
4065 return result;
4066 # elif defined (ACE_HAS_WTHREADS)
4067 ACE_UNUSED_ARG (thr_name);
4068 ACE_UNUSED_ARG (stack);
4069 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4070 if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
4072 CWinThread *cwin_thread =
4073 ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
4074 thread_args,
4075 priority,
4077 flags | THR_SUSPENDED);
4078 // Have to duplicate the handle because
4079 // CWinThread::~CWinThread() closes the original handle.
4080 # if !defined (ACE_HAS_WINCE)
4081 (void) ::DuplicateHandle (::GetCurrentProcess (),
4082 cwin_thread->m_hThread,
4083 ::GetCurrentProcess (),
4084 thr_handle,
4086 TRUE,
4087 DUPLICATE_SAME_ACCESS);
4088 # endif /* ! ACE_HAS_WINCE */
4089 *thr_id = cwin_thread->m_nThreadID;
4091 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
4092 cwin_thread->ResumeThread ();
4093 // cwin_thread will be deleted in AfxThreadExit()
4094 // Warning: If AfxThreadExit() is called from within the
4095 // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
4097 else
4098 # endif /* ACE_HAS_MFC */
4100 int const start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
4102 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4103 // If we need to set the priority, then we need to start the
4104 // thread in a suspended mode.
4105 ACE_SET_BITS (flags, THR_SUSPENDED);
4107 *thr_handle = (void *) ACE_BEGINTHREADEX (0,
4108 static_cast <u_int> (stacksize),
4109 thread_args->entry_point (),
4110 thread_args,
4111 flags,
4112 thr_id);
4114 if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
4116 // Set the priority of the new thread and then let it
4117 // continue, but only if the user didn't start it suspended
4118 // in the first place!
4119 if (ACE_OS::thr_setprio (*thr_handle, priority) != 0)
4121 return -1;
4124 if (start_suspended == 0)
4126 ACE_OS::thr_continue (*thr_handle);
4131 // Close down the handle if no one wants to use it.
4132 if (thr_handle == &tmp_handle && tmp_handle != 0)
4133 ::CloseHandle (tmp_handle);
4135 if (*thr_handle != 0)
4137 auto_thread_args.release ();
4138 return 0;
4140 else
4141 ACE_FAIL_RETURN (-1);
4142 /* NOTREACHED */
4144 # elif defined (ACE_VXWORKS)
4145 // The hard-coded values below are what ::sp () would use. (::sp ()
4146 // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
4147 // 20,000.) stacksize should be an even integer. If a stack is not
4148 // specified, ::taskSpawn () is used so that we can set the
4149 // priority, flags, and stacksize. If a stack is specified,
4150 // ::taskInit ()/::taskActivate() are used.
4152 // If called with thr_create() defaults, use same default values as ::sp ():
4153 if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
4154 // Assumes that there is a floating point coprocessor. As noted
4155 // above, ::sp () hardcodes this, so we should be safe with it.
4156 if (flags == 0) flags = VX_FP_TASK;
4157 if (stacksize == 0) stacksize = 20000;
4159 ACE_thread_t tid;
4160 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4161 if (stack == 0)
4163 # else
4164 ACE_UNUSED_ARG (stack);
4165 # endif /* 0 */
4166 // The call below to ::taskSpawn () causes VxWorks to assign a
4167 // unique task name of the form: "t" + an integer, because the
4168 // first argument is 0.
4169 tid = ::taskSpawn (thr_name && *thr_name ? const_cast <char*> (*thr_name) : 0,
4170 priority,
4171 (int) flags,
4172 stacksize,
4173 thread_args->entry_point (),
4174 (ACE_VX_USR_ARG_T) thread_args,
4175 0, 0, 0, 0, 0, 0, 0, 0, 0);
4176 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4178 else
4180 // If a task name (thr_id) was not supplied, then the task will
4181 // not have a unique name. That's VxWorks' behavior.
4183 // Carve out a TCB at the beginning of the stack space. The TCB
4184 // occupies 400 bytes with VxWorks 5.3.1/I386.
4185 WIND_TCB *tcb = (WIND_TCB *) stack;
4187 // The TID is defined to be the address of the TCB.
4188 int status = ::taskInit (tcb,
4189 thr_name && *thr_name ? const_cast <char*>(*thr_name) : 0,
4190 priority,
4191 (int) flags,
4192 (char *) stack + sizeof (WIND_TCB),
4193 (int) (stacksize - sizeof (WIND_TCB)),
4194 thread_args->entry_point (),
4195 (int) thread_args,
4196 0, 0, 0, 0, 0, 0, 0, 0, 0);
4198 if (status == OK)
4200 // The task was successfully initialized, now activate it.
4201 status = ::taskActivate ((ACE_hthread_t) tcb);
4204 tid = status == OK ? (ACE_thread_t) tcb : ERROR;
4206 # endif /* 0 */
4208 if (tid == ACE_VX_TASK_ID_ERROR)
4209 return -1;
4210 else
4212 if (thr_id)
4213 *thr_id = tid;
4215 if (thr_handle)
4216 *thr_handle = tid;
4218 if (thr_name && !(*thr_name))
4219 *thr_name = ::taskName (tid);
4221 auto_thread_args.release ();
4222 return 0;
4225 # endif /* ACE_HAS_STHREADS */
4226 #else
4227 ACE_UNUSED_ARG (func);
4228 ACE_UNUSED_ARG (args);
4229 ACE_UNUSED_ARG (flags);
4230 ACE_UNUSED_ARG (thr_id);
4231 ACE_UNUSED_ARG (thr_handle);
4232 ACE_UNUSED_ARG (priority);
4233 ACE_UNUSED_ARG (stack);
4234 ACE_UNUSED_ARG (stacksize);
4235 ACE_UNUSED_ARG (thr_name);
4236 ACE_NOTSUP_RETURN (-1);
4237 #endif /* ACE_HAS_THREADS */
4240 void
4241 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
4243 ACE_OS_TRACE ("ACE_OS::thr_exit");
4244 #if defined (ACE_HAS_THREADS)
4245 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_EXIT)
4246 ::pthread_exit (status);
4247 # elif defined (ACE_HAS_STHREADS)
4248 ::thr_exit (status);
4249 # elif defined (ACE_HAS_WTHREADS)
4250 // Can't call it here because on NT, the thread is exited
4251 // directly by ACE_Thread_Adapter::invoke ().
4252 // ACE_TSS_Cleanup::instance ()->thread_exit (status);
4254 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4255 int using_afx = -1;
4256 // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
4257 // But without #including ace/Thread_Manager.h, we don't know that.
4258 ACE_OS_Thread_Descriptor *td =
4259 ACE_Base_Thread_Adapter::thr_desc_log_msg ();
4260 if (td)
4261 using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
4262 # endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
4264 // Call TSS destructors.
4265 ACE_OS::cleanup_tss (0 /* not main thread */);
4267 // Exit the thread.
4268 // Allow CWinThread-destructor to be invoked from AfxEndThread.
4269 // _endthreadex will be called from AfxEndThread so don't exit the
4270 // thread now if we are running an MFC thread.
4271 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4272 if (using_afx != -1)
4274 if (using_afx)
4275 ::AfxEndThread (status);
4276 else
4277 ACE_ENDTHREADEX (status);
4279 else
4281 // Not spawned by ACE_Thread_Manager, use the old buggy
4282 // version. You should seriously consider using
4283 // ACE_Thread_Manager to spawn threads. The following code is
4284 // know to cause some problem.
4285 CWinThread *pThread = ::AfxGetThread ();
4286 if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
4287 ACE_ENDTHREADEX (status);
4288 else
4289 ::AfxEndThread (status);
4291 # else
4292 ACE_ENDTHREADEX (status);
4293 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
4295 # elif defined (ACE_HAS_VXTHREADS)
4296 ACE_UNUSED_ARG (status);
4297 ::taskDelete (ACE_OS::thr_self ());
4298 # else
4299 ACE_UNUSED_ARG (status);
4300 # endif /* ACE_HAS_PTHREADS */
4301 #else
4302 ACE_UNUSED_ARG (status);
4303 #endif /* ACE_HAS_THREADS */
4306 #if defined (ACE_HAS_VXTHREADS)
4307 // Leave this in the global scope to allow
4308 // users to adjust the delay value.
4309 int ACE_THR_JOIN_DELAY = 5;
4312 ACE_OS::thr_join (ACE_hthread_t thr_handle,
4313 ACE_THR_FUNC_RETURN *status)
4315 // We can't get the status of the thread
4316 if (status != 0)
4318 *status = 0;
4321 // This method can not support joining all threads
4322 if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
4324 ACE_NOTSUP_RETURN (-1);
4327 int retval = ESRCH;
4328 ACE_thread_t current = ACE_OS::thr_self ();
4330 // Make sure we are not joining ourself
4331 if (ACE_OS::thr_cmp (thr_handle, current))
4333 retval = EDEADLK;
4335 else
4337 // Whether the task exists or not
4338 // we will return a successful value
4339 retval = 0;
4341 // Verify that the task id still exists
4342 while (taskIdVerify (thr_handle) == OK)
4344 // Wait a bit to see if the task is still active.
4345 ACE_OS::sleep (ACE_THR_JOIN_DELAY);
4349 // Adapt the return value into errno and return value.
4350 // The ACE_ADAPT_RETVAL macro doesn't exactly do what
4351 // we need to do here, so we do it manually.
4352 if (retval != 0)
4354 errno = retval;
4355 retval = -1;
4358 return retval;
4362 ACE_OS::thr_join (ACE_thread_t waiter_id,
4363 ACE_thread_t *thr_id,
4364 ACE_THR_FUNC_RETURN *status)
4366 thr_id = 0;
4367 return ACE_OS::thr_join (waiter_id, status);
4369 #endif /* ACE_HAS_VXTHREADS */
4372 ACE_OS::thr_key_detach (ACE_thread_key_t key)
4374 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
4375 TSS_Cleanup_Instance cleanup;
4376 if (cleanup.valid ())
4378 return cleanup->thread_detach_key (key);
4380 else
4382 return -1;
4384 #else
4385 ACE_UNUSED_ARG (key);
4386 ACE_NOTSUP_RETURN (-1);
4387 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
4391 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id,
4392 size_t cpu_set_size,
4393 cpu_set_t * cpu_mask)
4395 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
4396 // Handle of the thread, which is NPTL thread-id, normally a big number
4397 if (::pthread_getaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4399 return -1;
4401 return 0;
4402 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
4403 // The process-id is expected as <thr_id>, which can be a thread-id of
4404 // linux-thread, thus making binding to cpu of that particular thread only.
4405 // If you are using this flag for NPTL-threads, however, please pass as a
4406 // thr_id process id obtained by ACE_OS::getpid ()
4407 ACE_UNUSED_ARG (cpu_set_size);
4408 if (::sched_getaffinity(thr_id, cpu_mask) == -1)
4410 return -1;
4412 return 0;
4413 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
4414 // The process-id is expected as <thr_id>, which can be a thread-id of
4415 // linux-thread, thus making binding to cpu of that particular thread only.
4416 // If you are using this flag for NPTL-threads, however, please pass as a
4417 // thr_id process id obtained by ACE_OS::getpid ()
4418 if (::sched_getaffinity(thr_id, cpu_set_size, cpu_mask) == -1)
4420 return -1;
4422 return 0;
4423 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4424 ACE_UNUSED_ARG (cpu_set_size);
4425 int result = 0;
4426 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id, *cpu_mask), result) == -1)
4428 return -1;
4430 return 0;
4431 #else
4432 ACE_UNUSED_ARG (thr_id);
4433 ACE_UNUSED_ARG (cpu_set_size);
4434 ACE_UNUSED_ARG (cpu_mask);
4435 ACE_NOTSUP_RETURN (-1);
4436 #endif
4440 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id,
4441 size_t cpu_set_size,
4442 const cpu_set_t * cpu_mask)
4444 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
4445 if (::pthread_setaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4447 return -1;
4449 return 0;
4450 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
4451 // The process-id is expected as <thr_id>, which can be a thread-id of
4452 // linux-thread, thus making binding to cpu of that particular thread only.
4453 // If you are using this flag for NPTL-threads, however, please pass as a
4454 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4456 ACE_UNUSED_ARG (cpu_set_size);
4457 if (::sched_setaffinity (thr_id, cpu_mask) == -1)
4459 return -1;
4461 return 0;
4462 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
4463 // The process-id is expected as <thr_id>, which can be a thread-id of
4464 // linux-thread, thus making binding to cpu of that particular thread only.
4465 // If you are using this flag for NPTL-threads, however, please pass as a
4466 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4468 if (::sched_setaffinity (thr_id, cpu_set_size, cpu_mask) == -1)
4470 return -1;
4472 return 0;
4473 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4474 ACE_UNUSED_ARG (cpu_set_size);
4475 int result = 0;
4476 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id, *cpu_mask), result) == -1)
4478 return -1;
4480 return 0;
4481 #else
4482 ACE_UNUSED_ARG (thr_id);
4483 ACE_UNUSED_ARG (cpu_set_size);
4484 ACE_UNUSED_ARG (cpu_mask);
4485 ACE_NOTSUP_RETURN (-1);
4486 #endif
4490 ACE_OS::thr_key_used (ACE_thread_key_t key)
4492 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
4493 TSS_Cleanup_Instance cleanup;
4494 if (cleanup.valid ())
4496 cleanup->thread_use_key (key);
4497 return 0;
4499 return -1;
4500 #else
4501 ACE_UNUSED_ARG (key);
4502 ACE_NOTSUP_RETURN (-1);
4503 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
4506 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4508 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t *key,
4509 # if defined (ACE_HAS_THR_C_DEST)
4510 ACE_THR_C_DEST dest
4511 # else
4512 ACE_THR_DEST dest
4513 # endif /* ACE_HAS_THR_C_DEST */
4516 // can't trace here. Trace uses TSS
4517 // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
4518 # if defined (ACE_HAS_THREADS)
4519 # if defined (ACE_HAS_PTHREADS)
4520 int result;
4521 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
4522 result),
4523 int, -1);
4524 # elif defined (ACE_HAS_STHREADS)
4525 int result;
4526 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
4527 result),
4528 int, -1);
4529 # elif defined (ACE_HAS_WTHREADS)
4530 ACE_UNUSED_ARG (dest);
4531 *key = ::TlsAlloc ();
4533 if (*key == ACE_SYSCALL_FAILED)
4534 ACE_FAIL_RETURN (-1);
4535 return 0;
4536 # endif /* ACE_HAS_STHREADS */
4537 # else
4538 ACE_UNUSED_ARG (key);
4539 ACE_UNUSED_ARG (dest);
4540 ACE_NOTSUP_RETURN (-1);
4541 # endif /* ACE_HAS_THREADS */
4543 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4546 ACE_OS::thr_keycreate (ACE_thread_key_t *key,
4547 # if defined (ACE_HAS_THR_C_DEST)
4548 ACE_THR_C_DEST dest)
4549 # else
4550 ACE_THR_DEST dest)
4551 # endif /* ACE_HAS_THR_C_DEST */
4553 // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
4554 #if defined (ACE_HAS_THREADS)
4555 # if defined (ACE_HAS_TSS_EMULATION)
4556 if (ACE_TSS_Emulation::next_key (*key) == 0)
4558 ACE_TSS_Emulation::tss_destructor (*key, dest);
4560 // Extract out the thread-specific table instance and stash away
4561 // the key and destructor so that we can free it up later on...
4562 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4563 if (cleanup.valid ())
4565 return cleanup->insert (*key, dest);
4567 else
4569 return -1;
4572 else
4573 return -1;
4574 # elif defined (ACE_HAS_WTHREADS)
4575 if (ACE_OS::thr_keycreate_native (key, dest) == 0)
4577 // Extract out the thread-specific table instance and stash away
4578 // the key and destructor so that we can free it up later on...
4579 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4580 if (cleanup.valid ())
4582 return cleanup->insert (*key, dest);
4584 else
4586 return -1;
4589 else
4590 return -1;
4591 /* NOTREACHED */
4592 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4593 return ACE_OS::thr_keycreate_native (key, dest);
4594 # else
4595 ACE_UNUSED_ARG (key);
4596 ACE_UNUSED_ARG (dest);
4597 ACE_NOTSUP_RETURN (-1);
4598 # endif /* ACE_HAS_TSS_EMULATION */
4599 # else /* ACE_HAS_THREADS */
4600 ACE_UNUSED_ARG (key);
4601 ACE_UNUSED_ARG (dest);
4602 ACE_NOTSUP_RETURN (-1);
4603 # endif /* ACE_HAS_THREADS */
4606 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4608 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key)
4610 ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
4611 # if defined (ACE_HAS_THREADS)
4612 # if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
4613 // For some systems, e.g. LynxOS, we need to ensure that
4614 // any registered thread destructor action for this slot
4615 // is now disabled. Otherwise in the event of a dynamic library
4616 // unload of libACE, by a program not linked with libACE,
4617 // ACE_TSS_cleanup will be invoked again at the thread exit
4618 // after libACE has been actually been unmapped from memory.
4619 (void) ACE_OS::thr_setspecific_native (key, 0);
4620 # endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
4621 # if defined (ACE_HAS_PTHREADS)
4622 # if defined (ACE_LACKS_PTHREAD_KEY_DELETE)
4623 ACE_UNUSED_ARG (key);
4624 ACE_NOTSUP_RETURN (-1);
4625 # else
4626 return ::pthread_key_delete (key);
4627 # endif /* ACE_LACKS_PTHREAD_KEY_DELETE */
4628 # elif defined (ACE_HAS_THR_KEYDELETE)
4629 return ::thr_keydelete (key);
4630 # elif defined (ACE_HAS_STHREADS)
4631 ACE_UNUSED_ARG (key);
4632 ACE_NOTSUP_RETURN (-1);
4633 # elif defined (ACE_HAS_WTHREADS)
4634 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
4635 # else
4636 ACE_UNUSED_ARG (key);
4637 ACE_NOTSUP_RETURN (-1);
4638 # endif /* ACE_HAS_PTHREADS */
4639 # else
4640 ACE_UNUSED_ARG (key);
4641 ACE_NOTSUP_RETURN (-1);
4642 # endif /* ACE_HAS_THREADS */
4644 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4647 ACE_OS::thr_keyfree (ACE_thread_key_t key)
4649 ACE_OS_TRACE ("ACE_OS::thr_keyfree");
4650 # if defined (ACE_HAS_THREADS)
4651 # if defined (ACE_HAS_TSS_EMULATION)
4652 // Release the key in the TSS_Emulation administration
4653 ACE_TSS_Emulation::release_key (key);
4654 TSS_Cleanup_Instance cleanup;
4655 if (cleanup.valid ())
4657 return cleanup->free_key (key);
4659 return -1;
4660 # elif defined (ACE_HAS_WTHREADS)
4661 // Extract out the thread-specific table instance and free up
4662 // the key and destructor.
4663 TSS_Cleanup_Instance cleanup;
4664 if (cleanup.valid ())
4666 return cleanup->free_key (key);
4668 return -1;
4669 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4670 return ACE_OS::thr_keyfree_native (key);
4671 # else
4672 ACE_UNUSED_ARG (key);
4673 ACE_NOTSUP_RETURN (-1);
4674 # endif /* ACE_HAS_TSS_EMULATION */
4675 # else /* ACE_HAS_THREADS */
4676 ACE_UNUSED_ARG (key);
4677 ACE_NOTSUP_RETURN (-1);
4678 return 0;
4679 # endif /* ACE_HAS_THREADS */
4683 ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
4685 // Set the thread priority on the current thread.
4686 ACE_hthread_t my_thread_id;
4687 ACE_OS::thr_self (my_thread_id);
4689 int const status = ACE_OS::thr_setprio (my_thread_id, prio);
4691 #if defined (ACE_NEEDS_LWP_PRIO_SET)
4692 // If the thread is in the RT class, then set the priority on its
4693 // LWP. (Instead of doing this if the thread is in the RT class, it
4694 // should be done for all bound threads. But, there doesn't appear
4695 // to be an easy way to determine if the thread is bound.)
4697 if (status == 0)
4699 // Find what scheduling class the thread's LWP is in.
4700 ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0);
4701 if (ACE_OS::lwp_getparams (sched_params) == -1)
4703 return -1;
4705 else if (sched_params.policy () == ACE_SCHED_FIFO ||
4706 sched_params.policy () == ACE_SCHED_RR)
4708 // This thread's LWP is in the RT class, so we need to set
4709 // its priority.
4710 sched_params.priority (prio);
4711 return ACE_OS::lwp_setparams (sched_params);
4713 // else this is not an RT thread. Nothing more needs to be
4714 // done.
4716 #endif /* ACE_NEEDS_LWP_PRIO_SET */
4718 return status;
4721 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4723 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key, void *data)
4725 // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
4726 # if defined (ACE_HAS_THREADS)
4727 # if defined (ACE_HAS_PTHREADS)
4728 int result;
4729 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key, data),
4730 result),
4731 int, -1);
4732 # elif defined (ACE_HAS_STHREADS)
4733 int result;
4734 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), result), int, -1);
4735 # elif defined (ACE_HAS_WTHREADS)
4736 ::TlsSetValue (key, data);
4737 return 0;
4738 # else /* ACE_HAS_STHREADS */
4739 ACE_UNUSED_ARG (key);
4740 ACE_UNUSED_ARG (data);
4741 ACE_NOTSUP_RETURN (-1);
4742 # endif /* ACE_HAS_STHREADS */
4743 # else
4744 ACE_UNUSED_ARG (key);
4745 ACE_UNUSED_ARG (data);
4746 ACE_NOTSUP_RETURN (-1);
4747 # endif /* ACE_HAS_THREADS */
4749 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4752 ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
4754 // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
4755 #if defined (ACE_HAS_THREADS)
4756 # if defined (ACE_HAS_TSS_EMULATION)
4757 if (ACE_TSS_Emulation::is_key (key) == 0)
4759 errno = EINVAL;
4760 data = 0;
4761 return -1;
4763 else
4765 ACE_TSS_Emulation::ts_object (key) = data;
4766 TSS_Cleanup_Instance cleanup;
4767 if (cleanup.valid ())
4769 cleanup->thread_use_key (key);
4770 // for TSS_Cleanup purposes treat stetting data to zero
4771 // like detaching. This is a consequence of POSIX allowing
4772 // deletion of a "used" key.
4773 if (data == 0)
4775 cleanup->thread_detach_key (key);
4777 return 0;
4779 else
4781 return -1;
4784 # elif defined (ACE_HAS_WTHREADS)
4785 if (ACE_OS::thr_setspecific_native (key, data) == 0)
4787 TSS_Cleanup_Instance cleanup;
4788 if (cleanup.valid ())
4790 cleanup->thread_use_key (key);
4791 // for TSS_Cleanup purposes treat stetting data to zero
4792 // like detaching. This is a consequence of POSIX allowing
4793 // deletion of a "used" key.
4794 if (data == 0)
4796 cleanup->thread_detach_key (key);
4798 return 0;
4800 return -1;
4802 return -1;
4803 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4804 return ACE_OS::thr_setspecific_native (key, data);
4805 # else /* ACE_HAS_TSS_EMULATION */
4806 ACE_UNUSED_ARG (key);
4807 ACE_UNUSED_ARG (data);
4808 ACE_NOTSUP_RETURN (-1);
4809 # endif /* ACE_HAS_TSS_EMULATION */
4810 # else /* ACE_HAS_THREADS */
4811 ACE_UNUSED_ARG (key);
4812 ACE_UNUSED_ARG (data);
4813 ACE_NOTSUP_RETURN (-1);
4814 # endif /* ACE_HAS_THREADS */
4817 void
4818 ACE_OS::unique_name (const void *object,
4819 char *name,
4820 size_t length)
4822 // The process ID will provide uniqueness between processes on the
4823 // same machine. The "this" pointer of the <object> will provide
4824 // uniqueness between other "live" objects in the same process. The
4825 // uniqueness of this name is therefore only valid for the life of
4826 // <object>.
4827 ACE_OS::snprintf (name, length, "%p%d", object,
4828 static_cast<int> (ACE_OS::getpid ()));
4831 #if defined (ACE_USES_WCHAR)
4832 void
4833 ACE_OS::unique_name (const void *object,
4834 wchar_t *name,
4835 size_t length)
4837 // The process ID will provide uniqueness between processes on the
4838 // same machine. The "this" pointer of the <object> will provide
4839 // uniqueness between other "live" objects in the same process. The
4840 // uniqueness of this name is therefore only valid for the life of
4841 // <object>.
4842 ACE_OS::snprintf (name, length, ACE_TEXT ("%p%d"), object,
4843 static_cast<int> (ACE_OS::getpid ()));
4845 #endif
4847 pid_t
4848 ACE_OS::thr_gettid ()
4850 #ifdef ACE_HAS_GETTID
4851 return syscall (SYS_gettid);
4852 #else
4853 ACE_NOTSUP_RETURN (-1);
4854 #endif
4857 ACE_END_VERSIONED_NAMESPACE_DECL
4859 #if defined (ACE_VXWORKS) && !defined (__RTP__)
4860 # include /**/ <usrLib.h> /* for ::sp() */
4861 # include /**/ <sysLib.h> /* for ::sysClkRateGet() */
4862 # include "ace/Service_Config.h"
4864 #if !defined (ACE_LACKS_VA_FUNCTIONS)
4866 // This global function can be used from the VxWorks shell to pass
4867 // arguments to a C main () function.
4869 // usage: -> spa main, "arg1", "arg2"
4871 // All arguments must be quoted, even numbers.
4873 spa (FUNCPTR entry, ...)
4875 // The called entrypoint can get the function name plus the normal 10
4876 // optional arguments.
4877 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 1 + 10;
4878 static char *argv[ACE_MAX_ARGS] = { 0 };
4879 va_list pvar;
4880 ACE_VX_USR_ARG_T argc;
4882 // Hardcode a program name because the real one isn't available
4883 // through the VxWorks shell.
4884 argv[0] = const_cast<char*> ("ace_main");
4886 // Peel off arguments to spa () and put into argv. va_arg () isn't
4887 // necessarily supposed to return 0 when done, though since the
4888 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4889 // the unused ones. This function could be used to increase that
4890 // limit, but then it couldn't depend on the trailing 0. So, the
4891 // number of arguments would have to be passed.
4892 va_start (pvar, entry);
4894 for (argc = 1; argc < ACE_MAX_ARGS; ++argc)
4896 argv[argc] = va_arg (pvar, char *);
4898 if (argv[argc] == 0)
4899 break;
4902 if (argc >= ACE_MAX_ARGS && argv[ACE_MAX_ARGS - 1] != 0)
4904 // Try to read another arg, and warn user if the limit was exceeded.
4906 // Note that the VxWorks shell arguments change from int to long when
4907 // using a 64bit compiler. Cast the argument up so that the format
4908 // specifier remains correct for either build type.
4909 if (va_arg (pvar, char *) != 0)
4910 ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %ld\n",
4911 (long)ACE_MAX_ARGS);
4913 else
4915 // fill unused argv slots with 0 to get rid of leftovers
4916 // from previous invocations
4917 for (ACE_VX_USR_ARG_T i = argc; i < ACE_MAX_ARGS; ++i)
4918 argv[i] = 0;
4921 // The hard-coded options are what ::sp () uses, except for the
4922 // larger stack size (instead of ::sp ()'s 20000).
4923 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
4924 100, // task priority
4925 VX_FP_TASK, // task options
4926 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
4927 entry, // entry point
4928 argc, // first argument to main ()
4929 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
4930 0, 0, 0, 0, 0, 0, 0, 0);
4931 va_end (pvar);
4933 // ::taskSpawn () returns the taskID on success: return 0 instead if
4934 // successful
4935 return ret > 0 ? 0 : -1;
4937 #endif /* !ACE_LACKS_VA_FUNCTIONS */
4939 // A helper function for the extended spa functions
4940 static void
4941 add_to_argv (ACE_VX_USR_ARG_T& argc, char** argv, int max_args, char* string)
4943 char indouble = 0;
4944 size_t previous = 0;
4945 size_t length = ACE_OS::strlen (string);
4947 if (length > 0)
4949 // We use <= to make sure that we get the last argument
4950 for (size_t i = 0; i <= length; i++)
4952 // Is it a double quote that hasn't been escaped?
4953 if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
4955 indouble ^= 1;
4956 if (indouble)
4958 // We have just entered a double quoted string, so
4959 // save the starting position of the contents.
4960 previous = i + 1;
4962 else
4964 // We have just left a double quoted string, so
4965 // zero out the ending double quote.
4966 string[i] = '\0';
4969 else if (string[i] == '\\') // Escape the next character
4971 // The next character is automatically skipped because
4972 // of the memmove().
4973 ACE_OS::memmove (string + i, string + i + 1, length);
4974 --length;
4976 else if (!indouble &&
4977 (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
4979 string[i] = '\0';
4980 if (argc < max_args)
4982 argv[argc] = string + previous;
4983 ++argc;
4985 else
4987 ACE_OS::fprintf (stderr, "spae(): number of arguments "
4988 "limited to %d\n", max_args);
4991 // Skip over whitespace in between arguments
4992 for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
4996 // Save the starting point for the next time around
4997 previous = i;
4999 // Make sure we don't skip over a character due
5000 // to the above loop to skip over whitespace
5001 --i;
5007 #if !defined (ACE_LACKS_VA_FUNCTIONS)
5009 // This global function can be used from the VxWorks shell to pass
5010 // arguments to a C main () function.
5012 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
5014 // All arguments must be within double quotes, even numbers.
5016 spae (FUNCPTR entry, ...)
5018 static int const WINDSH_ARGS = 10;
5019 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
5020 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
5021 va_list pvar;
5022 ACE_VX_USR_ARG_T argc = 1;
5024 // Peel off arguments to spa () and put into argv. va_arg () isn't
5025 // necessarily supposed to return 0 when done, though since the
5026 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5027 // the unused ones.
5028 va_start (pvar, entry);
5030 int i = 0;
5031 for (char* str = va_arg (pvar, char*);
5032 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
5034 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
5037 // fill unused argv slots with 0 to get rid of leftovers
5038 // from previous invocations
5039 for (i = argc; i < ACE_MAX_ARGS; ++i)
5040 argv[i] = 0;
5042 // The hard-coded options are what ::sp () uses, except for the
5043 // larger stack size (instead of ::sp ()'s 20000).
5044 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
5045 100, // task priority
5046 VX_FP_TASK, // task options
5047 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
5048 entry, // entry point
5049 argc, // first argument to main ()
5050 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
5051 0, 0, 0, 0, 0, 0, 0, 0);
5052 va_end (pvar);
5054 // ::taskSpawn () returns the taskID on success: return 0 instead if
5055 // successful
5056 return ret > 0 ? 0 : -1;
5059 // This global function can be used from the VxWorks shell to pass
5060 // arguments to a C main () function. The function will be run
5061 // within the shells task.
5063 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
5065 // All arguments must be within double quotes, even numbers.
5066 // Unlike the spae function, this fuction executes the supplied
5067 // routine in the foreground, rather than spawning it in a separate
5068 // task.
5070 spaef (FUNCPTR entry, ...)
5072 static int const WINDSH_ARGS = 10;
5073 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
5074 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
5075 va_list pvar;
5076 ACE_VX_USR_ARG_T argc = 1;
5078 // Peel off arguments to spa () and put into argv. va_arg () isn't
5079 // necessarily supposed to return 0 when done, though since the
5080 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5081 // the unused ones.
5082 va_start (pvar, entry);
5084 int i = 0;
5085 for (char* str = va_arg (pvar, char*);
5086 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
5088 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
5091 // fill unused argv slots with 0 to get rid of leftovers
5092 // from previous invocations
5093 for (i = argc; i < ACE_MAX_ARGS; ++i)
5094 argv[i] = 0;
5096 int ret = entry (argc, argv);
5098 va_end (pvar);
5100 // Return the return value of the invoked ace_main routine.
5101 return ret;
5103 #endif /* !ACE_LACKS_VA_FUNCTIONS */
5105 // This global function can be used from the VxWorks shell to pass
5106 // arguments to and run a main () function (i.e. ace_main).
5108 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
5110 // All arguments must be within double quotes, even numbers.
5111 // This routine spawns the main () function in a separate task and waits till the
5112 // task has finished.
5113 static int _vx_call_rc = 0;
5115 static int
5116 _vx_call_entry(FUNCPTR entry, int argc, char* argv[])
5118 ACE_Service_Config::current (ACE_Service_Config::global());
5119 _vx_call_rc = entry (argc, argv);
5120 return _vx_call_rc;
5124 vx_execae (FUNCPTR entry, char* arg, int prio, int opt, size_t stacksz, ...)
5126 static ACE_VX_USR_ARG_T const ACE_MAX_ARGS = 128;
5127 static char* argv[ACE_MAX_ARGS] = { const_cast<char*> ("ace_main"), 0 };
5128 ACE_VX_USR_ARG_T argc = 1;
5130 // Peel off arguments to run_main () and put into argv.
5131 if (arg)
5133 add_to_argv(argc, argv, ACE_MAX_ARGS, arg);
5136 // fill unused argv slots with 0 to get rid of leftovers
5137 // from previous invocations
5138 for (ACE_VX_USR_ARG_T i = argc; i < ACE_MAX_ARGS; ++i)
5139 argv[i] = 0;
5141 // The hard-coded options are what ::sp () uses, except for the
5142 // larger stack size (instead of ::sp ()'s 20000).
5143 ACE_VX_TASK_ID const ret = ::taskSpawn (argv[0], // task name
5144 prio==0 ? 100 : prio, // task priority
5145 opt==0 ? VX_FP_TASK : opt, // task options
5146 stacksz==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE : stacksz, // stack size
5147 (FUNCPTR)_vx_call_entry, // entrypoint caller
5148 (ACE_VX_USR_ARG_T)entry, // entry point
5149 argc, // first argument to main ()
5150 (ACE_VX_USR_ARG_T) argv, // second argument to main ()
5151 0, 0, 0, 0, 0, 0, 0);
5153 if (ret == ACE_VX_TASK_ID_ERROR)
5154 return 255;
5156 while( ret > 0 && ::taskIdVerify (ret) != ERROR )
5157 ::taskDelay (3 * ::sysClkRateGet ());
5159 // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
5160 // successful
5161 return ret > 0 ? _vx_call_rc : 255;
5164 #if defined(ACE_AS_STATIC_LIBS) && defined (ACE_VXWORKS_DEBUGGING_HELPER)
5165 /** Wind River workbench allows the user to spawn a kernel task as a
5166 "Debug Configuration". Use this function as the entrypoint so that
5167 the arguments are translated into the form that ace_main() requires.
5169 int ace_wb_exec (int arg0, int arg1, int arg2, int arg3, int arg4,
5170 int arg5, int arg6, int arg7, int arg8, int arg9)
5172 return spaef ((FUNCPTR) ace_main, arg0, arg1, arg2, arg3, arg4,
5173 arg5, arg6, arg7, arg8, arg9);
5175 #endif /* ACE_AS_STATIC_LIBS && ... */
5177 #endif /* ACE_VXWORKS && !__RTP__ */