[7297] Fixed profession spells sorting in trainer spell list at client.
[getmangos.git] / dep / ACE_wrappers / ace / OS_NS_Thread.cpp
blobe5c37092ad24066ddfe3f14338fd18fc3c18d189
1 #include "ace/OS_NS_Thread.h"
3 ACE_RCSID (ace,
4 OS_NS_Thread,
5 "$Id: OS_NS_Thread.cpp 81345 2008-04-13 07:28:11Z johnnyw $")
7 #if !defined (ACE_HAS_INLINED_OSCALLS)
8 # include "ace/OS_NS_Thread.inl"
9 #endif /* ACE_HAS_INLINED_OSCALLS */
11 #include "ace/OS_NS_stdio.h"
12 #include "ace/Sched_Params.h"
13 #include "ace/OS_Memory.h"
14 #include "ace/OS_Thread_Adapter.h"
15 #include "ace/Min_Max.h"
16 #include "ace/Object_Manager_Base.h"
17 #include "ace/OS_NS_errno.h"
18 #include "ace/OS_NS_ctype.h"
19 #include "ace/Log_Msg.h" // for ACE_ASSERT
20 // This is necessary to work around nasty problems with MVS C++.
21 #include "ace/Auto_Ptr.h"
22 #include "ace/Thread_Mutex.h"
23 #include "ace/Condition_T.h"
24 #include "ace/Guard_T.h"
26 extern "C" void
27 ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args)
29 ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::mutex_lock_cleanup (args);
33 #if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
34 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
35 (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID)
36 #elif defined (ACE_HAS_WINCE) && defined (UNDER_CE) && (UNDER_CE >= 211)
37 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
38 CreateThread (0, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & CREATE_SUSPENDED, (unsigned long *) THR_ID)
39 #elif defined(ACE_HAS_WTHREADS)
40 // Green Hills compiler gets confused when __stdcall is imbedded in
41 // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
42 // instead.
43 typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*);
44 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
45 ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
46 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
48 /*****************************************************************************/
50 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
52 void
53 ACE_Thread_ID::to_string (char *thr_string) const
55 char format[128]; // Converted format string
56 char *fp = 0; // Current format pointer
57 fp = format;
58 *fp++ = '%'; // Copy in the %
60 #if defined (ACE_WIN32)
61 ACE_OS::strcpy (fp, "u");
62 ACE_OS::sprintf (thr_string,
63 format,
64 static_cast <unsigned> (thread_id_));
65 #elif defined (DIGITAL_UNIX)
66 ACE_OS::strcpy (fp, "u");
67 ACE_OS::sprintf (thr_string, format,
68 # if defined (ACE_HAS_THREADS)
69 thread_id_
70 # else
71 thread_id_
72 # endif /* ACE_HAS_THREADS */
74 #else
76 # if defined (ACE_MVS) || defined (ACE_TANDEM_T1248_PTHREADS)
77 // MVS's pthread_t is a struct... yuck. So use the ACE 5.0
78 // code for it.
79 ACE_OS::strcpy (fp, "u");
80 ACE_OS::sprintf (thr_string, format, thread_handle_);
81 # else
82 // Yes, this is an ugly C-style cast, but the
83 // correct C++ cast is different depending on
84 // whether the t_id is an integral type or a pointer
85 // type. FreeBSD uses a pointer type, but doesn't
86 // have a _np function to get an integral type, like
87 // the OSes above.
88 ACE_OS::strcpy (fp, "lu");
89 ACE_OS::sprintf (thr_string,
90 format,
91 (unsigned long) thread_handle_);
92 # endif /* ACE_MVS || ACE_TANDEM_T1248_PTHREADS */
94 #endif /* ACE_WIN32 */
97 /*****************************************************************************/
99 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
101 #if defined (ACE_HAS_TSS_EMULATION)
102 u_int ACE_TSS_Emulation::total_keys_ = 0;
104 ACE_TSS_Keys* ACE_TSS_Emulation::tss_keys_used_ = 0;
106 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
107 ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]
108 = { 0 };
110 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
112 bool ACE_TSS_Emulation::key_created_ = false;
114 ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_;
116 /* static */
117 # if defined (ACE_HAS_THR_C_FUNC)
118 extern "C"
119 void
120 ACE_TSS_Emulation_cleanup (void *ptr)
122 ACE_UNUSED_ARG (ptr);
123 // Really this must be used for ACE_TSS_Emulation code to make the TSS
124 // cleanup
126 # else
127 void
128 ACE_TSS_Emulation_cleanup (void *ptr)
130 ACE_UNUSED_ARG (ptr);
131 // Really this must be used for ACE_TSS_Emulation code to make the TSS
132 // cleanup
134 # endif /* ACE_HAS_THR_C_FUNC */
136 void **
137 ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created)
139 // TSS Singleton implementation.
141 // Create the one native TSS key, if necessary.
142 if (!key_created_)
144 // Double-checked lock . . .
145 ACE_TSS_BASE_GUARD
147 if (!key_created_)
149 ACE_NO_HEAP_CHECK;
150 if (ACE_OS::thr_keycreate_native (&native_tss_key_,
151 &ACE_TSS_Emulation_cleanup) != 0)
153 ACE_ASSERT (0);
154 return 0; // Major problems, this should *never* happen!
156 key_created_ = true;
160 void **old_ts_storage = 0;
162 // Get the tss_storage from thread-OS specific storage.
163 if (ACE_OS::thr_getspecific_native (native_tss_key_,
164 (void **) &old_ts_storage) == -1)
166 ACE_ASSERT (false);
167 return 0; // This should not happen!
170 // Check to see if this is the first time in for this thread.
171 // This block can also be entered after a fork () in the child process.
172 if (old_ts_storage == 0)
174 if (ts_created)
175 *ts_created = 1u;
177 // Use the ts_storage passed as argument, if non-zero. It is
178 // possible that this has been implemented in the stack. At the
179 // moment, this is unknown. The cleanup must not do nothing.
180 // If ts_storage is zero, allocate (and eventually leak) the
181 // storage array.
182 if (ts_storage == 0)
184 ACE_NO_HEAP_CHECK;
186 ACE_NEW_RETURN (ts_storage,
187 void*[ACE_TSS_THREAD_KEYS_MAX],
190 // Zero the entire TSS array. Do it manually instead of
191 // using memset, for optimum speed. Though, memset may be
192 // faster :-)
193 void **tss_base_p = ts_storage;
195 for (u_int i = 0;
196 i < ACE_TSS_THREAD_KEYS_MAX;
197 ++i)
198 *tss_base_p++ = 0;
201 // Store the pointer in thread-specific storage. It gets
202 // deleted via the ACE_TSS_Emulation_cleanup function when the
203 // thread terminates.
204 if (ACE_OS::thr_setspecific_native (native_tss_key_,
205 (void *) ts_storage) != 0)
207 ACE_ASSERT (false);
208 return 0; // This should not happen!
211 else
212 if (ts_created)
213 ts_created = 0;
215 return ts_storage ? ts_storage : old_ts_storage;
217 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
219 u_int
220 ACE_TSS_Emulation::total_keys ()
222 ACE_OS_Recursive_Thread_Mutex_Guard (
223 *static_cast <ACE_recursive_thread_mutex_t *>
224 (ACE_OS_Object_Manager::preallocated_object[
225 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
227 return total_keys_;
231 ACE_TSS_Emulation::next_key (ACE_thread_key_t &key)
233 ACE_OS_Recursive_Thread_Mutex_Guard (
234 *static_cast <ACE_recursive_thread_mutex_t *>
235 (ACE_OS_Object_Manager::preallocated_object[
236 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
238 // Initialize the tss_keys_used_ pointer on first use.
239 if (tss_keys_used_ == 0)
241 ACE_NEW_RETURN (tss_keys_used_, ACE_TSS_Keys, -1);
244 if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX)
246 u_int counter = 0;
247 // Loop through all possible keys and check whether a key is free
248 for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++)
250 ACE_thread_key_t localkey;
251 # if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
252 ACE_OS::memset (&localkey, 0, sizeof (ACE_thread_key_t));
253 ACE_OS::memcpy (&localkey, &counter_, sizeof (u_int));
254 # else
255 localkey = counter;
256 # endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
257 // If the key is not set as used, we can give out this key, if not
258 // we have to search further
259 if (tss_keys_used_->is_set(localkey) == 0)
261 tss_keys_used_->test_and_set(localkey);
262 key = localkey;
263 break;
267 ++total_keys_;
268 return 0;
270 else
272 key = ACE_OS::NULL_key;
273 return -1;
278 ACE_TSS_Emulation::release_key (ACE_thread_key_t key)
280 ACE_OS_Recursive_Thread_Mutex_Guard (
281 *static_cast <ACE_recursive_thread_mutex_t *>
282 (ACE_OS_Object_Manager::preallocated_object[
283 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
285 if (tss_keys_used_ != 0 &&
286 tss_keys_used_->test_and_clear (key) == 0)
288 --total_keys_;
289 return 0;
291 return 1;
295 ACE_TSS_Emulation::is_key (ACE_thread_key_t key)
297 ACE_OS_Recursive_Thread_Mutex_Guard (
298 *static_cast <ACE_recursive_thread_mutex_t *>
299 (ACE_OS_Object_Manager::preallocated_object[
300 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
302 if (tss_keys_used_ != 0 &&
303 tss_keys_used_->is_set (key) == 1)
305 return 1;
307 return 0;
310 void *
311 ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX])
313 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
314 // On VxWorks, in particular, don't check to see if the field
315 // is 0. It isn't always, specifically, when a program is run
316 // directly by the shell (without spawning a new task) after
317 // another program has been run.
319 u_int ts_created = 0;
320 tss_base (ts_storage, &ts_created);
321 if (ts_created)
323 # else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
324 tss_base () = ts_storage;
325 # endif
327 // Zero the entire TSS array. Do it manually instead of using
328 // memset, for optimum speed. Though, memset may be faster :-)
329 void **tss_base_p = tss_base ();
330 for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
332 *tss_base_p = 0;
335 return tss_base ();
336 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
338 else
340 return 0;
342 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
345 void
346 ACE_TSS_Emulation::tss_close ()
348 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
349 ACE_OS::thr_keyfree_native (native_tss_key_);
350 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
353 #endif /* ACE_HAS_TSS_EMULATION */
355 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
357 /*****************************************************************************/
359 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
361 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
362 // the single file of template instantiations.
364 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id)
365 : tid_(id)
367 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
370 ACE_TSS_Ref::ACE_TSS_Ref (void)
372 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
375 // Check for equality.
376 bool
377 ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const
379 ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
381 return this->tid_ == info.tid_;
384 // Check for inequality.
385 ACE_SPECIAL_INLINE
386 bool
387 ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
389 ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
391 return !(*this == tss_ref);
394 // moved class ACE_TSS_Info declaration
395 // to OS.h so it can be visible to the
396 // single file of template instantiations
398 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
399 ACE_TSS_Info::Destructor dest)
400 : key_ (key),
401 destructor_ (dest),
402 thread_count_ (-1)
404 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
407 ACE_TSS_Info::ACE_TSS_Info (void)
408 : key_ (ACE_OS::NULL_key),
409 destructor_ (0),
410 thread_count_ (-1)
412 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
415 # if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
416 static inline bool operator== (const ACE_thread_key_t &lhs,
417 const ACE_thread_key_t &rhs)
419 return ! ACE_OS::memcmp (&lhs, &rhs, sizeof (ACE_thread_key_t));
422 static inline bool operator!= (const ACE_thread_key_t &lhs,
423 const ACE_thread_key_t &rhs)
425 return ! (lhs == rhs);
427 # endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
429 // Check for equality.
430 bool
431 ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const
433 ACE_OS_TRACE ("ACE_TSS_Info::operator==");
435 return this->key_ == info.key_;
438 // Check for inequality.
439 bool
440 ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const
442 ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
444 return !(*this == info);
447 void
448 ACE_TSS_Info::dump (void)
450 # if defined (ACE_HAS_DUMP)
451 // ACE_OS_TRACE ("ACE_TSS_Info::dump");
453 # if 0
454 ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
455 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %u\n"), this->key_));
456 ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("destructor_ = %u\n"), this->destructor_));
457 ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
458 # endif /* 0 */
459 # endif /* ACE_HAS_DUMP */
462 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
463 // to the single file of template instantiations.
465 ACE_TSS_Keys::ACE_TSS_Keys (void)
467 for (u_int i = 0; i < ACE_WORDS; ++i)
469 key_bit_words_[i] = 0;
473 ACE_SPECIAL_INLINE
474 void
475 ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit)
477 word = key / ACE_BITS_PER_WORD;
478 bit = key % ACE_BITS_PER_WORD;
482 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key)
484 ACE_KEY_INDEX (key_index, key);
485 u_int word, bit;
486 find (key_index, word, bit);
488 if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
490 return 1;
492 else
494 ACE_SET_BITS (key_bit_words_[word], 1 << bit);
495 return 0;
500 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key)
502 ACE_KEY_INDEX (key_index, key);
503 u_int word, bit;
504 find (key_index, word, bit);
506 if (word < ACE_WORDS && ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
508 ACE_CLR_BITS (key_bit_words_[word], 1 << bit);
509 return 0;
511 else
513 return 1;
518 ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
520 ACE_KEY_INDEX (key_index, key);
521 u_int word, bit;
522 find (key_index, word, bit);
524 return word < ACE_WORDS ? ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit) : 0;
528 * @class ACE_TSS_Cleanup
529 * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
531 class ACE_TSS_Cleanup
533 public:
534 /// Register a newly-allocated key
535 /// @param key the key to be monitored
536 /// @param destructor the function to call to delete objects stored via this key
537 int insert (ACE_thread_key_t key, void (*destructor)(void *));
539 /// Mark a key as being used by this thread.
540 void thread_use_key (ACE_thread_key_t key);
542 /// This thread is no longer using this key
543 /// call destructor if appropriate
544 int thread_detach_key (ACE_thread_key_t key);
546 /// This key is no longer used
547 /// Release key if use count == 0
548 /// fail if use_count != 0;
549 /// @param key the key to be released
550 int free_key (ACE_thread_key_t key);
552 /// Cleanup the thread-specific objects. Does _NOT_ exit the thread.
553 /// For each used key perform the same actions as free_key.
554 void thread_exit (void);
556 private:
557 void dump (void);
559 /// Release a key used by this thread
560 /// @param info reference to the info for this key
561 /// @param destructor out arg to receive destructor function ptr
562 /// @param tss_obj out arg to receive pointer to deletable object
563 void thread_release (
564 ACE_TSS_Info &info,
565 ACE_TSS_Info::Destructor & destructor,
566 void *& tss_obj);
568 /// remove key if it's unused (thread_count == 0)
569 /// @param info reference to the info for this key
570 int remove_key (ACE_TSS_Info &info);
572 /// Find the TSS keys (if any) for this thread.
573 /// @param thread_keys reference to pointer to be filled in by this function.
574 /// @return false if keys don't exist.
575 bool find_tss_keys (ACE_TSS_Keys *& thread_keys) const;
577 /// Accessor for this threads ACE_TSS_Keys instance.
578 /// Creates the keys if necessary.
579 ACE_TSS_Keys *tss_keys ();
581 /// Ensure singleton.
582 ACE_TSS_Cleanup (void);
583 ~ACE_TSS_Cleanup (void);
585 /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
586 friend class TSS_Cleanup_Instance;
588 private:
589 // Array of <ACE_TSS_Info> objects.
590 typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS];
591 typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR;
593 /// Table of <ACE_TSS_Info>'s.
594 ACE_TSS_TABLE table_;
596 /// Key for the thread-specific ACE_TSS_Keys
597 /// Used by find_tss_keys() or tss_keys() to find the
598 /// bit array that records whether each TSS key is in
599 /// use by this thread.
600 ACE_thread_key_t in_use_;
604 /*****************************************************************************/
606 * @class TSS_Cleanup_Instance
607 * @A class to manage an instance pointer to ACE_TSS_Cleanup.
608 * Note: that the double checked locking pattern doesn't allow
609 * safe deletion.
610 * Callers who wish to access the singleton ACE_TSS_Cleanup must
611 * do so by instantiating a TSS_Cleanup_Instance, calling the valid
612 * method to be sure the ACE_TSS_Cleanup is available, then using
613 * the TSS_Cleanup_Instance as a pointer to the instance.
614 * Construction argument to the TSS_Cleanup_Instance determines how
615 * it is to be used:
616 * CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
617 * USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
618 * DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
619 * delete it when the TSS_Cleanup_Instance goes out of scope.
622 class TSS_Cleanup_Instance
624 public:
625 enum Purpose
627 CREATE,
628 USE,
629 DESTROY
631 TSS_Cleanup_Instance (Purpose purpose = USE);
632 ~TSS_Cleanup_Instance();
634 bool valid();
635 ACE_TSS_Cleanup * operator ->();
637 private:
639 ACE_TSS_Cleanup * operator *();
641 private:
642 static unsigned int reference_count_;
643 static ACE_TSS_Cleanup * instance_;
644 static ACE_Thread_Mutex* mutex_;
645 static ACE_Thread_Condition<ACE_Thread_Mutex>* condition_;
647 private:
648 ACE_TSS_Cleanup * ptr_;
649 unsigned short flags_;
650 enum
652 FLAG_DELETING = 1,
653 FLAG_VALID_CHECKED = 2
657 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose)
658 : ptr_(0)
659 , flags_(0)
661 // During static construction or construction of the ACE_Object_Manager,
662 // there can be only one thread in this constructor at any one time, so
663 // it's safe to check for a zero mutex_. If it's zero, we create a new
664 // mutex and condition variable.
665 if (mutex_ == 0)
667 ACE_NEW (mutex_, ACE_Thread_Mutex ());
668 ACE_NEW (condition_, ACE_Thread_Condition<ACE_Thread_Mutex> (*mutex_));
671 ACE_Guard<ACE_Thread_Mutex> guard(*mutex_);
673 if (purpose == CREATE)
675 if (instance_ == 0)
677 instance_ = new ACE_TSS_Cleanup();
679 ptr_ = instance_;
680 ++reference_count_;
682 else if(purpose == DESTROY)
684 if (instance_ != 0)
686 ptr_ = instance_;
687 instance_ = 0;
688 ACE_SET_BITS(flags_, FLAG_DELETING);
689 while (reference_count_ > 0)
691 condition_->wait();
695 else // must be normal use
697 ACE_ASSERT(purpose == USE);
698 if (instance_ != 0)
700 ptr_ = instance_;
701 ++reference_count_;
706 TSS_Cleanup_Instance::~TSS_Cleanup_Instance (void)
708 // Variable to hold the mutex_ to delete outside the scope of the
709 // guard.
710 ACE_Thread_Mutex *del_mutex = 0;
712 // scope the guard
714 ACE_Guard<ACE_Thread_Mutex> guard (*mutex_);
715 if (ptr_ != 0)
717 if (ACE_BIT_ENABLED (flags_, FLAG_DELETING))
719 ACE_ASSERT(instance_ == 0);
720 ACE_ASSERT(reference_count_ == 0);
721 delete ptr_;
722 del_mutex = mutex_ ;
723 mutex_ = 0;
725 else
727 ACE_ASSERT (reference_count_ > 0);
728 --reference_count_;
729 if (reference_count_ == 0 && instance_ == 0)
730 condition_->signal ();
733 }// end of guard scope
735 if (del_mutex != 0)
737 delete condition_;
738 condition_ = 0;
739 delete del_mutex;
743 bool
744 TSS_Cleanup_Instance::valid()
746 ACE_SET_BITS(flags_, FLAG_VALID_CHECKED);
747 return (this->instance_ != 0);
750 ACE_TSS_Cleanup *
751 TSS_Cleanup_Instance::operator *()
753 ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
754 return instance_;
757 ACE_TSS_Cleanup *
758 TSS_Cleanup_Instance::operator ->()
760 ACE_ASSERT(ACE_BIT_ENABLED(flags_, FLAG_VALID_CHECKED));
761 return instance_;
764 // = Static object initialization.
765 unsigned int TSS_Cleanup_Instance::reference_count_ = 0;
766 ACE_TSS_Cleanup * TSS_Cleanup_Instance::instance_ = 0;
767 ACE_Thread_Mutex* TSS_Cleanup_Instance::mutex_ = 0;
768 ACE_Thread_Condition<ACE_Thread_Mutex>* TSS_Cleanup_Instance::condition_ = 0;
770 ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void)
774 void
775 ACE_TSS_Cleanup::thread_exit (void)
777 ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
778 // variables to hold the destructors, keys
779 // and pointers to the object to be destructed
780 // the actual destruction is deferred until the guard is released
781 ACE_TSS_Info::Destructor destructor[ACE_DEFAULT_THREAD_KEYS];
782 void * tss_obj[ACE_DEFAULT_THREAD_KEYS];
783 ACE_thread_key_t keys[ACE_DEFAULT_THREAD_KEYS];
784 // count of items to be destroyed
785 unsigned int d_count = 0;
787 // scope the guard
789 ACE_TSS_CLEANUP_GUARD
791 // if not initialized or already cleaned up
792 ACE_TSS_Keys *this_thread_keys = 0;
793 if (! find_tss_keys (this_thread_keys) )
795 return;
798 // Minor hack: Iterating in reverse order means the LOG buffer which is
799 // accidentally allocated first will be accidentally deallocated (almost)
800 // last -- in case someone logs something from the other destructors.
801 // applications should not count on this behavior because platforms which
802 // do not use ACE_TSS_Cleanup may delete objects in other orders.
803 unsigned int key_index = ACE_DEFAULT_THREAD_KEYS;
804 while( key_index > 0)
806 --key_index;
807 ACE_TSS_Info & info = this->table_[key_index];
808 // if this key is in use by this thread
809 if (info.key_in_use () && this_thread_keys->is_set(info.key_))
811 // defer deleting the in-use key until all others have been deleted
812 if(info.key_ != this->in_use_)
814 destructor[d_count] = 0;
815 tss_obj[d_count] = 0;
816 keys[d_count] = 0;
817 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
818 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
820 keys[d_count] = info.key_;
821 ++d_count;
827 // remove the in_use bit vector last
828 ACE_KEY_INDEX (use_index, this->in_use_);
829 ACE_TSS_Info & info = this->table_[use_index];
830 destructor[d_count] = 0;
831 tss_obj[d_count] = 0;
832 keys[d_count] = 0;
833 this->thread_release (info, destructor[d_count], tss_obj[d_count]);
834 if (destructor[d_count] != 0 && tss_obj[d_count] != 0)
836 keys[d_count] = info.key_;
837 ++d_count;
839 } // end of guard scope
840 for (unsigned int d_index = 0; d_index < d_count; ++d_index)
842 (*destructor[d_index])(tss_obj[d_index]);
843 #if defined (ACE_HAS_TSS_EMULATION)
844 ACE_TSS_Emulation::ts_object (keys[d_index]) = 0;
845 #else // defined (ACE_HAS_TSS_EMULATION)
846 ACE_OS::thr_setspecific_native (keys[d_index], 0);
847 #endif // defined (ACE_HAS_TSS_EMULATION)
851 extern "C" void
852 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
854 delete static_cast <ACE_TSS_Keys *> (tss_keys);
857 ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
858 : in_use_ (ACE_OS::NULL_key)
860 ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
864 ACE_TSS_Cleanup::insert (ACE_thread_key_t key,
865 void (*destructor)(void *))
867 ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
868 ACE_TSS_CLEANUP_GUARD
870 ACE_KEY_INDEX (key_index, key);
871 ACE_ASSERT (key_index < ACE_DEFAULT_THREAD_KEYS);
872 if (key_index < ACE_DEFAULT_THREAD_KEYS)
874 ACE_ASSERT (table_[key_index].thread_count_ == -1);
875 table_[key_index] = ACE_TSS_Info (key, destructor);
876 table_[key_index].thread_count_ = 0; // inserting it does not use it
877 // but it does "allocate" it
878 return 0;
880 else
882 return -1;
887 ACE_TSS_Cleanup::free_key (ACE_thread_key_t key)
889 ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
890 ACE_TSS_CLEANUP_GUARD
891 ACE_KEY_INDEX (key_index, key);
892 if (key_index < ACE_DEFAULT_THREAD_KEYS)
894 return remove_key (this->table_ [key_index]);
896 return -1;
900 ACE_TSS_Cleanup::remove_key (ACE_TSS_Info &info)
902 // assume CLEANUP_GUARD is held by caller
903 ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
905 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
906 // When this is done, any existing TSS objects controlled by this key are leaked
907 // There is no "right thing" to do in this case
909 // only remove it if all threads are done with it
910 if (info.thread_count_ != 0)
912 return -1;
914 #endif // 0
916 #if !defined (ACE_HAS_TSS_EMULATION)
917 ACE_OS_thread_key_t temp_key = info.key_;
918 ACE_OS::thr_keyfree_native (temp_key);
919 #endif /* !ACE_HAS_TSS_EMULATION */
920 if (info.key_ == this->in_use_)
922 this->in_use_ = ACE_OS::NULL_key;
924 info.key_in_use (0);
925 info.destructor_ = 0;
926 return 0;
930 ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key)
932 // variables to hold the destructor and the object to be destructed
933 // the actual call is deferred until the guard is released
934 ACE_TSS_Info::Destructor destructor = 0;
935 void * tss_obj = 0;
937 // scope the guard
939 ACE_TSS_CLEANUP_GUARD
941 ACE_KEY_INDEX (key_index, key);
942 ACE_ASSERT (key_index < sizeof(this->table_)/sizeof(this->table_[0])
943 && this->table_[key_index].key_ == key);
944 ACE_TSS_Info &info = this->table_ [key_index];
946 // sanity check
947 if (!info.key_in_use ())
949 return -1;
952 this->thread_release (info, destructor, tss_obj);
953 } // end of scope for the Guard
954 // if there's a destructor and an object to be destroyed
955 if (destructor != 0 && tss_obj != 0)
957 (*destructor) (tss_obj);
959 return 0;
962 void
963 ACE_TSS_Cleanup::thread_release (
964 ACE_TSS_Info &info,
965 ACE_TSS_Info::Destructor & destructor,
966 void *& tss_obj)
968 // assume guard is held by caller
969 // Find the TSS keys (if any) for this thread
970 // do not create them if they don't exist
971 ACE_TSS_Keys * thread_keys = 0;
972 if (find_tss_keys (thread_keys))
974 // if this key is in use by this thread
975 if (thread_keys->test_and_clear(info.key_) == 0)
977 // save destructor & pointer to tss object
978 // until after the guard is released
979 destructor = info.destructor_;
980 ACE_OS::thr_getspecific (info.key_, &tss_obj);
981 ACE_ASSERT (info.thread_count_ > 0);
982 --info.thread_count_;
987 void
988 ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key)
990 // If the key's ACE_TSS_Info in-use bit for this thread is not set,
991 // set it and increment the key's thread_count_.
992 if (! tss_keys ()->test_and_set (key))
994 ACE_TSS_CLEANUP_GUARD
996 // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
997 ACE_KEY_INDEX (key_index, key);
998 ACE_TSS_Info &key_info = this->table_ [key_index];
1000 ACE_ASSERT (key_info.key_in_use ());
1001 ++key_info.thread_count_;
1005 void
1006 ACE_TSS_Cleanup::dump (void)
1008 # if defined (ACE_HAS_DUMP)
1009 // Iterate through all the thread-specific items and dump them all.
1011 ACE_TSS_TABLE_ITERATOR key_info = table_;
1012 for (unsigned int i = 0;
1013 i < ACE_DEFAULT_THREAD_KEYS;
1014 ++key_info, ++i)
1015 key_info->dump ();
1016 # endif /* ACE_HAS_DUMP */
1019 bool
1020 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys *& tss_keys) const
1022 if (this->in_use_ == ACE_OS::NULL_key)
1023 return false;
1024 if (ACE_OS::thr_getspecific (in_use_,
1025 reinterpret_cast<void **> (&tss_keys)) == -1)
1027 ACE_ASSERT (false);
1028 return false; // This should not happen!
1030 return tss_keys != 0;
1033 ACE_TSS_Keys *
1034 ACE_TSS_Cleanup::tss_keys ()
1036 if (this->in_use_ == ACE_OS::NULL_key)
1038 ACE_TSS_CLEANUP_GUARD
1039 // Double-check;
1040 if (in_use_ == ACE_OS::NULL_key)
1042 // Initialize in_use_ with a new key.
1043 if (ACE_OS::thr_keycreate (&in_use_,
1044 &ACE_TSS_Cleanup_keys_destroyer))
1046 ACE_ASSERT (false);
1047 return 0; // Major problems, this should *never* happen!
1052 void *ts_keys = 0;
1053 if (ACE_OS::thr_getspecific (in_use_, &ts_keys) == -1)
1055 ACE_ASSERT (false);
1056 return 0; // This should not happen!
1059 if (ts_keys == 0)
1061 ACE_NEW_RETURN (ts_keys,
1062 ACE_TSS_Keys,
1064 // Store the dynamically allocated pointer in thread-specific
1065 // storage.
1066 if (ACE_OS::thr_setspecific (in_use_, ts_keys) == -1)
1068 ACE_ASSERT (false);
1069 delete reinterpret_cast <ACE_TSS_Keys*> (ts_keys);
1070 return 0; // Major problems, this should *never* happen!
1074 return reinterpret_cast <ACE_TSS_Keys*>(ts_keys);
1077 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
1079 /*****************************************************************************/
1081 // = Static initialization.
1083 // This is necessary to deal with POSIX pthreads insanity. This
1084 // guarantees that we've got a "zero'd" thread id even when
1085 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
1086 // as structures... Under no circumstances should these be given
1087 // initial values.
1088 // Note: these three objects require static construction.
1089 ACE_thread_t ACE_OS::NULL_thread;
1090 ACE_hthread_t ACE_OS::NULL_hthread;
1091 #if defined (ACE_HAS_TSS_EMULATION)
1092 ACE_thread_key_t ACE_OS::NULL_key = static_cast <ACE_thread_key_t> (-1);
1093 #else /* ! ACE_HAS_TSS_EMULATION */
1094 ACE_thread_key_t ACE_OS::NULL_key;
1095 #endif /* ! ACE_HAS_TSS_EMULATION */
1097 /*****************************************************************************/
1099 void
1100 ACE_OS::cleanup_tss (const u_int main_thread)
1102 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
1103 { // scope the cleanup instance
1104 // Call TSS destructors for current thread.
1105 TSS_Cleanup_Instance cleanup;
1106 if (cleanup.valid ())
1108 cleanup->thread_exit ();
1111 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
1113 if (main_thread)
1115 #if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS)
1116 // Just close the ACE_Log_Msg for the current (which should be
1117 // main) thread. We don't have TSS emulation; if there's native
1118 // TSS, it should call its destructors when the main thread
1119 // exits.
1120 ACE_Base_Thread_Adapter::close_log_msg ();
1121 #endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
1123 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
1124 // Finally, free up the ACE_TSS_Cleanup instance. This method gets
1125 // called by the ACE_Object_Manager.
1126 TSS_Cleanup_Instance cleanup(TSS_Cleanup_Instance::DESTROY);
1127 if (cleanup.valid ())
1129 ; // the pointer deletes the Cleanup when it goes out of scope
1132 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
1134 #if defined (ACE_HAS_TSS_EMULATION)
1135 ACE_TSS_Emulation::tss_close ();
1136 #endif /* ACE_HAS_TSS_EMULATION */
1140 /*****************************************************************************/
1141 // CONDITIONS BEGIN
1142 /*****************************************************************************/
1144 #if defined (ACE_LACKS_COND_T)
1145 // NOTE: The ACE_OS::cond_* functions for some non-Unix platforms are
1146 // defined here either because they're too big to be inlined, or
1147 // to avoid use before definition if they were inline.
1149 // @@ The following functions could be inlined if i could figure where
1150 // to put it among the #ifdefs!
1152 ACE_OS::condattr_init (ACE_condattr_t &attributes, int type)
1154 attributes.type = type;
1155 return 0;
1159 ACE_OS::condattr_destroy (ACE_condattr_t &)
1161 return 0;
1165 ACE_OS::cond_broadcast (ACE_cond_t *cv)
1167 ACE_OS_TRACE ("ACE_OS::cond_broadcast");
1168 # if defined (ACE_HAS_THREADS)
1169 // The <external_mutex> must be locked before this call is made.
1171 // This is needed to ensure that <waiters_> and <was_broadcast_> are
1172 // consistent relative to each other.
1173 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1174 int have_waiters = 0;
1176 if (cv->waiters_ > 0)
1178 // We are broadcasting, even if there is just one waiter...
1179 // Record the fact that we are broadcasting. This helps the
1180 // cond_wait() method know how to optimize itself. Be sure to
1181 // set this with the <waiters_lock_> held.
1182 cv->was_broadcast_ = 1;
1183 have_waiters = 1;
1185 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1186 int result = 0;
1187 if (have_waiters)
1189 // Wake up all the waiters.
1190 if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1)
1191 result = -1;
1192 // Wait for all the awakened threads to acquire their part of
1193 // the counting semaphore.
1194 # if defined (ACE_VXWORKS)
1195 else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1)
1196 # else
1197 else if (ACE_OS::event_wait (&cv->waiters_done_) == -1)
1198 # endif /* ACE_VXWORKS */
1199 result = -1;
1200 // This is okay, even without the <waiters_lock_> held because
1201 // no other waiter threads can wake up to access it.
1202 cv->was_broadcast_ = 0;
1204 return result;
1205 # else
1206 ACE_UNUSED_ARG (cv);
1207 ACE_NOTSUP_RETURN (-1);
1208 # endif /* ACE_HAS_THREADS */
1212 ACE_OS::cond_destroy (ACE_cond_t *cv)
1214 ACE_OS_TRACE ("ACE_OS::cond_destroy");
1215 # if defined (ACE_HAS_THREADS)
1216 # if defined (ACE_HAS_WTHREADS)
1217 ACE_OS::event_destroy (&cv->waiters_done_);
1218 # elif defined (ACE_VXWORKS)
1219 ACE_OS::sema_destroy (&cv->waiters_done_);
1220 # endif /* ACE_VXWORKS */
1221 ACE_OS::thread_mutex_destroy (&cv->waiters_lock_);
1222 return ACE_OS::sema_destroy (&cv->sema_);
1223 # else
1224 ACE_UNUSED_ARG (cv);
1225 ACE_NOTSUP_RETURN (-1);
1226 # endif /* ACE_HAS_THREADS */
1230 ACE_OS::cond_init (ACE_cond_t *cv,
1231 ACE_condattr_t &attributes,
1232 const char *name, void *arg)
1234 return
1235 ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
1238 # if defined (ACE_HAS_WCHAR)
1240 ACE_OS::cond_init (ACE_cond_t *cv,
1241 ACE_condattr_t &attributes,
1242 const wchar_t *name, void *arg)
1244 return
1245 ACE_OS::cond_init (cv, static_cast<short> (attributes.type), name, arg);
1247 # endif /* ACE_HAS_WCHAR */
1250 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *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)
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 */
1278 # if defined (ACE_HAS_WCHAR)
1280 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
1282 ACE_OS_TRACE ("ACE_OS::cond_init");
1283 # if defined (ACE_HAS_THREADS)
1284 cv->waiters_ = 0;
1285 cv->was_broadcast_ = 0;
1287 int result = 0;
1288 if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
1289 result = -1;
1290 else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
1291 result = -1;
1292 # if defined (ACE_VXWORKS)
1293 else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
1294 # else
1295 else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
1296 # endif /* ACE_VXWORKS */
1297 result = -1;
1298 return result;
1299 # else
1300 ACE_UNUSED_ARG (cv);
1301 ACE_UNUSED_ARG (type);
1302 ACE_UNUSED_ARG (name);
1303 ACE_UNUSED_ARG (arg);
1304 ACE_NOTSUP_RETURN (-1);
1305 # endif /* ACE_HAS_THREADS */
1307 # endif /* ACE_HAS_WCHAR */
1310 ACE_OS::cond_signal (ACE_cond_t *cv)
1312 ACE_OS_TRACE ("ACE_OS::cond_signal");
1313 # if defined (ACE_HAS_THREADS)
1314 // If there aren't any waiters, then this is a no-op. Note that
1315 // this function *must* be called with the <external_mutex> held
1316 // since other wise there is a race condition that can lead to the
1317 // lost wakeup bug... This is needed to ensure that the <waiters_>
1318 // value is not in an inconsistent internal state while being
1319 // updated by another thread.
1320 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1321 int have_waiters = cv->waiters_ > 0;
1322 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1324 if (have_waiters != 0)
1325 return ACE_OS::sema_post (&cv->sema_);
1326 else
1327 return 0; // No-op
1328 # else
1329 ACE_UNUSED_ARG (cv);
1330 ACE_NOTSUP_RETURN (-1);
1331 # endif /* ACE_HAS_THREADS */
1335 ACE_OS::cond_wait (ACE_cond_t *cv,
1336 ACE_mutex_t *external_mutex)
1338 ACE_OS_TRACE ("ACE_OS::cond_wait");
1339 # if defined (ACE_HAS_THREADS)
1340 // Prevent race conditions on the <waiters_> count.
1341 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1342 ++cv->waiters_;
1343 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1345 int result = 0;
1347 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1348 if (external_mutex->type_ == USYNC_PROCESS)
1349 // This call will automatically release the mutex and wait on the semaphore.
1350 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_,
1351 cv->sema_, INFINITE, FALSE),
1352 result),
1353 int, -1, result);
1354 else
1355 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1357 // We keep the lock held just long enough to increment the count of
1358 // waiters by one. Note that we can't keep it held across the call
1359 // to ACE_OS::sema_wait() since that will deadlock other calls to
1360 // ACE_OS::cond_signal().
1361 if (ACE_OS::mutex_unlock (external_mutex) != 0)
1362 return -1;
1364 // Wait to be awakened by a ACE_OS::cond_signal() or
1365 // ACE_OS::cond_broadcast().
1366 result = ACE_OS::sema_wait (&cv->sema_);
1369 // Reacquire lock to avoid race conditions on the <waiters_> count.
1370 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1372 // We're ready to return, so there's one less waiter.
1373 --cv->waiters_;
1375 int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1377 // Release the lock so that other collaborating threads can make
1378 // progress.
1379 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1381 if (result == -1)
1382 // Bad things happened, so let's just return below.
1383 /* NOOP */;
1384 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1385 else if (external_mutex->type_ == USYNC_PROCESS)
1387 if (last_waiter)
1389 // This call atomically signals the <waiters_done_> event and
1390 // waits until it can acquire the mutex. This is important to
1391 // prevent unfairness.
1392 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
1393 external_mutex->proc_mutex_,
1394 INFINITE, FALSE),
1395 result),
1396 int, -1, result);
1397 else
1398 // We must always regain the <external_mutex>, even when
1399 // errors occur because that's the guarantee that we give to
1400 // our callers.
1401 ACE_OS::mutex_lock (external_mutex);
1403 return result;
1404 /* NOTREACHED */
1406 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1407 // If we're the last waiter thread during this particular broadcast
1408 // then let all the other threads proceed.
1409 else if (last_waiter)
1410 # if defined (ACE_VXWORKS)
1411 ACE_OS::sema_post (&cv->waiters_done_);
1412 # else
1413 ACE_OS::event_signal (&cv->waiters_done_);
1414 # endif /* ACE_VXWORKS */
1416 // We must always regain the <external_mutex>, even when errors
1417 // occur because that's the guarantee that we give to our callers.
1418 ACE_OS::mutex_lock (external_mutex);
1420 return result;
1421 # else
1422 ACE_UNUSED_ARG (cv);
1423 ACE_UNUSED_ARG (external_mutex);
1424 ACE_NOTSUP_RETURN (-1);
1425 # endif /* ACE_HAS_THREADS */
1429 ACE_OS::cond_timedwait (ACE_cond_t *cv,
1430 ACE_mutex_t *external_mutex,
1431 ACE_Time_Value *timeout)
1433 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1434 # if defined (ACE_HAS_THREADS)
1435 // Handle the easy case first.
1436 if (timeout == 0)
1437 return ACE_OS::cond_wait (cv, external_mutex);
1438 # if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS)
1440 // Prevent race conditions on the <waiters_> count.
1441 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1442 cv->waiters_++;
1443 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1445 int result = 0;
1446 ACE_Errno_Guard error (errno, 0);
1447 int msec_timeout;
1449 if (timeout->sec () == 0 && timeout->usec () == 0)
1450 msec_timeout = 0; // Do a "poll."
1451 else
1453 // Note that we must convert between absolute time (which is
1454 // passed as a parameter) and relative time (which is what
1455 // WaitForSingleObjects() expects).
1456 ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
1458 // Watchout for situations where a context switch has caused the
1459 // current time to be > the timeout.
1460 if (relative_time < ACE_Time_Value::zero)
1461 msec_timeout = 0;
1462 else
1463 msec_timeout = relative_time.msec ();
1466 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1467 if (external_mutex->type_ == USYNC_PROCESS)
1468 // This call will automatically release the mutex and wait on the
1469 // semaphore.
1470 result = ::SignalObjectAndWait (external_mutex->proc_mutex_,
1471 cv->sema_,
1472 msec_timeout,
1473 FALSE);
1474 else
1475 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1477 // We keep the lock held just long enough to increment the count
1478 // of waiters by one. Note that we can't keep it held across
1479 // the call to WaitForSingleObject since that will deadlock
1480 // other calls to ACE_OS::cond_signal().
1481 if (ACE_OS::mutex_unlock (external_mutex) != 0)
1482 return -1;
1484 // Wait to be awakened by a ACE_OS::signal() or
1485 // ACE_OS::broadcast().
1486 # if defined (ACE_WIN32)
1487 # if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1488 result = ::WaitForSingleObject (cv->sema_, msec_timeout);
1489 # else /* ACE_USES_WINCE_SEMA_SIMULATION */
1490 // Can't use Win32 API on our simulated semaphores.
1491 result = ACE_OS::sema_wait (&cv->sema_,
1492 timeout);
1493 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1494 # elif defined (ACE_VXWORKS)
1495 // Inline the call to ACE_OS::sema_wait () because it takes an
1496 // ACE_Time_Value argument. Avoid the cost of that conversion . . .
1497 int const ticks_per_sec = ::sysClkRateGet ();
1498 int const ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS;
1499 result = ::semTake (cv->sema_.sema_, ticks);
1500 # endif /* ACE_WIN32 || VXWORKS */
1503 // Reacquire lock to avoid race conditions.
1504 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1505 cv->waiters_--;
1507 int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1509 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1511 # if defined (ACE_WIN32)
1512 if (result != WAIT_OBJECT_0)
1514 switch (result)
1516 case WAIT_TIMEOUT:
1517 error = ETIME;
1518 break;
1519 default:
1520 error = ::GetLastError ();
1521 break;
1523 result = -1;
1525 # elif defined (ACE_VXWORKS)
1526 if (result == ERROR)
1528 switch (errno)
1530 case S_objLib_OBJ_TIMEOUT:
1531 error = ETIME;
1532 break;
1533 case S_objLib_OBJ_UNAVAILABLE:
1534 if (msec_timeout == 0)
1535 error = ETIME;
1536 break;
1537 default:
1538 error = errno;
1539 break;
1541 result = -1;
1543 # endif /* ACE_WIN32 || VXWORKS */
1544 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1545 if (external_mutex->type_ == USYNC_PROCESS)
1547 if (last_waiter)
1548 // This call atomically signals the <waiters_done_> event and
1549 // waits until it can acquire the mutex. This is important to
1550 // prevent unfairness.
1551 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
1552 external_mutex->proc_mutex_,
1553 INFINITE, FALSE),
1554 result),
1555 int, -1, result);
1556 else
1557 // We must always regain the <external_Mutex>, even when
1558 // errors occur because that's the guarantee that we give to
1559 // our callers.
1560 ACE_OS::mutex_lock (external_mutex);
1562 return result;
1563 /* NOTREACHED */
1565 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1566 // Note that this *must* be an "if" statement rather than an "else
1567 // if" statement since the caller may have timed out and hence the
1568 // result would have been -1 above.
1569 if (last_waiter)
1570 // Release the signaler/broadcaster if we're the last waiter.
1571 # if defined (ACE_WIN32)
1572 ACE_OS::event_signal (&cv->waiters_done_);
1573 # else
1574 ACE_OS::sema_post (&cv->waiters_done_);
1575 # endif /* ACE_WIN32 */
1577 // We must always regain the <external_mutex>, even when errors
1578 // occur because that's the guarantee that we give to our callers.
1579 ACE_OS::mutex_lock (external_mutex);
1581 return result;
1582 # endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
1583 # else
1584 ACE_UNUSED_ARG (cv);
1585 ACE_UNUSED_ARG (external_mutex);
1586 ACE_UNUSED_ARG (timeout);
1587 ACE_NOTSUP_RETURN (-1);
1588 # endif /* ACE_HAS_THREADS */
1591 # if defined (ACE_HAS_WTHREADS)
1593 ACE_OS::cond_timedwait (ACE_cond_t *cv,
1594 ACE_thread_mutex_t *external_mutex,
1595 ACE_Time_Value *timeout)
1597 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1598 # if defined (ACE_HAS_THREADS)
1599 // Handle the easy case first.
1600 if (timeout == 0)
1601 return ACE_OS::cond_wait (cv, external_mutex);
1603 // Prevent race conditions on the <waiters_> count.
1604 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1605 cv->waiters_++;
1606 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1608 int result = 0;
1609 int error = 0;
1610 int msec_timeout;
1612 if (timeout->sec () == 0 && timeout->usec () == 0)
1613 msec_timeout = 0; // Do a "poll."
1614 else
1616 // Note that we must convert between absolute time (which is
1617 // passed as a parameter) and relative time (which is what
1618 // WaitForSingleObjects() expects).
1619 ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
1621 // Watchout for situations where a context switch has caused the
1622 // current time to be > the timeout.
1623 if (relative_time < ACE_Time_Value::zero)
1624 msec_timeout = 0;
1625 else
1626 msec_timeout = relative_time.msec ();
1629 // We keep the lock held just long enough to increment the count of
1630 // waiters by one. Note that we can't keep it held across the call
1631 // to WaitForSingleObject since that will deadlock other calls to
1632 // ACE_OS::cond_signal().
1633 if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
1634 return -1;
1636 // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
1637 # if defined (ACE_USES_WINCE_SEMA_SIMULATION)
1638 // Can't use Win32 API on simulated semaphores.
1639 result = ACE_OS::sema_wait (&cv->sema_,
1640 timeout);
1642 if (result == -1 && errno == ETIME)
1643 result = WAIT_TIMEOUT;
1644 # else
1645 result = ::WaitForSingleObject (cv->sema_, msec_timeout);
1646 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1648 // Reacquire lock to avoid race conditions.
1649 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1651 cv->waiters_--;
1653 int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1655 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1657 if (result != WAIT_OBJECT_0)
1659 switch (result)
1661 case WAIT_TIMEOUT:
1662 error = ETIME;
1663 break;
1664 default:
1665 error = ::GetLastError ();
1666 break;
1668 result = -1;
1671 if (last_waiter)
1672 // Release the signaler/broadcaster if we're the last waiter.
1673 ACE_OS::event_signal (&cv->waiters_done_);
1675 // We must always regain the <external_mutex>, even when errors
1676 // occur because that's the guarantee that we give to our callers.
1677 ACE_OS::thread_mutex_lock (external_mutex);
1678 errno = error;
1679 return result;
1680 # else
1681 ACE_NOTSUP_RETURN (-1);
1682 # endif /* ACE_HAS_THREADS */
1686 ACE_OS::cond_wait (ACE_cond_t *cv,
1687 ACE_thread_mutex_t *external_mutex)
1689 ACE_OS_TRACE ("ACE_OS::cond_wait");
1690 # if defined (ACE_HAS_THREADS)
1691 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1692 cv->waiters_++;
1693 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1695 int result = 0;
1696 int error = 0;
1698 // We keep the lock held just long enough to increment the count of
1699 // waiters by one. Note that we can't keep it held across the call
1700 // to ACE_OS::sema_wait() since that will deadlock other calls to
1701 // ACE_OS::cond_signal().
1702 if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
1703 return -1;
1705 // Wait to be awakened by a ACE_OS::cond_signal() or
1706 // ACE_OS::cond_broadcast().
1707 # if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1708 result = ::WaitForSingleObject (cv->sema_, INFINITE);
1709 # else
1710 // Can't use Win32 API on simulated semaphores.
1711 result = ACE_OS::sema_wait (&cv->sema_);
1713 if (result != WAIT_OBJECT_0 && errno == ETIME)
1714 result = WAIT_TIMEOUT;
1716 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1718 // Reacquire lock to avoid race conditions.
1719 ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
1721 cv->waiters_--;
1723 int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
1725 ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
1727 if (result != WAIT_OBJECT_0)
1729 switch (result)
1731 case WAIT_TIMEOUT:
1732 error = ETIME;
1733 break;
1734 default:
1735 error = ::GetLastError ();
1736 break;
1739 else if (last_waiter)
1740 // Release the signaler/broadcaster if we're the last waiter.
1741 ACE_OS::event_signal (&cv->waiters_done_);
1743 // We must always regain the <external_mutex>, even when errors
1744 // occur because that's the guarantee that we give to our callers.
1745 ACE_OS::thread_mutex_lock (external_mutex);
1747 // Reset errno in case mutex_lock() also fails...
1748 errno = error;
1749 return result;
1750 # else
1751 ACE_NOTSUP_RETURN (-1);
1752 # endif /* ACE_HAS_THREADS */
1754 # endif /* ACE_HAS_WTHREADS */
1755 #else
1757 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
1759 ACE_condattr_t attributes;
1760 if (ACE_OS::condattr_init (attributes, type) == 0
1761 && ACE_OS::cond_init (cv, attributes, name, arg) == 0)
1763 (void) ACE_OS::condattr_destroy (attributes);
1764 return 0;
1766 return -1;
1768 #endif /* ACE_LACKS_COND_T */
1770 /*****************************************************************************/
1771 // CONDITIONS END
1772 /*****************************************************************************/
1774 /*****************************************************************************/
1775 // MUTEXES BEGIN
1776 /*****************************************************************************/
1779 ACE_OS::mutex_init (ACE_mutex_t *m,
1780 int lock_scope,
1781 const char *name,
1782 ACE_mutexattr_t *attributes,
1783 LPSECURITY_ATTRIBUTES sa,
1784 int lock_type)
1786 // ACE_OS_TRACE ("ACE_OS::mutex_init");
1787 #if defined (ACE_HAS_THREADS)
1788 # if defined (ACE_HAS_PTHREADS)
1789 ACE_UNUSED_ARG (name);
1790 ACE_UNUSED_ARG (sa);
1792 # if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
1793 /* Tests show that VxWorks 6.x pthread lib does not only
1794 * require zeroing of mutex/condition objects to function correctly
1795 * but also of the attribute objects.
1797 pthread_mutexattr_t l_attributes = {0};
1798 # else
1799 pthread_mutexattr_t l_attributes;
1800 # endif
1802 if (attributes == 0)
1803 attributes = &l_attributes;
1804 int result = 0;
1805 int attr_init = 0; // have we initialized the local attributes.
1807 // Only do these initializations if the <attributes> parameter
1808 // wasn't originally set.
1809 if (attributes == &l_attributes)
1811 if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0)
1813 result = 0;
1814 attr_init = 1; // we have initialized these attributes
1816 else
1818 result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
1822 if (result == 0 && lock_scope != 0)
1824 # if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
1825 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes,
1826 lock_scope),
1827 result);
1828 # endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
1831 if (result == 0 && lock_type != 0)
1833 # if defined (ACE_HAS_RECURSIVE_MUTEXES)
1834 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes,
1835 lock_type),
1836 result);
1837 # endif /* ACE_HAS_RECURSIVE_MUTEXES */
1840 if (result == 0)
1842 # if defined (ACE_VXWORKS)&& (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
1843 /* VxWorks 6.x API reference states:
1844 * If the memory for the mutex variable object has been allocated
1845 * dynamically, it is a good policy to always zero out the
1846 * block of memory so as to avoid spurious EBUSY return code
1847 * when calling this routine.
1848 * Tests shows this to be necessary.
1850 ACE_OS::memset (m, 0, sizeof (*m));
1851 # endif
1852 if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0)
1853 result = 0;
1854 else
1855 result = -1; // ACE_ADAPT_RETVAL used it for intermediate status
1858 // Only do the deletions if the <attributes> parameter wasn't
1859 // originally set.
1860 if (attributes == &l_attributes && attr_init)
1861 ::pthread_mutexattr_destroy (&l_attributes);
1863 return result;
1864 # elif defined (ACE_HAS_STHREADS)
1865 ACE_UNUSED_ARG (name);
1866 ACE_UNUSED_ARG (sa);
1867 ACE_UNUSED_ARG (lock_type);
1868 int result;
1869 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m,
1870 lock_scope,
1871 attributes),
1872 result),
1873 int, -1);
1874 # elif defined (ACE_HAS_WTHREADS)
1875 m->type_ = lock_scope;
1877 SECURITY_ATTRIBUTES sa_buffer;
1878 SECURITY_DESCRIPTOR sd_buffer;
1879 switch (lock_scope)
1881 case USYNC_PROCESS:
1882 # if defined (ACE_HAS_WINCE)
1883 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
1884 m->proc_mutex_ =
1885 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1886 (sa, &sa_buffer, &sd_buffer),
1887 FALSE,
1888 ACE_Ascii_To_Wide (name).wchar_rep ());
1889 # else /* ACE_HAS_WINCE */
1890 m->proc_mutex_ =
1891 ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
1892 (sa, &sa_buffer, &sd_buffer),
1893 FALSE,
1894 name);
1895 # endif /* ACE_HAS_WINCE */
1896 if (m->proc_mutex_ == 0)
1897 ACE_FAIL_RETURN (-1);
1898 else
1900 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1901 ACE_OS::set_errno_to_last_error ();
1902 return 0;
1904 case USYNC_THREAD:
1905 return ACE_OS::thread_mutex_init (&m->thr_mutex_,
1906 lock_type,
1907 name,
1908 attributes);
1909 default:
1910 errno = EINVAL;
1911 return -1;
1913 /* NOTREACHED */
1915 # elif defined (ACE_VXWORKS)
1916 ACE_UNUSED_ARG (name);
1917 ACE_UNUSED_ARG (attributes);
1918 ACE_UNUSED_ARG (sa);
1919 ACE_UNUSED_ARG (lock_type);
1921 return (*m = ::semMCreate (lock_scope)) == 0 ? -1 : 0;
1922 # endif /* ACE_HAS_PTHREADS */
1923 #else
1924 ACE_UNUSED_ARG (m);
1925 ACE_UNUSED_ARG (lock_scope);
1926 ACE_UNUSED_ARG (name);
1927 ACE_UNUSED_ARG (attributes);
1928 ACE_UNUSED_ARG (sa);
1929 ACE_UNUSED_ARG (lock_type);
1930 ACE_NOTSUP_RETURN (-1);
1931 #endif /* ACE_HAS_THREADS */
1935 ACE_OS::mutex_destroy (ACE_mutex_t *m)
1937 ACE_OS_TRACE ("ACE_OS::mutex_destroy");
1938 #if defined (ACE_HAS_THREADS)
1939 # if defined (ACE_HAS_PTHREADS)
1940 int result;
1941 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m),
1942 result), int, -1);
1943 # elif defined (ACE_HAS_STHREADS)
1944 int result;
1945 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), result), int, -1);
1946 # elif defined (ACE_HAS_WTHREADS)
1947 switch (m->type_)
1949 case USYNC_PROCESS:
1950 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_),
1951 ace_result_),
1952 int, -1);
1953 case USYNC_THREAD:
1954 return ACE_OS::thread_mutex_destroy (&m->thr_mutex_);
1955 default:
1956 errno = EINVAL;
1957 return -1;
1959 /* NOTREACHED */
1960 # elif defined (ACE_VXWORKS)
1961 return ::semDelete (*m) == OK ? 0 : -1;
1962 # endif /* Threads variety case */
1963 #else
1964 ACE_UNUSED_ARG (m);
1965 ACE_NOTSUP_RETURN (-1);
1966 #endif /* ACE_HAS_THREADS */
1969 #if defined (ACE_HAS_WCHAR)
1971 ACE_OS::mutex_init (ACE_mutex_t *m,
1972 int lock_scope,
1973 const wchar_t *name,
1974 ACE_mutexattr_t *attributes,
1975 LPSECURITY_ATTRIBUTES sa,
1976 int lock_type)
1978 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
1979 m->type_ = lock_scope;
1980 SECURITY_ATTRIBUTES sa_buffer;
1981 SECURITY_DESCRIPTOR sd_buffer;
1982 switch (lock_scope)
1984 case USYNC_PROCESS:
1985 m->proc_mutex_ =
1986 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1987 (sa, &sa_buffer, &sd_buffer),
1988 FALSE,
1989 name);
1990 if (m->proc_mutex_ == 0)
1991 ACE_FAIL_RETURN (-1);
1992 else
1993 return 0;
1994 case USYNC_THREAD:
1995 return ACE_OS::thread_mutex_init (&m->thr_mutex_,
1996 lock_type,
1997 name,
1998 attributes);
2001 errno = EINVAL;
2002 return -1;
2003 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2004 return ACE_OS::mutex_init (m,
2005 lock_scope,
2006 ACE_Wide_To_Ascii (name).char_rep (),
2007 attributes,
2009 lock_type);
2010 #endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2012 #endif /* ACE_HAS_WCHAR */
2015 ACE_OS::mutex_lock (ACE_mutex_t *m)
2017 // ACE_OS_TRACE ("ACE_OS::mutex_lock");
2018 #if defined (ACE_HAS_THREADS)
2019 # if defined (ACE_HAS_PTHREADS)
2020 // Note, don't use "::" here since the following call is often a macro.
2021 int result;
2022 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), result),
2023 int, -1);
2024 # elif defined (ACE_HAS_STHREADS)
2025 int result;
2026 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), result), int, -1);
2027 # elif defined (ACE_HAS_WTHREADS)
2028 switch (m->type_)
2030 case USYNC_PROCESS:
2031 switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
2034 // Timeout can't occur, so don't bother checking...
2036 case WAIT_OBJECT_0:
2037 case WAIT_ABANDONED:
2038 // We will ignore abandonments in this method
2039 // Note that we still hold the lock
2040 return 0;
2041 default:
2042 // This is a hack, we need to find an appropriate mapping...
2043 ACE_OS::set_errno_to_last_error ();
2044 return -1;
2046 case USYNC_THREAD:
2047 return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
2048 default:
2049 errno = EINVAL;
2050 return -1;
2052 /* NOTREACHED */
2053 # elif defined (ACE_VXWORKS)
2054 return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1;
2055 # endif /* Threads variety case */
2056 #else
2057 ACE_UNUSED_ARG (m);
2058 ACE_NOTSUP_RETURN (-1);
2059 #endif /* ACE_HAS_THREADS */
2063 ACE_OS::mutex_lock (ACE_mutex_t *m,
2064 int &abandoned)
2066 ACE_OS_TRACE ("ACE_OS::mutex_lock");
2067 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2068 abandoned = 0;
2069 switch (m->type_)
2071 case USYNC_PROCESS:
2072 switch (::WaitForSingleObject (m->proc_mutex_, INFINITE))
2075 // Timeout can't occur, so don't bother checking...
2077 case WAIT_OBJECT_0:
2078 return 0;
2079 case WAIT_ABANDONED:
2080 abandoned = 1;
2081 return 0; // something goofed, but we hold the lock ...
2082 default:
2083 // This is a hack, we need to find an appropriate mapping...
2084 ACE_OS::set_errno_to_last_error ();
2085 return -1;
2087 case USYNC_THREAD:
2088 return ACE_OS::thread_mutex_lock (&m->thr_mutex_);
2089 default:
2090 errno = EINVAL;
2091 return -1;
2093 /* NOTREACHED */
2094 #else
2095 ACE_UNUSED_ARG (m);
2096 ACE_UNUSED_ARG (abandoned);
2097 ACE_NOTSUP_RETURN (-1);
2098 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2102 ACE_OS::mutex_lock (ACE_mutex_t *m,
2103 const ACE_Time_Value &timeout)
2105 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
2107 # if defined (ACE_HAS_PTHREADS)
2108 int result;
2110 // "timeout" should be an absolute time.
2112 timespec_t ts = timeout; // Calls ACE_Time_Value::operator timespec_t().
2114 // Note that the mutex should not be a recursive one, i.e., it
2115 // should only be a standard mutex or an error checking mutex.
2117 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, -1, result);
2119 // We need to adjust this to make the errno values consistent.
2120 if (result == -1 && errno == ETIMEDOUT)
2121 errno = ETIME;
2122 return result;
2124 # elif defined (ACE_HAS_WTHREADS)
2125 // Note that we must convert between absolute time (which is passed
2126 // as a parameter) and relative time (which is what the system call
2127 // expects).
2128 ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ());
2130 switch (m->type_)
2132 case USYNC_PROCESS:
2133 switch (::WaitForSingleObject (m->proc_mutex_,
2134 relative_time.msec ()))
2136 case WAIT_OBJECT_0:
2137 case WAIT_ABANDONED:
2138 // We will ignore abandonments in this method
2139 // Note that we still hold the lock
2140 return 0;
2141 case WAIT_TIMEOUT:
2142 errno = ETIME;
2143 return -1;
2144 default:
2145 // This is a hack, we need to find an appropriate mapping...
2146 ACE_OS::set_errno_to_last_error ();
2147 return -1;
2149 case USYNC_THREAD:
2150 ACE_NOTSUP_RETURN (-1);
2151 default:
2152 errno = EINVAL;
2153 return -1;
2155 /* NOTREACHED */
2157 # elif defined (ACE_VXWORKS)
2159 // Note that we must convert between absolute time (which is passed
2160 // as a parameter) and relative time (which is what the system call
2161 // expects).
2162 ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ());
2164 int ticks_per_sec = ::sysClkRateGet ();
2166 int ticks = relative_time.sec() * ticks_per_sec +
2167 relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS;
2168 if (::semTake (*m, ticks) == ERROR)
2170 if (errno == S_objLib_OBJ_TIMEOUT)
2171 // Convert the VxWorks errno to one that's common for to ACE
2172 // platforms.
2173 errno = ETIME;
2174 else if (errno == S_objLib_OBJ_UNAVAILABLE)
2175 errno = EBUSY;
2176 return -1;
2178 else
2179 return 0;
2180 # endif /* ACE_HAS_PTHREADS */
2182 #else
2183 ACE_UNUSED_ARG (m);
2184 ACE_UNUSED_ARG (timeout);
2185 ACE_NOTSUP_RETURN (-1);
2186 #endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
2190 ACE_OS::mutex_trylock (ACE_mutex_t *m)
2192 ACE_OS_TRACE ("ACE_OS::mutex_trylock");
2193 #if defined (ACE_HAS_THREADS)
2194 # if defined (ACE_HAS_PTHREADS)
2195 // Note, don't use "::" here since the following call is often a macro.
2196 int result;
2197 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), result),
2198 int, -1);
2199 # elif defined (ACE_HAS_STHREADS)
2200 int result;
2201 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), result), int, -1);
2202 # elif defined (ACE_HAS_WTHREADS)
2203 switch (m->type_)
2205 case USYNC_PROCESS:
2207 // Try for 0 milliseconds - i.e. nonblocking.
2208 switch (::WaitForSingleObject (m->proc_mutex_, 0))
2210 case WAIT_OBJECT_0:
2211 return 0;
2212 case WAIT_ABANDONED:
2213 // We will ignore abandonments in this method. Note that
2214 // we still hold the lock.
2215 return 0;
2216 case WAIT_TIMEOUT:
2217 errno = EBUSY;
2218 return -1;
2219 default:
2220 ACE_OS::set_errno_to_last_error ();
2221 return -1;
2224 case USYNC_THREAD:
2225 return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
2226 default:
2227 errno = EINVAL;
2228 return -1;
2230 /* NOTREACHED */
2231 # elif defined (ACE_VXWORKS)
2232 if (::semTake (*m, NO_WAIT) == ERROR)
2233 if (errno == S_objLib_OBJ_UNAVAILABLE)
2235 // couldn't get the semaphore
2236 errno = EBUSY;
2237 return -1;
2239 else
2240 // error
2241 return -1;
2242 else
2243 // got the semaphore
2244 return 0;
2245 # endif /* Threads variety case */
2246 #else
2247 ACE_UNUSED_ARG (m);
2248 ACE_NOTSUP_RETURN (-1);
2249 #endif /* ACE_HAS_THREADS */
2253 ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned)
2255 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2256 abandoned = 0;
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 abandoned = 1;
2268 return 0; // something goofed, but we hold the lock ...
2269 case WAIT_TIMEOUT:
2270 errno = EBUSY;
2271 return -1;
2272 default:
2273 ACE_OS::set_errno_to_last_error ();
2274 return -1;
2277 case USYNC_THREAD:
2278 return ACE_OS::thread_mutex_trylock (&m->thr_mutex_);
2279 default:
2280 errno = EINVAL;
2281 return -1;
2283 /* NOTREACHED */
2284 #else
2285 ACE_UNUSED_ARG (m);
2286 ACE_UNUSED_ARG (abandoned);
2287 ACE_NOTSUP_RETURN (-1);
2288 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2292 ACE_OS::mutex_unlock (ACE_mutex_t *m)
2294 ACE_OS_TRACE ("ACE_OS::mutex_unlock");
2295 #if defined (ACE_HAS_THREADS)
2296 # if defined (ACE_HAS_PTHREADS)
2297 // Note, don't use "::" here since the following call is often a macro.
2298 int result;
2299 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), result),
2300 int, -1);
2301 # elif defined (ACE_HAS_STHREADS)
2302 int result;
2303 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), result), int, -1);
2304 # elif defined (ACE_HAS_WTHREADS)
2305 switch (m->type_)
2307 case USYNC_PROCESS:
2308 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_),
2309 ace_result_),
2310 int, -1);
2311 case USYNC_THREAD:
2312 return ACE_OS::thread_mutex_unlock (&m->thr_mutex_);
2313 default:
2314 errno = EINVAL;
2315 return -1;
2317 /* NOTREACHED */
2318 # elif defined (ACE_VXWORKS)
2319 return ::semGive (*m) == OK ? 0 : -1;
2320 # endif /* Threads variety case */
2321 #else
2322 ACE_UNUSED_ARG (m);
2323 ACE_NOTSUP_RETURN (-1);
2324 #endif /* ACE_HAS_THREADS */
2327 void
2328 ACE_OS::mutex_lock_cleanup (void *mutex)
2330 ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
2331 #if defined (ACE_HAS_THREADS)
2332 # if defined (ACE_HAS_PTHREADS)
2333 ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex;
2334 ACE_OS::mutex_unlock (p_lock);
2335 # else
2336 ACE_UNUSED_ARG (mutex);
2337 # endif /* ACE_HAS_PTHREADS */
2338 #else
2339 ACE_UNUSED_ARG (mutex);
2340 #endif /* ACE_HAS_THREADS */
2343 /*****************************************************************************/
2344 // MUTEXES END
2345 /*****************************************************************************/
2347 /*****************************************************************************/
2348 // EVENTS BEGIN
2349 /*****************************************************************************/
2352 ACE_OS::event_destroy (ACE_event_t *event)
2354 #if defined (ACE_WIN32)
2355 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1);
2356 #elif defined (ACE_HAS_THREADS)
2357 if (event->eventdata_)
2359 // mutex_destroy()/cond_destroy() are called in a loop if the object
2360 // is BUSY. This avoids conditions where we fail to destroy these
2361 // objects because at time of destroy they were just being used in
2362 // another thread possibly causing deadlocks later on if they keep
2363 // being used after we're gone.
2365 if (event->eventdata_->type_ == USYNC_PROCESS)
2367 if (event->name_)
2369 // Only destroy the event data if we're the ones who initialized
2370 // it.
2372 int r1, r2;
2373 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2374 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2375 (!defined (ACE_USES_FIFO_SEM) && \
2376 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2377 // First destroy the mutex so locking after this will return
2378 // errors.
2379 while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
2380 && errno == EBUSY)
2382 ACE_OS::thr_yield ();
2384 # else
2385 r1 = ACE_OS::sema_destroy(&event->lock_);
2386 # endif
2388 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2389 (!defined (ACE_USES_FIFO_SEM) && \
2390 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2391 // Now fix event to manual reset, raise signal and broadcast
2392 // until is's possible to destroy the condition.
2393 event->eventdata_->manual_reset_ = 1;
2394 while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
2395 && errno == EBUSY)
2397 event->eventdata_->is_signaled_ = 1;
2398 ACE_OS::cond_broadcast (&event->eventdata_->condition_);
2399 ACE_OS::thr_yield ();
2401 # else
2402 r2 = ACE_OS::sema_destroy(&event->semaphore_);
2403 # endif
2404 ACE_OS::munmap (event->eventdata_,
2405 sizeof (ACE_eventdata_t));
2406 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR(event->name_));
2407 ACE_OS::free (event->name_);
2408 return r1 != 0 || r2 != 0 ? -1 : 0;
2410 else
2412 ACE_OS::munmap (event->eventdata_,
2413 sizeof (ACE_eventdata_t));
2414 # if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || \
2415 (defined (ACE_LACKS_MUTEXATTR_PSHARED) && defined (ACE_LACKS_CONDATTR_PSHARED))) && \
2416 (defined (ACE_USES_FIFO_SEM) || \
2417 (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && defined (ACE_LACKS_NAMED_POSIX_SEM)))
2418 ACE_OS::sema_destroy(&event->lock_);
2419 # endif
2420 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2421 (!defined (ACE_USES_FIFO_SEM) && \
2422 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2423 return 0;
2424 # else
2425 return ACE_OS::sema_destroy(&event->semaphore_);
2426 # endif
2429 else
2431 int r1, r2;
2432 // First destroy the mutex so locking after this will return errors.
2433 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2434 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2435 (!defined (ACE_USES_FIFO_SEM) && \
2436 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2437 // first destroy the mutex so locking after this will return errors
2438 while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1
2439 && errno == EBUSY)
2441 ACE_OS::thr_yield ();
2443 # else
2444 r1 = ACE_OS::sema_destroy(&event->lock_);
2445 # endif
2447 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2448 (!defined (ACE_USES_FIFO_SEM) && \
2449 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2450 // Now fix event to manual reset, raise signal and broadcast until
2451 // it's possible to destroy the condition.
2452 event->eventdata_->manual_reset_ = 1;
2453 while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1
2454 && errno == EBUSY)
2456 event->eventdata_->is_signaled_ = 1;
2457 ACE_OS::cond_broadcast (&event->eventdata_->condition_);
2458 ACE_OS::thr_yield ();
2460 # else
2461 r2 = ACE_OS::sema_destroy(&event->semaphore_);
2462 # endif
2463 delete event->eventdata_;
2464 return r1 != 0 || r2 != 0 ? -1 : 0;
2468 return 0;
2469 #else
2470 ACE_UNUSED_ARG (event);
2471 ACE_NOTSUP_RETURN (-1);
2472 #endif /* ACE_WIN32 */
2476 ACE_OS::event_init (ACE_event_t *event,
2477 int manual_reset,
2478 int initial_state,
2479 int type,
2480 const char *name,
2481 void *arg,
2482 LPSECURITY_ATTRIBUTES sa)
2484 #if defined (ACE_WIN32)
2485 ACE_UNUSED_ARG (type);
2486 ACE_UNUSED_ARG (arg);
2487 SECURITY_ATTRIBUTES sa_buffer;
2488 SECURITY_DESCRIPTOR sd_buffer;
2489 # if defined (ACE_HAS_WINCE)
2490 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
2491 *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r
2492 (sa, &sa_buffer, &sd_buffer),
2493 manual_reset,
2494 initial_state,
2495 ACE_Ascii_To_Wide (name).wchar_rep ());
2496 # else /* ACE_HAS_WINCE */
2497 *event = ::CreateEventA (ACE_OS::default_win32_security_attributes_r
2498 (sa, &sa_buffer, &sd_buffer),
2499 manual_reset,
2500 initial_state,
2501 name);
2502 # endif /* ACE_HAS_WINCE */
2503 if (*event == 0)
2504 ACE_FAIL_RETURN (-1);
2505 else
2506 return 0;
2507 #elif defined (ACE_HAS_THREADS)
2508 ACE_UNUSED_ARG (sa);
2509 event->eventdata_ = 0;
2510 ACE_eventdata_t* evtdata;
2512 if (type == USYNC_PROCESS)
2514 const char *name_p = 0;
2515 # if defined (ACE_SHM_OPEN_REQUIRES_ONE_SLASH)
2516 char adj_name[MAXPATHLEN];
2517 if (name[0] != '/')
2519 adj_name[0] = '/';
2520 ACE_OS::strsncpy (&adj_name[1], name, MAXPATHLEN-1);
2521 name_p = adj_name;
2523 else
2525 name_p = name;
2527 # else
2528 name_p = name;
2529 # endif /* ACE_SHM_OPEN_REQUIRES_ONE_SLASH */
2530 int owner = 0;
2531 // Let's see if the shared memory entity already exists.
2532 ACE_HANDLE fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
2533 O_RDWR | O_CREAT | O_EXCL,
2534 ACE_DEFAULT_FILE_PERMS);
2535 if (fd == ACE_INVALID_HANDLE)
2537 if (errno == EEXIST)
2538 fd = ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p),
2539 O_RDWR | O_CREAT,
2540 ACE_DEFAULT_FILE_PERMS);
2541 if (fd == ACE_INVALID_HANDLE) // Still can't get it.
2542 return -1;
2544 else
2546 // We own this shared memory object! Let's set its size.
2547 if (ACE_OS::ftruncate (fd, sizeof (ACE_eventdata_t)) == -1)
2549 ACE_OS::close (fd);
2550 return -1;
2552 owner = 1;
2555 evtdata =
2556 (ACE_eventdata_t *) ACE_OS::mmap (0,
2557 sizeof (ACE_eventdata_t),
2558 PROT_RDWR,
2559 MAP_SHARED,
2562 ACE_OS::close (fd);
2563 if (evtdata == MAP_FAILED)
2565 if (owner)
2566 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2567 return -1;
2570 if (owner)
2572 event->name_ = ACE_OS::strdup (name_p);
2573 if (event->name_ == 0)
2575 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p));
2576 return -1;
2578 event->eventdata_ = evtdata;
2579 event->eventdata_->type_ = type;
2580 event->eventdata_->manual_reset_ = manual_reset;
2581 event->eventdata_->is_signaled_ = initial_state;
2582 event->eventdata_->auto_event_signaled_ = false;
2583 event->eventdata_->waiting_threads_ = 0;
2584 event->eventdata_->signal_count_ = 0;
2586 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2587 (!defined (ACE_USES_FIFO_SEM) && \
2588 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2589 int result = ACE_OS::cond_init (&event->eventdata_->condition_,
2590 static_cast<short> (type),
2591 name,
2592 arg);
2593 # else
2594 char sem_name[128];
2595 ACE_OS::strncpy (sem_name,
2596 name,
2597 sizeof (sem_name) - (1 + sizeof ("._ACE_EVTSEM_")));
2598 ACE_OS::strcat (sem_name, "._ACE_EVTSEM_");
2599 int result = ACE_OS::sema_init (&event->semaphore_,
2601 type,
2602 sem_name,
2603 arg);
2604 # endif
2605 if (result == 0)
2606 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2607 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2608 (!defined (ACE_USES_FIFO_SEM) && \
2609 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2610 result = ACE_OS::mutex_init (&event->eventdata_->lock_,
2611 type,
2612 name,
2613 (ACE_mutexattr_t *) arg);
2614 # else
2616 char lck_name[128];
2617 ACE_OS::strncpy
2618 (lck_name,
2619 name,
2620 sizeof (lck_name) - (1 + sizeof ("._ACE_EVTLCK_")));
2621 ACE_OS::strcat (lck_name, "._ACE_EVTLCK_");
2622 result = ACE_OS::sema_init (&event->lock_,
2624 type,
2625 lck_name,
2626 arg);
2627 if (result == 0)
2628 result = ACE_OS::sema_post (&event->lock_); /* Initially unlock */
2630 # endif
2631 return result;
2633 else
2635 int result = 0;
2637 event->name_ = 0;
2638 event->eventdata_ = evtdata;
2639 #if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_CONDATTR_PSHARED)) && \
2640 (defined (ACE_USES_FIFO_SEM) || \
2641 (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && !defined (ACE_LACKS_NAMED_POSIX_SEM)))
2642 char sem_name[128];
2643 ACE_OS::strncpy (sem_name,
2644 name,
2645 sizeof (sem_name) - (1 + sizeof ("._ACE_EVTSEM_")));
2646 ACE_OS::strcat (sem_name, "._ACE_EVTSEM_");
2647 result = ACE_OS::sema_init(&event->semaphore_,
2649 type,
2650 sem_name,
2651 arg);
2652 # endif
2654 # if (!defined (ACE_HAS_PTHREADS) || !defined (_POSIX_THREAD_PROCESS_SHARED) || \
2655 (defined (ACE_LACKS_MUTEXATTR_PSHARED) && defined (ACE_LACKS_CONDATTR_PSHARED))) && \
2656 (defined (ACE_USES_FIFO_SEM) || \
2657 (defined (ACE_HAS_POSIX_SEM) && defined (ACE_HAS_POSIX_SEM_TIMEOUT) && defined (ACE_LACKS_NAMED_POSIX_SEM)))
2658 if (result == 0)
2660 char lck_name[128];
2661 ACE_OS::strncpy
2662 (lck_name,
2663 name,
2664 sizeof (lck_name) - (1 + sizeof ("._ACE_EVTLCK_")));
2665 ACE_OS::strcat (lck_name, "._ACE_EVTLCK_");
2666 result = ACE_OS::sema_init (&event->lock_,
2668 type,
2669 lck_name,
2670 arg);
2672 # endif
2673 return result;
2676 else
2678 ACE_NEW_RETURN (evtdata, ACE_eventdata_t, -1);
2679 event->name_ = 0;
2680 event->eventdata_ = evtdata;
2681 event->eventdata_->type_ = type;
2682 event->eventdata_->manual_reset_ = manual_reset;
2683 event->eventdata_->is_signaled_ = initial_state;
2684 event->eventdata_->auto_event_signaled_ = false;
2685 event->eventdata_->waiting_threads_ = 0;
2686 event->eventdata_->signal_count_ = 0;
2688 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2689 (!defined (ACE_USES_FIFO_SEM) && \
2690 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2691 int result = ACE_OS::cond_init (&event->eventdata_->condition_,
2692 static_cast<short> (type),
2693 name,
2694 arg);
2695 # else
2696 int result = ACE_OS::sema_init (&event->semaphore_,
2698 type,
2699 name,
2700 arg);
2701 # endif
2702 if (result == 0)
2703 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2704 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2705 (!defined (ACE_USES_FIFO_SEM) && \
2706 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2707 result = ACE_OS::mutex_init (&event->eventdata_->lock_,
2708 type,
2709 name,
2710 (ACE_mutexattr_t *) arg);
2711 # else
2712 result = ACE_OS::sema_init (&event->lock_,
2714 type,
2715 name,
2716 arg);
2717 if (result == 0)
2718 result = ACE_OS::sema_post(&event->lock_); /* initially unlock */
2719 # endif
2721 return result;
2723 #else
2724 ACE_UNUSED_ARG (event);
2725 ACE_UNUSED_ARG (manual_reset);
2726 ACE_UNUSED_ARG (initial_state);
2727 ACE_UNUSED_ARG (type);
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 result = 0;
2742 int error = 0;
2744 // grab the lock first
2745 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2746 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2747 (!defined (ACE_USES_FIFO_SEM) && \
2748 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2749 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
2750 # else
2751 if (ACE_OS::sema_wait (&event->lock_) == 0)
2752 # endif
2754 if (event->eventdata_->waiting_threads_ > 0)
2756 // Manual-reset event.
2757 if (event->eventdata_->manual_reset_ == 1)
2759 // Wakeup all waiters.
2760 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2761 (!defined (ACE_USES_FIFO_SEM) && \
2762 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2763 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2765 result = -1;
2766 error = errno;
2768 if (result == 0)
2769 event->eventdata_->signal_count_ = event->eventdata_->waiting_threads_;
2770 # else
2771 event->eventdata_->signal_count_ = event->eventdata_->waiting_threads_;
2772 for (unsigned long i=0; i<event->eventdata_->signal_count_ ;++i)
2773 if (ACE_OS::sema_post(&event->semaphore_) != 0)
2775 event->eventdata_->signal_count_ = 0;
2776 result = -1;
2777 error = errno;
2780 if (result == 0)
2781 while(event->eventdata_->signal_count_!=0 && event->eventdata_->waiting_threads_!=0)
2782 ACE_OS::thr_yield ();
2783 # endif
2785 // Auto-reset event: wakeup one waiter.
2786 else
2788 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2789 (!defined (ACE_USES_FIFO_SEM) && \
2790 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2791 if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0)
2792 # else
2793 if (ACE_OS::sema_post(&event->semaphore_) != 0)
2794 # endif
2796 result = -1;
2797 error = errno;
2800 event->eventdata_->auto_event_signaled_ = true;
2804 // Reset event.
2805 event->eventdata_->is_signaled_ = 0;
2807 // Now we can let go of the lock.
2808 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2809 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2810 (!defined (ACE_USES_FIFO_SEM) && \
2811 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2812 ACE_OS::mutex_unlock (&event->eventdata_->lock_);
2813 # else
2814 ACE_OS::sema_post (&event->lock_);
2815 # endif
2816 if (result == -1)
2817 // Reset errno in case mutex_unlock() also fails...
2818 errno = error;
2820 else
2821 result = -1;
2822 return result;
2823 #else
2824 ACE_UNUSED_ARG (event);
2825 ACE_NOTSUP_RETURN (-1);
2826 #endif /* ACE_WIN32 */
2830 ACE_OS::event_reset (ACE_event_t *event)
2832 #if defined (ACE_WIN32)
2833 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1);
2834 #elif defined (ACE_HAS_THREADS)
2835 int result = 0;
2837 // Grab the lock first.
2838 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2839 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2840 (!defined (ACE_USES_FIFO_SEM) && \
2841 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2842 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
2843 # else
2844 if (ACE_OS::sema_wait (&event->lock_) == 0)
2845 # endif
2847 // Reset event.
2848 event->eventdata_->is_signaled_ = 0;
2849 event->eventdata_->auto_event_signaled_ = false;
2851 // Now we can let go of the lock.
2852 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2853 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2854 (!defined (ACE_USES_FIFO_SEM) && \
2855 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2856 ACE_OS::mutex_unlock (&event->eventdata_->lock_);
2857 # else
2858 ACE_OS::sema_post (&event->lock_);
2859 # endif
2861 else
2862 result = -1;
2863 return result;
2864 #else
2865 ACE_UNUSED_ARG (event);
2866 ACE_NOTSUP_RETURN (-1);
2867 #endif /* ACE_WIN32 */
2871 ACE_OS::event_signal (ACE_event_t *event)
2873 #if defined (ACE_WIN32)
2874 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1);
2875 #elif defined (ACE_HAS_THREADS)
2876 int result = 0;
2877 int error = 0;
2879 // grab the lock first
2880 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2881 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2882 (!defined (ACE_USES_FIFO_SEM) && \
2883 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2884 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
2885 # else
2886 if (ACE_OS::sema_wait (&event->lock_) == 0)
2887 # endif
2889 // Manual-reset event.
2890 if (event->eventdata_->manual_reset_ == 1)
2892 // wakeup all
2893 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2894 (!defined (ACE_USES_FIFO_SEM) && \
2895 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2896 if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0)
2898 result = -1;
2899 error = errno;
2901 # else
2902 if (ACE_OS::sema_post(&event->semaphore_) != 0)
2904 result = -1;
2905 error = errno;
2907 # endif
2909 if (result == 0)
2910 // signal event
2911 event->eventdata_->is_signaled_ = 1;
2913 // Auto-reset event
2914 else
2916 if (event->eventdata_->waiting_threads_ == 0)
2917 // No waiters: signal event.
2918 event->eventdata_->is_signaled_ = 1;
2919 // Waiters: wakeup one waiter.
2920 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
2921 (!defined (ACE_USES_FIFO_SEM) && \
2922 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2923 else if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0)
2924 # else
2925 else if (ACE_OS::sema_post(&event->semaphore_) != 0)
2926 # endif
2928 result = -1;
2929 error = errno;
2932 event->eventdata_->auto_event_signaled_ = true;
2935 // Now we can let go of the lock.
2936 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
2937 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
2938 (!defined (ACE_USES_FIFO_SEM) && \
2939 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
2940 ACE_OS::mutex_unlock (&event->eventdata_->lock_);
2941 # else
2942 ACE_OS::sema_post (&event->lock_);
2943 # endif
2945 if (result == -1)
2946 // Reset errno in case mutex_unlock() also fails...
2947 errno = error;
2949 else
2950 result = -1;
2952 return result;
2953 #else
2954 ACE_UNUSED_ARG (event);
2955 ACE_NOTSUP_RETURN (-1);
2956 #endif /* ACE_WIN32 */
2960 ACE_OS::event_timedwait (ACE_event_t *event,
2961 ACE_Time_Value *timeout,
2962 int use_absolute_time)
2964 if (timeout == 0)
2965 // Wait indefinitely.
2966 return ACE_OS::event_wait (event);
2968 #if defined (ACE_WIN32)
2969 DWORD result;
2971 if (timeout->sec () == 0 && timeout->usec () == 0)
2972 // Do a "poll".
2973 result = ::WaitForSingleObject (*event, 0);
2974 else
2976 // Wait for upto <relative_time> number of milliseconds. Note
2977 // that we must convert between absolute time (which is passed
2978 // as a parameter) and relative time (which is what
2979 // WaitForSingleObjects() expects).
2980 // <timeout> parameter is given in absolute or relative value
2981 // depending on parameter <use_absolute_time>.
2982 int msec_timeout;
2983 if (use_absolute_time)
2985 // Time is given in absolute time, we should use
2986 // gettimeofday() to calculate relative time
2987 ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
2989 // Watchout for situations where a context switch has caused
2990 // the current time to be > the timeout. Thanks to Norbert
2991 // Rapp <NRapp@nexus-informatics.de> for pointing this.
2992 if (relative_time < ACE_Time_Value::zero)
2993 msec_timeout = 0;
2994 else
2995 msec_timeout = relative_time.msec ();
2997 else
2998 // time is given in relative time, just convert it into
2999 // milliseconds and use it
3000 msec_timeout = timeout->msec ();
3001 result = ::WaitForSingleObject (*event, msec_timeout);
3004 switch (result)
3006 case WAIT_OBJECT_0:
3007 return 0;
3008 case WAIT_TIMEOUT:
3009 errno = ETIME;
3010 return -1;
3011 default:
3012 // This is a hack, we need to find an appropriate mapping...
3013 ACE_OS::set_errno_to_last_error ();
3014 return -1;
3016 #elif defined (ACE_HAS_THREADS)
3017 int result = 0;
3018 int error = 0;
3020 // grab the lock first
3021 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
3022 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
3023 (!defined (ACE_USES_FIFO_SEM) && \
3024 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3025 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
3026 # else
3027 if (ACE_OS::sema_wait (&event->lock_) == 0)
3028 # endif
3030 if (event->eventdata_->is_signaled_ == 1)
3031 // event is currently signaled
3033 if (event->eventdata_->manual_reset_ == 0)
3035 // AUTO: reset state
3036 event->eventdata_->is_signaled_ = 0;
3037 event->eventdata_->auto_event_signaled_ = false;
3040 else
3041 // event is currently not signaled
3043 event->eventdata_->waiting_threads_++;
3045 ACE_Time_Value absolute_timeout = *timeout;
3047 // cond_timewait() expects absolute time, check
3048 // <use_absolute_time> flag.
3049 if (use_absolute_time == 0)
3050 absolute_timeout += ACE_OS::gettimeofday ();
3052 while (event->eventdata_->is_signaled_ == 0 &&
3053 event->eventdata_->auto_event_signaled_ == false)
3055 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
3056 (!defined (ACE_USES_FIFO_SEM) && \
3057 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3058 if (ACE_OS::cond_timedwait (&event->eventdata_->condition_,
3059 &event->eventdata_->lock_,
3060 &absolute_timeout) != 0)
3062 result = -1;
3063 error = errno;
3064 break;
3067 if (event->eventdata_->signal_count_ > 0)
3069 event->eventdata_->signal_count_--;
3070 break;
3072 # else
3073 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
3074 (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3075 if (ACE_OS::mutex_unlock (&event->eventdata_->lock_) != 0)
3076 # else
3077 if (ACE_OS::sema_post (&event->lock_) != 0)
3078 # endif
3080 event->eventdata_->waiting_threads_--;
3081 return -1;
3084 if (ACE_OS::sema_wait(&event->semaphore_, absolute_timeout) !=0)
3086 result = -1;
3087 if (errno == ETIMEDOUT) // Semaphores time out with ETIMEDOUT (POSIX)
3088 error = ETIME;
3089 else
3090 error = errno;
3093 bool signalled = false;
3094 if (result == 0 && event->eventdata_->signal_count_ > 0)
3096 event->eventdata_->signal_count_--;
3097 signalled = true;
3100 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
3101 (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3102 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) != 0)
3103 # else
3104 if (ACE_OS::sema_wait (&event->lock_) != 0)
3105 # endif
3107 event->eventdata_->waiting_threads_--; // yes, I know it's not save
3108 return -1;
3111 if (result)
3112 break;
3114 if (event->eventdata_->manual_reset_ == 1 && event->eventdata_->is_signaled_ == 1)
3115 if (ACE_OS::sema_post(&event->semaphore_) != 0)
3117 result = -1;
3118 error = errno;
3119 break;
3122 if (signalled)
3123 break;
3124 # endif
3127 // Reset the auto_event_signaled_ to false now that we have
3128 // woken up.
3129 if (event->eventdata_->auto_event_signaled_ == true)
3130 event->eventdata_->auto_event_signaled_ = false;
3132 event->eventdata_->waiting_threads_--;
3135 // Now we can let go of the lock.
3136 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
3137 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
3138 (!defined (ACE_USES_FIFO_SEM) && \
3139 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3140 ACE_OS::mutex_unlock (&event->eventdata_->lock_);
3141 # else
3142 ACE_OS::sema_post (&event->lock_);
3143 # endif
3145 if (result == -1)
3146 // Reset errno in case mutex_unlock() also fails...
3147 errno = error;
3149 else
3150 result = -1;
3151 return result;
3152 #else
3153 ACE_UNUSED_ARG (event);
3154 ACE_UNUSED_ARG (timeout);
3155 ACE_UNUSED_ARG (use_absolute_time);
3156 ACE_NOTSUP_RETURN (-1);
3157 #endif /* ACE_WIN32 */
3161 ACE_OS::event_wait (ACE_event_t *event)
3163 #if defined (ACE_WIN32)
3164 switch (::WaitForSingleObject (*event, INFINITE))
3166 case WAIT_OBJECT_0:
3167 return 0;
3168 default:
3170 ACE_OS::set_errno_to_last_error ();
3171 return -1;
3174 #elif defined (ACE_HAS_THREADS)
3175 int result = 0;
3176 int error = 0;
3178 // grab the lock first
3179 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
3180 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
3181 (!defined (ACE_USES_FIFO_SEM) && \
3182 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3183 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0)
3184 # else
3185 if (ACE_OS::sema_wait (&event->lock_) == 0)
3186 # endif
3188 if (event->eventdata_->is_signaled_ == 1)
3189 // Event is currently signaled.
3191 if (event->eventdata_->manual_reset_ == 0)
3192 // AUTO: reset state
3193 event->eventdata_->is_signaled_ = 0;
3195 else // event is currently not signaled
3197 event->eventdata_->waiting_threads_++;
3199 while (event->eventdata_->is_signaled_ == 0 &&
3200 event->eventdata_->auto_event_signaled_ == false)
3202 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_CONDATTR_PSHARED)) || \
3203 (!defined (ACE_USES_FIFO_SEM) && \
3204 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3205 if (ACE_OS::cond_wait (&event->eventdata_->condition_,
3206 &event->eventdata_->lock_) != 0)
3208 result = -1;
3209 error = errno;
3210 // Something went wrong...
3211 break;
3213 if (event->eventdata_->signal_count_ > 0)
3215 event->eventdata_->signal_count_--;
3216 break;
3218 # else
3219 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
3220 (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3221 if (ACE_OS::mutex_unlock (&event->eventdata_->lock_) != 0)
3222 # else
3223 if (ACE_OS::sema_post (&event->lock_) != 0)
3224 # endif
3226 event->eventdata_->waiting_threads_--;
3227 return -1;
3230 if (ACE_OS::sema_wait (&event->semaphore_) !=0)
3232 result = -1;
3233 error = errno;
3236 bool signalled = false;
3237 if (result == 0 && event->eventdata_->signal_count_ > 0)
3239 event->eventdata_->signal_count_--;
3240 signalled = true;
3243 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)) || \
3244 (!defined (ACE_USES_FIFO_SEM) && (!defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3245 if (ACE_OS::mutex_lock (&event->eventdata_->lock_) != 0)
3246 # else
3247 if (ACE_OS::sema_wait (&event->lock_) != 0)
3248 # endif
3250 event->eventdata_->waiting_threads_--;
3251 return -1;
3254 if (result)
3255 break;
3257 if (event->eventdata_->manual_reset_ == 1 && event->eventdata_->is_signaled_ == 1)
3258 if (ACE_OS::sema_post(&event->semaphore_) != 0)
3260 result = -1;
3261 error = errno;
3262 break;
3265 if (signalled)
3266 break;
3267 # endif
3270 // Reset it since we have woken up.
3271 if (event->eventdata_->auto_event_signaled_ == true)
3272 event->eventdata_->auto_event_signaled_ = false;
3274 event->eventdata_->waiting_threads_--;
3277 // Now we can let go of the lock.
3278 # if (defined (ACE_HAS_PTHREADS) && defined (_POSIX_THREAD_PROCESS_SHARED) && \
3279 (!defined (ACE_LACKS_MUTEXATTR_PSHARED) || !defined (ACE_LACKS_CONDATTR_PSHARED))) || \
3280 (!defined (ACE_USES_FIFO_SEM) && \
3281 (!defined (ACE_HAS_POSIX_SEM) || !defined (ACE_HAS_POSIX_SEM_TIMEOUT) || defined (ACE_LACKS_NAMED_POSIX_SEM)))
3282 ACE_OS::mutex_unlock (&event->eventdata_->lock_);
3283 # else
3284 ACE_OS::sema_post (&event->lock_);
3285 # endif
3287 if (result == -1)
3288 // Reset errno in case mutex_unlock() also fails...
3289 errno = error;
3291 else
3292 result = -1;
3293 return result;
3294 #else
3295 ACE_UNUSED_ARG (event);
3296 ACE_NOTSUP_RETURN (-1);
3297 #endif /* ACE_WIN32 */
3300 /*****************************************************************************/
3301 // EVENTS END
3302 /*****************************************************************************/
3305 ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params)
3307 #if defined (ACE_HAS_STHREADS) || defined (sun)
3308 // Get the class TS and RT class IDs.
3309 ACE_id_t rt_id;
3310 ACE_id_t ts_id;
3311 if (ACE_OS::scheduling_class ("RT", rt_id) == -1
3312 || ACE_OS::scheduling_class ("TS", ts_id) == -1)
3313 return -1;
3315 // Get this LWP's scheduling parameters.
3316 pcparms_t pcparms;
3317 // The following is just to avoid Purify warnings about unitialized
3318 // memory reads.
3319 ACE_OS::memset (&pcparms, 0, sizeof pcparms);
3320 pcparms.pc_cid = PC_CLNULL;
3322 if (ACE_OS::priority_control (P_LWPID,
3323 P_MYID,
3324 PC_GETPARMS,
3325 (char *) &pcparms) == -1)
3326 return -1;
3327 else if (pcparms.pc_cid == rt_id)
3329 // RT class.
3330 rtparms_t rtparms;
3331 ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms);
3333 sched_params.policy (ACE_SCHED_FIFO);
3334 sched_params.priority (rtparms.rt_pri);
3335 sched_params.scope (ACE_SCOPE_THREAD);
3336 ACE_Time_Value quantum (rtparms.rt_tqsecs,
3337 rtparms.rt_tqnsecs == RT_TQINF
3338 ? 0 : rtparms.rt_tqnsecs * 1000);
3339 sched_params.quantum (quantum);
3340 return 0;
3342 else if (pcparms.pc_cid == ts_id)
3344 /* TS class */
3345 tsparms_t tsparms;
3346 ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms);
3348 sched_params.policy (ACE_SCHED_OTHER);
3349 sched_params.priority (tsparms.ts_upri);
3350 sched_params.scope (ACE_SCOPE_THREAD);
3351 return 0;
3353 else
3354 return -1;
3356 #else /* ! ACE_HAS_STHREADS && ! sun */
3357 ACE_UNUSED_ARG (sched_params);
3358 ACE_NOTSUP_RETURN (-1);
3359 #endif /* ! ACE_HAS_STHREADS && ! sun */
3363 ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params)
3365 #if defined (ACE_HAS_STHREADS) || defined (sun)
3366 ACE_Sched_Params lwp_params (sched_params);
3367 lwp_params.scope (ACE_SCOPE_LWP);
3368 return ACE_OS::sched_params (lwp_params);
3369 #else /* ! ACE_HAS_STHREADS && ! sun */
3370 ACE_UNUSED_ARG (sched_params);
3371 ACE_NOTSUP_RETURN (-1);
3372 #endif /* ! ACE_HAS_STHREADS && ! sun */
3375 #if !defined (ACE_HAS_THREADS) || (defined (ACE_LACKS_RWLOCK_T) && \
3376 !defined (ACE_HAS_PTHREADS_UNIX98_EXT))
3378 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
3379 int type,
3380 const ACE_TCHAR *name,
3381 void *arg)
3383 // ACE_OS_TRACE ("ACE_OS::rwlock_init");
3384 # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
3385 // NT, POSIX, and VxWorks don't support this natively.
3386 ACE_UNUSED_ARG (name);
3387 int result = -1;
3389 // Since we cannot use the user specified name for all three
3390 // objects, we will create three completely new names.
3391 ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN];
3392 ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN];
3393 ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN];
3394 ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN];
3396 ACE_OS::unique_name ((const void *) &rw->lock_,
3397 name1,
3398 ACE_UNIQUE_NAME_LEN);
3399 ACE_OS::unique_name ((const void *) &rw->waiting_readers_,
3400 name2,
3401 ACE_UNIQUE_NAME_LEN);
3402 ACE_OS::unique_name ((const void *) &rw->waiting_writers_,
3403 name3,
3404 ACE_UNIQUE_NAME_LEN);
3405 ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_,
3406 name4,
3407 ACE_UNIQUE_NAME_LEN);
3409 ACE_condattr_t attributes;
3410 if (ACE_OS::condattr_init (attributes, type) == 0)
3412 if (ACE_OS::mutex_init (&rw->lock_, type, name1,
3413 (ACE_mutexattr_t *) arg) == 0
3414 && ACE_OS::cond_init (&rw->waiting_readers_,
3415 attributes, name2, arg) == 0
3416 && ACE_OS::cond_init (&rw->waiting_writers_,
3417 attributes, name3, arg) == 0
3418 && ACE_OS::cond_init (&rw->waiting_important_writer_,
3419 attributes, name4, arg) == 0)
3421 // Success!
3422 rw->ref_count_ = 0;
3423 rw->num_waiting_writers_ = 0;
3424 rw->num_waiting_readers_ = 0;
3425 rw->important_writer_ = 0;
3426 result = 0;
3428 ACE_OS::condattr_destroy (attributes);
3431 if (result == -1)
3433 // Save/restore errno.
3434 ACE_Errno_Guard error (errno);
3435 ACE_OS::mutex_destroy (&rw->lock_);
3436 ACE_OS::cond_destroy (&rw->waiting_readers_);
3437 ACE_OS::cond_destroy (&rw->waiting_writers_);
3438 ACE_OS::cond_destroy (&rw->waiting_important_writer_);
3440 return result;
3441 # else
3442 ACE_UNUSED_ARG (rw);
3443 ACE_UNUSED_ARG (type);
3444 ACE_UNUSED_ARG (name);
3445 ACE_UNUSED_ARG (arg);
3446 ACE_NOTSUP_RETURN (-1);
3447 # endif /* ACE_HAS_THREADS */
3449 #endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
3452 ACE_OS::sched_params (const ACE_Sched_Params &sched_params,
3453 ACE_id_t id)
3455 ACE_OS_TRACE ("ACE_OS::sched_params");
3456 #if defined (ACE_HAS_STHREADS)
3457 return ACE_OS::set_scheduling_params (sched_params, id);
3458 #elif defined (ACE_HAS_PTHREADS) && \
3459 (!defined (ACE_LACKS_SETSCHED) || defined (ACE_TANDEM_T1248_PTHREADS) || \
3460 defined (ACE_HAS_PTHREAD_SCHEDPARAM))
3461 if (sched_params.quantum () != ACE_Time_Value::zero)
3463 // quantums not supported
3464 errno = EINVAL;
3465 return -1;
3468 // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
3469 // providing this code for 1003.1c PThreads. Please note that this
3470 // has only been tested for POSIX 1003.1c threads, and may cause
3471 // problems with other PThreads flavors!
3473 struct sched_param param;
3474 param.sched_priority = sched_params.priority ();
3476 if (sched_params.scope () == ACE_SCOPE_PROCESS)
3478 # if defined(ACE_TANDEM_T1248_PTHREADS) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3479 ACE_UNUSED_ARG (id);
3480 ACE_NOTSUP_RETURN (-1);
3481 # else /* ! ACE_TANDEM_T1248_PTHREADS */
3482 int result = ::sched_setscheduler (id == ACE_SELF ? 0 : id,
3483 sched_params.policy (),
3484 &param) == -1 ? -1 : 0;
3485 # if defined (DIGITAL_UNIX)
3486 return result == 0
3487 ? // Use priocntl (2) to set the process in the RT class,
3488 // if using an RT policy.
3489 ACE_OS::set_scheduling_params (sched_params)
3490 : result;
3491 # else /* ! DIGITAL_UNIX */
3492 return result;
3493 # endif /* ! DIGITAL_UNIX */
3494 # endif /* ! ACE_TANDEM_T1248_PTHREADS */
3496 else if (sched_params.scope () == ACE_SCOPE_THREAD)
3498 ACE_thread_t thr_id = ACE_OS::thr_self ();
3500 int result;
3501 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
3502 sched_params.policy (),
3503 &param),
3504 result),
3505 int, -1);
3507 # if defined (sun)
3508 // We need to be able to set LWP priorities on Suns, even without
3509 // ACE_HAS_STHREADS, to obtain preemption.
3510 else if (sched_params.scope () == ACE_SCOPE_LWP)
3511 return ACE_OS::set_scheduling_params (sched_params, id);
3512 # endif /* sun */
3513 else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
3515 errno = EINVAL;
3516 return -1;
3519 #elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
3521 // PharLap ETS can act on the current thread - it can set the
3522 // quantum also, unlike Win32. All this only works on the RT
3523 // version.
3524 # if defined (ACE_HAS_PHARLAP_RT)
3525 if (id != ACE_SELF)
3526 ACE_NOTSUP_RETURN (-1);
3528 # if !defined (ACE_PHARLAP_LABVIEW_RT)
3529 if (sched_params.quantum() != ACE_Time_Value::zero)
3530 EtsSetTimeSlice (sched_params.quantum().msec());
3531 # endif
3533 # else
3535 if (sched_params.quantum () != ACE_Time_Value::zero)
3537 // I don't know of a way to set the quantum on Win32.
3538 errno = EINVAL;
3539 return -1;
3542 # endif /* ACE_HAS_PHARLAP_RT */
3544 if (sched_params.scope () == ACE_SCOPE_THREAD)
3547 // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
3548 // a VERY BAD THING. This include guard will allow people
3549 // to easily disable this feature in ACE.
3550 // It won't work at all for Pharlap since there's no SetPriorityClass.
3551 #if !defined (ACE_HAS_PHARLAP) && \
3552 !defined (ACE_DISABLE_WIN32_INCREASE_PRIORITY)
3553 // Set the priority class of this process to the REALTIME process class
3554 // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL.
3555 if (!::SetPriorityClass (::GetCurrentProcess (),
3556 (sched_params.policy () == ACE_SCHED_FIFO ||
3557 sched_params.policy () == ACE_SCHED_RR)
3558 ? REALTIME_PRIORITY_CLASS
3559 : NORMAL_PRIORITY_CLASS))
3561 ACE_OS::set_errno_to_last_error ();
3562 return -1;
3564 #endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
3566 // Now that we have set the priority class of the process, set the
3567 // priority of the current thread to the desired value.
3568 return ACE_OS::thr_setprio (sched_params.priority ());
3570 else if (sched_params.scope () == ACE_SCOPE_PROCESS)
3573 # if defined (ACE_HAS_PHARLAP_RT)
3574 ACE_NOTSUP_RETURN (-1);
3575 # else
3576 HANDLE hProcess
3577 = ::OpenProcess (PROCESS_SET_INFORMATION,
3578 FALSE,
3579 id == ACE_SELF ? ::GetCurrentProcessId() : id);
3580 if (!hProcess)
3582 ACE_OS::set_errno_to_last_error();
3583 return -1;
3585 // There is no way for us to set the priority of the thread when we
3586 // are setting the priority of a different process. So just ignore
3587 // the priority argument when ACE_SCOPE_PROCESS is specified.
3588 // Setting the priority class will automatically increase the base
3589 // priority of all the threads within a process while maintaining the
3590 // relative priorities of the threads within it.
3591 if (!::SetPriorityClass (hProcess,
3592 (sched_params.policy () == ACE_SCHED_FIFO ||
3593 sched_params.policy () == ACE_SCHED_RR)
3594 ? REALTIME_PRIORITY_CLASS
3595 : NORMAL_PRIORITY_CLASS))
3597 ACE_OS::set_errno_to_last_error ();
3598 ::CloseHandle (hProcess);
3599 return -1;
3601 ::CloseHandle (hProcess);
3602 return 0;
3603 #endif /* ACE_HAS_PHARLAP_RT */
3606 else
3608 errno = EINVAL;
3609 return -1;
3611 #elif defined (ACE_VXWORKS)
3612 ACE_UNUSED_ARG (id);
3614 // There is only one class of priorities on VxWorks, and no time
3615 // quanta. So, just set the current thread's priority.
3617 if (sched_params.policy () != ACE_SCHED_FIFO
3618 || sched_params.scope () != ACE_SCOPE_PROCESS
3619 || sched_params.quantum () != ACE_Time_Value::zero)
3621 errno = EINVAL;
3622 return -1;
3625 // Set the thread priority on the current thread.
3626 return ACE_OS::thr_setprio (sched_params.priority ());
3627 #else
3628 ACE_UNUSED_ARG (sched_params);
3629 ACE_UNUSED_ARG (id);
3630 ACE_NOTSUP_RETURN (-1);
3631 #endif /* ACE_HAS_STHREADS */
3635 ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id)
3637 #if defined (ACE_HAS_PRIOCNTL)
3638 // Get the priority class ID.
3639 pcinfo_t pcinfo;
3640 // The following is just to avoid Purify warnings about unitialized
3641 // memory reads.
3642 ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
3644 ACE_OS::strcpy (pcinfo.pc_clname, class_name);
3645 if (ACE_OS::priority_control (P_ALL /* ignored */,
3646 P_MYID /* ignored */,
3647 PC_GETCID,
3648 (char *) &pcinfo) == -1)
3650 return -1;
3652 else
3654 id = pcinfo.pc_cid;
3655 return 0;
3657 #else /* ! ACE_HAS_PRIOCNTL */
3658 ACE_UNUSED_ARG (class_name);
3659 ACE_UNUSED_ARG (id);
3660 ACE_NOTSUP_RETURN (-1);
3661 #endif /* ! ACE_HAS_PRIOCNTL */
3665 ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params,
3666 ACE_id_t id)
3668 #if defined (ACE_HAS_PRIOCNTL)
3669 // Set priority class, priority, and quantum of this LWP or process as
3670 // specified in sched_params.
3672 // Get the priority class ID.
3673 ACE_id_t class_id;
3674 if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER ?
3675 "TS" :
3676 "RT", class_id) == -1)
3678 return -1;
3681 pcparms_t pcparms;
3682 // The following is just to avoid Purify warnings about unitialized
3683 // memory reads.
3684 ACE_OS::memset (&pcparms, 0, sizeof pcparms);
3686 pcparms.pc_cid = class_id;
3688 if (sched_params.policy () == ACE_SCHED_OTHER &&
3689 sched_params.quantum () == ACE_Time_Value::zero)
3690 // SunOS doesn't support non-zero quantums in time-sharing class: use
3691 // real-time class instead.
3693 tsparms_t tsparms;
3694 // The following is just to avoid Purify warnings about unitialized
3695 // memory reads.
3696 ACE_OS::memset (&tsparms, 0, sizeof tsparms);
3698 // Don't change ts_uprilim (user priority limit)
3699 tsparms.ts_uprilim = TS_NOCHANGE;
3700 tsparms.ts_upri = sched_params.priority ();
3702 // Package up the TS class ID and parameters for the
3703 // priority_control () call.
3704 ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms);
3706 else if (sched_params.policy () == ACE_SCHED_FIFO ||
3707 (sched_params.policy () == ACE_SCHED_RR &&
3708 sched_params.quantum () != ACE_Time_Value::zero))
3709 // must have non-zero quantum for RR, to make it meaningful
3710 // A zero quantum with FIFO has special significance: it actually
3711 // means infinite time quantum, i.e., run-to-completion.
3713 rtparms_t rtparms;
3714 // The following is just to avoid Purify warnings about unitialized
3715 // memory reads.
3716 ACE_OS::memset (&rtparms, 0, sizeof rtparms);
3718 rtparms.rt_pri = sched_params.priority ();
3720 if (sched_params.quantum () == ACE_Time_Value::zero)
3722 // rtparms.rt_tqsecs is ignored with RT_TQINF
3723 rtparms.rt_tqnsecs = RT_TQINF;
3725 else
3727 rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec ();
3728 rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000;
3731 // Package up the RT class ID and parameters for the
3732 // priority_control () call.
3733 ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms);
3735 else
3737 errno = EINVAL;
3738 return -1;
3741 if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD
3742 ? ACE_SCOPE_PROCESS
3743 : sched_params.scope ()),
3745 PC_SETPARMS,
3746 (char *) &pcparms) < 0)
3748 return ACE_OS::last_error ();
3751 return 0;
3752 #else /* ! ACE_HAS_PRIOCNTL */
3753 ACE_UNUSED_ARG (sched_params);
3754 ACE_UNUSED_ARG (id);
3755 ACE_NOTSUP_RETURN (-1);
3756 #endif /* ! ACE_HAS_PRIOCNTL */
3760 ACE_OS::thr_create (ACE_THR_FUNC func,
3761 void *args,
3762 long flags,
3763 ACE_thread_t *thr_id,
3764 ACE_hthread_t *thr_handle,
3765 long priority,
3766 void *stack,
3767 size_t stacksize,
3768 ACE_Base_Thread_Adapter *thread_adapter,
3769 const char** thr_name)
3771 ACE_OS_TRACE ("ACE_OS::thr_create");
3773 if (ACE_BIT_DISABLED (flags, THR_DETACHED) &&
3774 ACE_BIT_DISABLED (flags, THR_JOINABLE))
3775 ACE_SET_BITS (flags, THR_JOINABLE);
3777 #if defined (ACE_NO_THREAD_ADAPTER)
3778 # define ACE_THREAD_FUNCTION func
3779 # define ACE_THREAD_ARGUMENT args
3780 #else /* ! defined (ACE_NO_THREAD_ADAPTER) */
3781 # define ACE_THREAD_FUNCTION thread_args->entry_point ()
3782 # define ACE_THREAD_ARGUMENT thread_args
3783 #endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
3785 ACE_Base_Thread_Adapter *thread_args = 0;
3786 if (thread_adapter == 0)
3787 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
3788 ACE_NEW_RETURN (thread_args,
3789 ACE_OS_Thread_Adapter (func, args,
3790 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME,
3791 ACE_OS_Object_Manager::seh_except_selector(),
3792 ACE_OS_Object_Manager::seh_except_handler()),
3793 -1);
3794 #else
3795 ACE_NEW_RETURN (thread_args,
3796 ACE_OS_Thread_Adapter (func, args,
3797 (ACE_THR_C_FUNC) ACE_THREAD_ADAPTER_NAME),
3798 -1);
3800 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
3801 else
3802 thread_args = thread_adapter;
3804 auto_ptr <ACE_Base_Thread_Adapter> auto_thread_args;
3806 if (thread_adapter == 0)
3807 ACE_AUTO_PTR_RESET (auto_thread_args,
3808 thread_args,
3809 ACE_Base_Thread_Adapter);
3811 #if defined (ACE_HAS_THREADS)
3813 // *** Set Stack Size
3814 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3815 if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3816 stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
3817 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
3819 ACE_thread_t tmp_thr;
3820 if (thr_id == 0)
3821 thr_id = &tmp_thr;
3823 ACE_hthread_t tmp_handle;
3824 if (thr_handle == 0)
3825 thr_handle = &tmp_handle;
3827 # if defined (ACE_HAS_PTHREADS)
3828 int result;
3829 # if defined (ACE_VXWORKS) && (ACE_VXWORKS >= 0x600) && (ACE_VXWORKS <= 0x620)
3830 /* Tests show that VxWorks 6.x pthread lib does not only
3831 * require zeroing of mutex/condition objects to function correctly
3832 * but also of the attribute objects.
3834 pthread_attr_t attr = {0};
3835 # else
3836 pthread_attr_t attr;
3837 # endif
3838 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr), result) != 0)
3839 return -1;
3841 if (stacksize != 0)
3843 size_t size = stacksize;
3845 # if defined (PTHREAD_STACK_MIN)
3846 if (size < static_cast <size_t> (PTHREAD_STACK_MIN))
3847 size = PTHREAD_STACK_MIN;
3848 # endif /* PTHREAD_STACK_MIN */
3850 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
3851 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3852 int result;
3853 if (stack != 0)
3854 result = ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr, stack, size), result);
3855 else
3856 result = ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result);
3857 if (result == -1)
3858 # else
3859 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr, size), result) == -1)
3860 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3862 ::pthread_attr_destroy (&attr);
3863 return -1;
3865 # else
3866 ACE_UNUSED_ARG (size);
3867 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
3870 // *** Set Stack Address
3871 # if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3872 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
3873 if (stack != 0)
3875 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr, stack), result) != 0)
3877 ::pthread_attr_destroy (&attr);
3878 return -1;
3881 # else
3882 ACE_UNUSED_ARG (stack);
3883 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3884 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3886 // *** Deal with various attributes
3887 if (flags != 0)
3889 // *** Set Detach state
3890 # if !defined (ACE_LACKS_SETDETACH)
3891 if (ACE_BIT_ENABLED (flags, THR_DETACHED)
3892 || ACE_BIT_ENABLED (flags, THR_JOINABLE))
3894 int dstate = PTHREAD_CREATE_JOINABLE;
3896 if (ACE_BIT_ENABLED (flags, THR_DETACHED))
3897 dstate = PTHREAD_CREATE_DETACHED;
3899 if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
3900 result) != 0)
3902 ::pthread_attr_destroy (&attr);
3903 return -1;
3907 // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
3908 // call ::pthread_detach () below. If THR_DETACHED is not
3909 // enabled, we call ::pthread_detach () in the Thread_Manager,
3910 // after joining with the thread.
3911 # endif /* ACE_LACKS_SETDETACH */
3913 // *** Set Policy
3914 # if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3915 // If we wish to set the priority explicitly, we have to enable
3916 // explicit scheduling, and a policy, too.
3917 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3919 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3920 if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
3921 && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
3922 && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
3923 ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
3926 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3927 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3928 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3930 int spolicy;
3932 # if defined (ACE_HAS_ONLY_SCHED_OTHER)
3933 // SunOS, thru version 5.6, only supports SCHED_OTHER.
3934 spolicy = SCHED_OTHER;
3935 # elif defined (ACE_HAS_ONLY_SCHED_FIFO)
3936 // NonStop OSS standard pthread supports only SCHED_FIFO.
3937 spolicy = SCHED_FIFO;
3938 # else
3939 // Make sure to enable explicit scheduling, in case we didn't
3940 // enable it above (for non-default priority).
3941 ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
3943 if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3944 spolicy = SCHED_OTHER;
3945 else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3946 spolicy = SCHED_FIFO;
3947 # if defined (SCHED_IO)
3948 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3949 spolicy = SCHED_IO;
3950 # else
3951 else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
3953 errno = ENOSYS;
3954 return -1;
3956 # endif /* SCHED_IO */
3957 else
3958 spolicy = SCHED_RR;
3960 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3962 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
3963 result);
3964 if (result != 0)
3966 ::pthread_attr_destroy (&attr);
3967 return -1;
3971 // *** Set Priority (use reasonable default priorities)
3972 # if defined(ACE_HAS_PTHREADS)
3973 // If we wish to explicitly set a scheduling policy, we also
3974 // have to specify a priority. We choose a "middle" priority as
3975 // default. Maybe this is also necessary on other POSIX'ish
3976 // implementations?
3977 if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
3978 || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
3979 || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
3980 && priority == ACE_DEFAULT_THREAD_PRIORITY)
3982 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
3983 priority = ACE_THR_PRI_FIFO_DEF;
3984 else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
3985 priority = ACE_THR_PRI_RR_DEF;
3986 else // THR_SCHED_DEFAULT
3987 priority = ACE_THR_PRI_OTHER_DEF;
3989 # endif /* ACE_HAS_PTHREADS */
3990 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
3992 struct sched_param sparam;
3993 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
3995 # if defined (ACE_HAS_IRIX62_THREADS)
3996 sparam.sched_priority = ACE_MIN (priority,
3997 (long) PTHREAD_MAX_PRIORITY);
3998 # elif defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
3999 /* For MIT pthreads... */
4000 sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
4001 # elif defined(ACE_HAS_PTHREADS) && !defined (ACE_HAS_STHREADS)
4002 // The following code forces priority into range.
4003 if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
4004 sparam.sched_priority =
4005 ACE_MIN (ACE_THR_PRI_FIFO_MAX,
4006 ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
4007 else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
4008 sparam.sched_priority =
4009 ACE_MIN (ACE_THR_PRI_RR_MAX,
4010 ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
4011 else // Default policy, whether set or not
4012 sparam.sched_priority =
4013 ACE_MIN (ACE_THR_PRI_OTHER_MAX,
4014 ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
4015 # elif defined (PRIORITY_MAX)
4016 sparam.sched_priority = ACE_MIN (priority,
4017 (long) PRIORITY_MAX);
4018 # else
4019 sparam.sched_priority = priority;
4020 # endif /* ACE_HAS_IRIX62_THREADS */
4023 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
4024 // SunOS, through 5.6, POSIX only allows priorities > 0 to
4025 // ::pthread_attr_setschedparam. If a priority of 0 was
4026 // requested, set the thread priority after creating it, below.
4027 if (priority > 0)
4028 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4030 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
4031 result);
4032 if (result != 0)
4034 ::pthread_attr_destroy (&attr);
4035 return -1;
4041 // *** Set scheduling explicit or inherited
4042 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
4043 || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
4045 int sched = PTHREAD_EXPLICIT_SCHED;
4046 if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
4047 sched = PTHREAD_INHERIT_SCHED;
4048 if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr, sched), result) != 0)
4050 ::pthread_attr_destroy (&attr);
4051 return -1;
4054 # else /* ACE_LACKS_SETSCHED */
4055 ACE_UNUSED_ARG (priority);
4056 # endif /* ACE_LACKS_SETSCHED */
4058 // *** Set pthread name
4059 # if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
4060 if (thr_name && *thr_name)
4062 if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr, const_cast<char*>(*thr_name)), result) != 0)
4064 ::pthread_attr_destroy (&attr);
4065 return -1;
4068 #else
4069 ACE_UNUSED_ARG (thr_name);
4070 # endif
4072 // *** Set Scope
4073 # if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
4074 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
4075 || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
4077 # if defined (ACE_CONFIG_LINUX_H) || defined (HPUX) || defined (ACE_VXWORKS)
4078 // LinuxThreads do not have support for PTHREAD_SCOPE_PROCESS.
4079 // Neither does HPUX (up to HP-UX 11.00, as far as I know).
4080 // Also VxWorks only delivers scope system
4081 int scope = PTHREAD_SCOPE_SYSTEM;
4082 # else /* ACE_CONFIG_LINUX_H */
4083 int scope = PTHREAD_SCOPE_PROCESS;
4084 # endif /* ACE_CONFIG_LINUX_H */
4085 if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
4086 scope = PTHREAD_SCOPE_SYSTEM;
4088 if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr, scope), result) != 0)
4090 ::pthread_attr_destroy (&attr);
4091 return -1;
4094 # endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
4096 # ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
4097 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED))
4099 if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr), result) != 0)
4102 ::pthread_attr_destroy (&attr);
4103 return -1;
4106 # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
4108 # if ! defined(ACE_LACKS_THR_CONCURRENCY_FUNCS)
4109 if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
4111 // Increment the number of LWPs by one to emulate the
4112 // SunOS semantics.
4113 int lwps = ACE_OS::thr_getconcurrency ();
4114 if (lwps == -1)
4116 if (errno == ENOTSUP)
4117 // Suppress the ENOTSUP because it's harmless.
4118 errno = 0;
4119 else
4120 // This should never happen on SunOS:
4121 // ::thr_getconcurrency () should always succeed.
4122 return -1;
4124 else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
4126 if (errno == ENOTSUP)
4128 // Unlikely: ::thr_getconcurrency () is supported
4129 // but ::thr_setconcurrency () is not?
4131 else
4132 return -1;
4135 # endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */
4138 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
4139 &attr,
4140 thread_args->entry_point (),
4141 thread_args),
4142 result),
4143 int, -1, result);
4144 ::pthread_attr_destroy (&attr);
4146 // This is a SunOS or POSIX implementation of pthreads, where we
4147 // assume that ACE_thread_t and ACE_hthread_t are the same. If this
4148 // *isn't* correct on some platform, please let us know.
4149 if (result != -1)
4150 *thr_handle = *thr_id;
4152 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
4153 // SunOS prior to 5.7:
4155 // If the priority is 0, then we might have to set it now because we
4156 // couldn't set it with ::pthread_attr_setschedparam, as noted
4157 // above. This doesn't provide strictly correct behavior, because
4158 // the thread was created (above) with the priority of its parent.
4159 // (That applies regardless of the inherit_sched attribute: if it
4160 // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
4161 // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then "attr"
4162 // was initialized by the SunOS ::pthread_attr_init () to contain
4163 // NULL for the priority, which indicated to SunOS ::pthread_create
4164 // () to inherit the parent priority.)
4165 if (priority == 0)
4167 // Check the priority of this thread, which is the parent
4168 // of the newly created thread. If it is 0, then the
4169 // newly created thread will have inherited the priority
4170 // of 0, so there's no need to explicitly set it.
4171 struct sched_param sparam;
4172 int policy = 0;
4173 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
4174 &policy,
4175 &sparam),
4176 result), int,
4177 -1, result);
4179 // The only policy supported by by SunOS, thru version 5.6,
4180 // is SCHED_OTHER, so that's hard-coded here.
4181 policy = ACE_SCHED_OTHER;
4183 if (sparam.sched_priority != 0)
4185 ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
4186 // The memset to 0 sets the priority to 0, so we don't need
4187 // to explicitly set sparam.sched_priority.
4189 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id,
4190 policy,
4191 &sparam),
4192 result),
4193 int, -1);
4197 # if defined (ACE_NEEDS_LWP_PRIO_SET)
4198 # if 0
4199 // It would be useful if we could make this work. But, it requires
4200 // a mechanism for determining the ID of an LWP to which another
4201 // thread is bound. Is there a way to do that? Instead, just rely
4202 // on the code in ACE_Thread_Adapter::invoke () to set the LWP
4203 // priority.
4205 // If the thread is bound, then set the priority on its LWP.
4206 if (ACE_BIT_ENABLED (flags, THR_BOUND))
4208 ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) ||
4209 ACE_BIT_ENABLED (flags, THR_SCHED_RR) ?
4210 ACE_SCHED_FIFO :
4211 ACE_SCHED_OTHER,
4212 priority);
4213 result = ACE_OS::lwp_setparams (sched_params,
4214 /* ? How do we find the ID of the LWP
4215 to which *thr_id is bound? */);
4217 # endif /* 0 */
4218 # endif /* ACE_NEEDS_LWP_PRIO_SET */
4220 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4221 auto_thread_args.release ();
4222 return result;
4223 # elif defined (ACE_HAS_STHREADS)
4224 int result;
4225 int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
4227 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4228 // If we need to set the priority, then we need to start the
4229 // thread in a suspended mode.
4230 ACE_SET_BITS (flags, THR_SUSPENDED);
4232 ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize,
4233 thread_args->entry_point (),
4234 thread_args,
4235 flags, thr_id), result),
4236 int, -1, result);
4238 if (result != -1)
4240 // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
4241 *thr_handle = *thr_id;
4243 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4245 // Set the priority of the new thread and then let it
4246 // continue, but only if the user didn't start it suspended
4247 // in the first place!
4248 result = ACE_OS::thr_setprio (*thr_id, priority);
4249 if (result != 0)
4251 errno = result;
4252 return -1;
4255 if (start_suspended == 0)
4257 result = ACE_OS::thr_continue (*thr_id);
4258 if (result != 0)
4260 errno = result;
4261 return -1;
4266 auto_thread_args.release ();
4267 return result;
4268 # elif defined (ACE_HAS_WTHREADS)
4269 ACE_UNUSED_ARG (thr_name);
4270 ACE_UNUSED_ARG (stack);
4271 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4272 if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
4274 CWinThread *cwin_thread =
4275 ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
4276 thread_args,
4277 priority,
4279 flags | THR_SUSPENDED);
4280 // Have to duplicate the handle because
4281 // CWinThread::~CWinThread() closes the original handle.
4282 # if !defined (ACE_HAS_WINCE)
4283 (void) ::DuplicateHandle (::GetCurrentProcess (),
4284 cwin_thread->m_hThread,
4285 ::GetCurrentProcess (),
4286 thr_handle,
4288 TRUE,
4289 DUPLICATE_SAME_ACCESS);
4290 # endif /* ! ACE_HAS_WINCE */
4291 *thr_id = cwin_thread->m_nThreadID;
4293 if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
4294 cwin_thread->ResumeThread ();
4295 // cwin_thread will be deleted in AfxThreadExit()
4296 // Warning: If AfxThreadExit() is called from within the
4297 // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
4299 else
4300 # endif /* ACE_HAS_MFC */
4302 int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
4304 if (priority != ACE_DEFAULT_THREAD_PRIORITY)
4305 // If we need to set the priority, then we need to start the
4306 // thread in a suspended mode.
4307 ACE_SET_BITS (flags, THR_SUSPENDED);
4309 *thr_handle = (void *) ACE_BEGINTHREADEX (0,
4310 static_cast <u_int> (stacksize),
4311 thread_args->entry_point (),
4312 thread_args,
4313 flags,
4314 thr_id);
4316 if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
4318 // Set the priority of the new thread and then let it
4319 // continue, but only if the user didn't start it suspended
4320 // in the first place!
4321 ACE_OS::thr_setprio (*thr_handle, priority);
4323 if (start_suspended == 0)
4324 ACE_OS::thr_continue (*thr_handle);
4327 # if 0
4328 *thr_handle = ::CreateThread
4330 stacksize,
4331 LPTHREAD_START_ROUTINE (thread_args->entry_point ()),
4332 thread_args,
4333 flags,
4334 thr_id);
4335 # endif /* 0 */
4337 // Close down the handle if no one wants to use it.
4338 if (thr_handle == &tmp_handle && tmp_handle != 0)
4339 ::CloseHandle (tmp_handle);
4341 if (*thr_handle != 0)
4343 auto_thread_args.release ();
4344 return 0;
4346 else
4347 ACE_FAIL_RETURN (-1);
4348 /* NOTREACHED */
4350 # elif defined (ACE_VXWORKS)
4351 // The hard-coded values below are what ::sp () would use. (::sp ()
4352 // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
4353 // 20,000.) stacksize should be an even integer. If a stack is not
4354 // specified, ::taskSpawn () is used so that we can set the
4355 // priority, flags, and stacksize. If a stack is specified,
4356 // ::taskInit ()/::taskActivate() are used.
4358 // If called with thr_create() defaults, use same default values as ::sp ():
4359 if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
4360 // Assumes that there is a floating point coprocessor. As noted
4361 // above, ::sp () hardcodes this, so we should be safe with it.
4362 if (flags == 0) flags = VX_FP_TASK;
4363 if (stacksize == 0) stacksize = 20000;
4365 ACE_thread_t tid;
4366 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4367 if (stack == 0)
4369 # else
4370 ACE_UNUSED_ARG (stack);
4371 # endif /* 0 */
4372 // The call below to ::taskSpawn () causes VxWorks to assign a
4373 // unique task name of the form: "t" + an integer, because the
4374 // first argument is 0.
4375 tid = ::taskSpawn (thr_name && *thr_name ? const_cast <char*> (*thr_name) : 0,
4376 priority,
4377 (int) flags,
4378 (int) stacksize,
4379 thread_args->entry_point (),
4380 (int) thread_args,
4381 0, 0, 0, 0, 0, 0, 0, 0, 0);
4382 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4384 else
4386 // If a task name (thr_id) was not supplied, then the task will
4387 // not have a unique name. That's VxWorks' behavior.
4389 // Carve out a TCB at the beginning of the stack space. The TCB
4390 // occupies 400 bytes with VxWorks 5.3.1/I386.
4391 WIND_TCB *tcb = (WIND_TCB *) stack;
4393 // The TID is defined to be the address of the TCB.
4394 int status = ::taskInit (tcb,
4395 thr_name && *thr_name ? const_cast <char*>(*thr_name) : 0,
4396 priority,
4397 (int) flags,
4398 (char *) stack + sizeof (WIND_TCB),
4399 (int) (stacksize - sizeof (WIND_TCB)),
4400 thread_args->entry_point (),
4401 (int) thread_args,
4402 0, 0, 0, 0, 0, 0, 0, 0, 0);
4404 if (status == OK)
4406 // The task was successfully initialized, now activate it.
4407 status = ::taskActivate ((ACE_hthread_t) tcb);
4410 tid = status == OK ? (ACE_thread_t) tcb : ERROR;
4412 # endif /* 0 */
4414 if (tid == ERROR)
4415 return -1;
4416 else
4418 if (thr_id)
4419 *thr_id = tid;
4421 if (thr_handle)
4422 *thr_handle = tid;
4424 if (thr_name && !(*thr_name))
4425 *thr_name = ::taskName (tid);
4427 auto_thread_args.release ();
4428 return 0;
4431 # endif /* ACE_HAS_STHREADS */
4432 #else
4433 ACE_UNUSED_ARG (func);
4434 ACE_UNUSED_ARG (args);
4435 ACE_UNUSED_ARG (flags);
4436 ACE_UNUSED_ARG (thr_id);
4437 ACE_UNUSED_ARG (thr_handle);
4438 ACE_UNUSED_ARG (priority);
4439 ACE_UNUSED_ARG (stack);
4440 ACE_UNUSED_ARG (stacksize);
4441 ACE_UNUSED_ARG (thr_name);
4442 ACE_NOTSUP_RETURN (-1);
4443 #endif /* ACE_HAS_THREADS */
4446 void
4447 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
4449 ACE_OS_TRACE ("ACE_OS::thr_exit");
4450 #if defined (ACE_HAS_THREADS)
4451 # if defined (ACE_HAS_PTHREADS)
4452 ::pthread_exit (status);
4453 # elif defined (ACE_HAS_STHREADS)
4454 ::thr_exit (status);
4455 # elif defined (ACE_HAS_WTHREADS)
4456 // Can't call it here because on NT, the thread is exited
4457 // directly by ACE_Thread_Adapter::invoke ().
4458 // ACE_TSS_Cleanup::instance ()->thread_exit (status);
4460 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4461 int using_afx = -1;
4462 // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
4463 // But without #including ace/Thread_Manager.h, we don't know that.
4464 ACE_OS_Thread_Descriptor *td =
4465 ACE_Base_Thread_Adapter::thr_desc_log_msg ();
4466 if (td)
4467 using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
4468 # endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
4470 // Call TSS destructors.
4471 ACE_OS::cleanup_tss (0 /* not main thread */);
4473 // Exit the thread.
4474 // Allow CWinThread-destructor to be invoked from AfxEndThread.
4475 // _endthreadex will be called from AfxEndThread so don't exit the
4476 // thread now if we are running an MFC thread.
4477 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4478 if (using_afx != -1)
4480 if (using_afx)
4481 ::AfxEndThread (status);
4482 else
4483 ACE_ENDTHREADEX (status);
4485 else
4487 // Not spawned by ACE_Thread_Manager, use the old buggy
4488 // version. You should seriously consider using
4489 // ACE_Thread_Manager to spawn threads. The following code is
4490 // know to cause some problem.
4491 CWinThread *pThread = ::AfxGetThread ();
4492 if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
4493 ACE_ENDTHREADEX (status);
4494 else
4495 ::AfxEndThread (status);
4497 # else
4498 ACE_ENDTHREADEX (status);
4499 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
4501 # elif defined (ACE_HAS_VXTHREADS)
4502 ACE_thread_t tid = ACE_OS::thr_self ();
4503 *((int *) status) = ::taskDelete (tid);
4504 # endif /* ACE_HAS_PTHREADS */
4505 #else
4506 ACE_UNUSED_ARG (status);
4507 #endif /* ACE_HAS_THREADS */
4510 #if defined (ACE_HAS_VXTHREADS)
4511 // Leave this in the global scope to allow
4512 // users to adjust the delay value.
4513 int ACE_THR_JOIN_DELAY = 5;
4516 ACE_OS::thr_join (ACE_hthread_t thr_handle,
4517 ACE_THR_FUNC_RETURN *status)
4519 // We can't get the status of the thread
4520 if (status != 0)
4522 *status = 0;
4525 // This method can not support joining all threads
4526 if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
4528 ACE_NOTSUP_RETURN (-1);
4531 int retval = ESRCH;
4532 ACE_thread_t current = ACE_OS::thr_self ();
4534 // Make sure we are not joining ourself
4535 if (ACE_OS::thr_cmp (thr_handle, current))
4537 retval = EDEADLK;
4539 else
4541 // Whether the task exists or not
4542 // we will return a successful value
4543 retval = 0;
4545 // Verify that the task id still exists
4546 while (taskIdVerify (thr_handle) == OK)
4548 // Wait a bit to see if the task is still active.
4549 ACE_OS::sleep (ACE_THR_JOIN_DELAY);
4553 // Adapt the return value into errno and return value.
4554 // The ACE_ADAPT_RETVAL macro doesn't exactly do what
4555 // we need to do here, so we do it manually.
4556 if (retval != 0)
4558 errno = retval;
4559 retval = -1;
4562 return retval;
4566 ACE_OS::thr_join (ACE_thread_t waiter_id,
4567 ACE_thread_t *thr_id,
4568 ACE_THR_FUNC_RETURN *status)
4570 thr_id = 0;
4571 return ACE_OS::thr_join (waiter_id, status);
4573 #endif /* ACE_HAS_VXTHREADS */
4576 ACE_OS::thr_key_detach (ACE_thread_key_t key, void *)
4578 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
4579 TSS_Cleanup_Instance cleanup;
4580 if (cleanup.valid ())
4582 return cleanup->thread_detach_key (key);
4584 else
4586 return -1;
4588 #else
4589 ACE_UNUSED_ARG (key);
4590 ACE_NOTSUP_RETURN (-1);
4591 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
4595 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id,
4596 size_t cpu_set_size,
4597 cpu_set_t * cpu_mask)
4599 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
4600 // Handle of the thread, which is NPTL thread-id, normally a big number
4601 if (::pthread_getaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4603 return -1;
4605 return 0;
4606 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
4607 // The process-id is expected as <thr_id>, which can be a thread-id of
4608 // linux-thread, thus making binding to cpu of that particular thread only.
4609 // If you are using this flag for NPTL-threads, however, please pass as a
4610 // thr_id process id obtained by ACE_OS::getpid ()
4611 ACE_UNUSED_ARG (cpu_set_size);
4612 if (::sched_getaffinity(thr_id, cpu_mask) == -1)
4614 return -1;
4616 return 0;
4617 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
4618 // The process-id is expected as <thr_id>, which can be a thread-id of
4619 // linux-thread, thus making binding to cpu of that particular thread only.
4620 // If you are using this flag for NPTL-threads, however, please pass as a
4621 // thr_id process id obtained by ACE_OS::getpid ()
4622 if (::sched_getaffinity(thr_id, cpu_set_size, cpu_mask) == -1)
4624 return -1;
4626 return 0;
4627 #else
4628 ACE_UNUSED_ARG (thr_id);
4629 ACE_UNUSED_ARG (cpu_set_size);
4630 ACE_UNUSED_ARG (cpu_mask);
4631 ACE_NOTSUP_RETURN (-1);
4632 #endif
4636 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id,
4637 size_t cpu_set_size,
4638 const cpu_set_t * cpu_mask)
4640 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
4641 if (::pthread_setaffinity_np (thr_id, cpu_set_size, cpu_mask) != 0)
4643 return -1;
4645 return 0;
4646 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
4647 // The process-id is expected as <thr_id>, which can be a thread-id of
4648 // linux-thread, thus making binding to cpu of that particular thread only.
4649 // If you are using this flag for NPTL-threads, however, please pass as a
4650 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4652 ACE_UNUSED_ARG (cpu_set_size);
4653 if (::sched_setaffinity (thr_id, cpu_mask) == -1)
4655 return -1;
4657 return 0;
4658 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
4659 // The process-id is expected as <thr_id>, which can be a thread-id of
4660 // linux-thread, thus making binding to cpu of that particular thread only.
4661 // If you are using this flag for NPTL-threads, however, please pass as a
4662 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4664 if (::sched_setaffinity (thr_id, cpu_set_size, cpu_mask) == -1)
4666 return -1;
4668 return 0;
4669 #else
4670 ACE_UNUSED_ARG (thr_id);
4671 ACE_UNUSED_ARG (cpu_set_size);
4672 ACE_UNUSED_ARG (cpu_mask);
4673 ACE_NOTSUP_RETURN (-1);
4674 #endif
4678 ACE_OS::thr_key_used (ACE_thread_key_t key)
4680 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
4681 TSS_Cleanup_Instance cleanup;
4682 if (cleanup.valid ())
4684 cleanup->thread_use_key (key);
4685 return 0;
4687 return -1;
4688 #else
4689 ACE_UNUSED_ARG (key);
4690 ACE_NOTSUP_RETURN (-1);
4691 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
4694 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4696 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t *key,
4697 # if defined (ACE_HAS_THR_C_DEST)
4698 ACE_THR_C_DEST dest
4699 # else
4700 ACE_THR_DEST dest
4701 # endif /* ACE_HAS_THR_C_DEST */
4704 // can't trace here. Trace uses TSS
4705 // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
4706 # if defined (ACE_HAS_THREADS)
4707 # if defined (ACE_HAS_PTHREADS)
4708 int result;
4709 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
4710 result),
4711 int, -1);
4712 # elif defined (ACE_HAS_STHREADS)
4713 int result;
4714 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
4715 result),
4716 int, -1);
4717 # elif defined (ACE_HAS_WTHREADS)
4718 ACE_UNUSED_ARG (dest);
4719 *key = ::TlsAlloc ();
4721 if (*key == ACE_SYSCALL_FAILED)
4722 ACE_FAIL_RETURN (-1);
4723 return 0;
4724 # endif /* ACE_HAS_STHREADS */
4725 # else
4726 ACE_UNUSED_ARG (key);
4727 ACE_UNUSED_ARG (dest);
4728 ACE_NOTSUP_RETURN (-1);
4729 # endif /* ACE_HAS_THREADS */
4731 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4734 ACE_OS::thr_keycreate (ACE_thread_key_t *key,
4735 # if defined (ACE_HAS_THR_C_DEST)
4736 ACE_THR_C_DEST dest,
4737 # else
4738 ACE_THR_DEST dest,
4739 # endif /* ACE_HAS_THR_C_DEST */
4740 void *)
4742 // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
4743 #if defined (ACE_HAS_THREADS)
4744 # if defined (ACE_HAS_TSS_EMULATION)
4745 if (ACE_TSS_Emulation::next_key (*key) == 0)
4747 ACE_TSS_Emulation::tss_destructor (*key, dest);
4749 // Extract out the thread-specific table instance and stash away
4750 // the key and destructor so that we can free it up later on...
4751 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4752 if (cleanup.valid ())
4754 return cleanup->insert (*key, dest);
4756 else
4758 return -1;
4761 else
4762 return -1;
4763 # elif defined (ACE_HAS_WTHREADS)
4764 if (ACE_OS::thr_keycreate_native (key, dest) == 0)
4766 // Extract out the thread-specific table instance and stash away
4767 // the key and destructor so that we can free it up later on...
4768 TSS_Cleanup_Instance cleanup (TSS_Cleanup_Instance::CREATE);
4769 if (cleanup.valid ())
4771 return cleanup->insert (*key, dest);
4773 else
4775 return -1;
4778 else
4779 return -1;
4780 /* NOTREACHED */
4781 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4782 return ACE_OS::thr_keycreate_native (key, dest);
4783 # else
4784 ACE_UNUSED_ARG (key);
4785 ACE_UNUSED_ARG (dest);
4786 ACE_NOTSUP_RETURN (-1);
4787 # endif /* ACE_HAS_TSS_EMULATION */
4788 # else /* ACE_HAS_THREADS */
4789 ACE_UNUSED_ARG (key);
4790 ACE_UNUSED_ARG (dest);
4791 ACE_NOTSUP_RETURN (-1);
4792 # endif /* ACE_HAS_THREADS */
4795 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4797 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key)
4799 ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
4800 # if defined (ACE_HAS_THREADS)
4801 # if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
4802 // For some systems, e.g. LynxOS, we need to ensure that
4803 // any registered thread destructor action for this slot
4804 // is now disabled. Otherwise in the event of a dynamic library
4805 // unload of libACE, by a program not linked with libACE,
4806 // ACE_TSS_cleanup will be invoked again at the thread exit
4807 // after libACE has been actually been unmapped from memory.
4808 (void) ACE_OS::thr_setspecific (key, 0);
4809 # endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
4810 # if defined (ACE_HAS_PTHREADS)
4811 return ::pthread_key_delete (key);
4812 # elif defined (ACE_HAS_THR_KEYDELETE)
4813 return ::thr_keydelete (key);
4814 # elif defined (ACE_HAS_STHREADS)
4815 ACE_UNUSED_ARG (key);
4816 ACE_NOTSUP_RETURN (-1);
4817 # elif defined (ACE_HAS_WTHREADS)
4818 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
4819 # else
4820 ACE_UNUSED_ARG (key);
4821 ACE_NOTSUP_RETURN (-1);
4822 # endif /* ACE_HAS_PTHREADS */
4823 # else
4824 ACE_UNUSED_ARG (key);
4825 ACE_NOTSUP_RETURN (-1);
4826 # endif /* ACE_HAS_THREADS */
4828 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4831 ACE_OS::thr_keyfree (ACE_thread_key_t key)
4833 ACE_OS_TRACE ("ACE_OS::thr_keyfree");
4834 # if defined (ACE_HAS_THREADS)
4835 # if defined (ACE_HAS_TSS_EMULATION)
4836 // Release the key in the TSS_Emulation administration
4837 ACE_TSS_Emulation::release_key (key);
4838 TSS_Cleanup_Instance cleanup;
4839 if (cleanup.valid ())
4841 return cleanup->free_key (key);
4843 return -1;
4844 # elif defined (ACE_HAS_WTHREADS)
4845 // Extract out the thread-specific table instance and free up
4846 // the key and destructor.
4847 TSS_Cleanup_Instance cleanup;
4848 if (cleanup.valid ())
4850 return cleanup->free_key (key);
4852 return -1;
4853 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4854 return ACE_OS::thr_keyfree_native (key);
4855 # else
4856 ACE_UNUSED_ARG (key);
4857 ACE_NOTSUP_RETURN (-1);
4858 # endif /* ACE_HAS_TSS_EMULATION */
4859 # else /* ACE_HAS_THREADS */
4860 ACE_UNUSED_ARG (key);
4861 ACE_NOTSUP_RETURN (-1);
4862 return 0;
4863 # endif /* ACE_HAS_THREADS */
4867 ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
4869 // Set the thread priority on the current thread.
4870 ACE_hthread_t my_thread_id;
4871 ACE_OS::thr_self (my_thread_id);
4873 int const status = ACE_OS::thr_setprio (my_thread_id, prio);
4875 #if defined (ACE_NEEDS_LWP_PRIO_SET)
4876 // If the thread is in the RT class, then set the priority on its
4877 // LWP. (Instead of doing this if the thread is in the RT class, it
4878 // should be done for all bound threads. But, there doesn't appear
4879 // to be an easy way to determine if the thread is bound.)
4881 if (status == 0)
4883 // Find what scheduling class the thread's LWP is in.
4884 ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0);
4885 if (ACE_OS::lwp_getparams (sched_params) == -1)
4887 return -1;
4889 else if (sched_params.policy () == ACE_SCHED_FIFO ||
4890 sched_params.policy () == ACE_SCHED_RR)
4892 // This thread's LWP is in the RT class, so we need to set
4893 // its priority.
4894 sched_params.priority (prio);
4895 return ACE_OS::lwp_setparams (sched_params);
4897 // else this is not an RT thread. Nothing more needs to be
4898 // done.
4900 #endif /* ACE_NEEDS_LWP_PRIO_SET */
4902 return status;
4905 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4907 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key, void *data)
4909 // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
4910 # if defined (ACE_HAS_THREADS)
4911 # if defined (ACE_HAS_PTHREADS)
4912 int result;
4913 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key, data),
4914 result),
4915 int, -1);
4916 # elif defined (ACE_HAS_STHREADS)
4917 int result;
4918 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), result), int, -1);
4919 # elif defined (ACE_HAS_WTHREADS)
4920 ::TlsSetValue (key, data);
4921 return 0;
4922 # else /* ACE_HAS_STHREADS */
4923 ACE_UNUSED_ARG (key);
4924 ACE_UNUSED_ARG (data);
4925 ACE_NOTSUP_RETURN (-1);
4926 # endif /* ACE_HAS_STHREADS */
4927 # else
4928 ACE_UNUSED_ARG (key);
4929 ACE_UNUSED_ARG (data);
4930 ACE_NOTSUP_RETURN (-1);
4931 # endif /* ACE_HAS_THREADS */
4933 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4936 ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
4938 // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
4939 #if defined (ACE_HAS_THREADS)
4940 # if defined (ACE_HAS_TSS_EMULATION)
4941 if (ACE_TSS_Emulation::is_key (key) == 0)
4943 errno = EINVAL;
4944 data = 0;
4945 return -1;
4947 else
4949 ACE_TSS_Emulation::ts_object (key) = data;
4950 TSS_Cleanup_Instance cleanup;
4951 if (cleanup.valid ())
4953 cleanup->thread_use_key (key);
4954 // for TSS_Cleanup purposes treat stetting data to zero
4955 // like detaching. This is a consequence of POSIX allowing
4956 // deletion of a "used" key.
4957 if (data == 0)
4959 cleanup->thread_detach_key (key);
4961 return 0;
4963 else
4965 return -1;
4968 # elif defined (ACE_HAS_WTHREADS)
4969 if (ACE_OS::thr_setspecific_native (key, data) == 0)
4971 TSS_Cleanup_Instance cleanup;
4972 if (cleanup.valid ())
4974 cleanup->thread_use_key (key);
4975 // for TSS_Cleanup purposes treat stetting data to zero
4976 // like detaching. This is a consequence of POSIX allowing
4977 // deletion of a "used" key.
4978 if (data == 0)
4980 cleanup->thread_detach_key (key);
4982 return 0;
4984 return -1;
4986 return -1;
4987 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4988 return ACE_OS::thr_setspecific_native (key, data);
4989 # else /* ACE_HAS_TSS_EMULATION */
4990 ACE_UNUSED_ARG (key);
4991 ACE_UNUSED_ARG (data);
4992 ACE_NOTSUP_RETURN (-1);
4993 # endif /* ACE_HAS_TSS_EMULATION */
4994 # else /* ACE_HAS_THREADS */
4995 ACE_UNUSED_ARG (key);
4996 ACE_UNUSED_ARG (data);
4997 ACE_NOTSUP_RETURN (-1);
4998 # endif /* ACE_HAS_THREADS */
5001 void
5002 ACE_OS::unique_name (const void *object,
5003 char *name,
5004 size_t length)
5006 // The process ID will provide uniqueness between processes on the
5007 // same machine. The "this" pointer of the <object> will provide
5008 // uniqueness between other "live" objects in the same process. The
5009 // uniqueness of this name is therefore only valid for the life of
5010 // <object>.
5011 char temp_name[ACE_UNIQUE_NAME_LEN];
5012 ACE_OS::sprintf (temp_name,
5013 "%p%d",
5014 object,
5015 static_cast <int> (ACE_OS::getpid ()));
5016 ACE_OS::strsncpy (name,
5017 temp_name,
5018 length);
5021 #if defined (ACE_USES_WCHAR)
5022 void
5023 ACE_OS::unique_name (const void *object,
5024 wchar_t *name,
5025 size_t length)
5027 // The process ID will provide uniqueness between processes on the
5028 // same machine. The "this" pointer of the <object> will provide
5029 // uniqueness between other "live" objects in the same process. The
5030 // uniqueness of this name is therefore only valid for the life of
5031 // <object>.
5032 wchar_t temp_name[ACE_UNIQUE_NAME_LEN];
5033 ACE_OS::sprintf (temp_name,
5034 ACE_TEXT ("%p%d"),
5035 object,
5036 static_cast <int> (ACE_OS::getpid ()));
5037 ACE_OS::strsncpy (name,
5038 temp_name,
5039 length);
5041 #endif
5043 ACE_END_VERSIONED_NAMESPACE_DECL
5045 #if defined (ACE_VXWORKS) && !defined (__RTP__)
5046 # include /**/ <usrLib.h> /* for ::sp() */
5047 # include /**/ <sysLib.h> /* for ::sysClkRateGet() */
5048 # include "ace/Service_Config.h"
5050 // This global function can be used from the VxWorks shell to pass
5051 // arguments to a C main () function.
5053 // usage: -> spa main, "arg1", "arg2"
5055 // All arguments must be quoted, even numbers.
5057 spa (FUNCPTR entry, ...)
5059 static const unsigned int ACE_MAX_ARGS = 10;
5060 static char *argv[ACE_MAX_ARGS];
5061 va_list pvar;
5062 unsigned int argc;
5064 // Hardcode a program name because the real one isn't available
5065 // through the VxWorks shell.
5066 argv[0] = "ace_main";
5068 // Peel off arguments to spa () and put into argv. va_arg () isn't
5069 // necessarily supposed to return 0 when done, though since the
5070 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5071 // the unused ones. This function could be used to increase that
5072 // limit, but then it couldn't depend on the trailing 0. So, the
5073 // number of arguments would have to be passed.
5074 va_start (pvar, entry);
5076 for (argc = 1; argc <= ACE_MAX_ARGS; ++argc)
5078 argv[argc] = va_arg (pvar, char *);
5080 if (argv[argc] == 0)
5081 break;
5084 if (argc > ACE_MAX_ARGS && argv[argc-1] != 0)
5086 // try to read another arg, and warn user if the limit was exceeded
5087 if (va_arg (pvar, char *) != 0)
5088 ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %d\n",
5089 ACE_MAX_ARGS);
5091 else
5093 // fill unused argv slots with 0 to get rid of leftovers
5094 // from previous invocations
5095 for (unsigned int i = argc; i <= ACE_MAX_ARGS; ++i)
5096 argv[i] = 0;
5099 // The hard-coded options are what ::sp () uses, except for the
5100 // larger stack size (instead of ::sp ()'s 20000).
5101 int const ret = ::taskSpawn (argv[0], // task name
5102 100, // task priority
5103 VX_FP_TASK, // task options
5104 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
5105 entry, // entry point
5106 argc, // first argument to main ()
5107 (int) argv, // second argument to main ()
5108 0, 0, 0, 0, 0, 0, 0, 0);
5109 va_end (pvar);
5111 // ::taskSpawn () returns the taskID on success: return 0 instead if
5112 // successful
5113 return ret > 0 ? 0 : ret;
5116 // A helper function for the extended spa functions
5117 static void
5118 add_to_argv (int& argc, char** argv, int max_args, char* string)
5120 char indouble = 0;
5121 size_t previous = 0;
5122 size_t length = ACE_OS::strlen (string);
5124 // We use <= to make sure that we get the last argument
5125 for (size_t i = 0; i <= length; i++)
5127 // Is it a double quote that hasn't been escaped?
5128 if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
5130 indouble ^= 1;
5131 if (indouble)
5133 // We have just entered a double quoted string, so
5134 // save the starting position of the contents.
5135 previous = i + 1;
5137 else
5139 // We have just left a double quoted string, so
5140 // zero out the ending double quote.
5141 string[i] = '\0';
5144 else if (string[i] == '\\') // Escape the next character
5146 // The next character is automatically
5147 // skipped because of the strcpy
5148 ACE_OS::strcpy (string + i, string + i + 1);
5149 length--;
5151 else if (!indouble &&
5152 (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
5154 string[i] = '\0';
5155 if (argc < max_args)
5157 argv[argc] = string + previous;
5158 argc++;
5160 else
5162 ACE_OS::fprintf (stderr, "spae(): number of arguments "
5163 "limited to %d\n", max_args);
5166 // Skip over whitespace in between arguments
5167 for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
5171 // Save the starting point for the next time around
5172 previous = i;
5174 // Make sure we don't skip over a character due
5175 // to the above loop to skip over whitespace
5176 i--;
5181 // This global function can be used from the VxWorks shell to pass
5182 // arguments to a C main () function.
5184 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
5186 // All arguments must be within double quotes, even numbers.
5188 spae (FUNCPTR entry, ...)
5190 static int const WINDSH_ARGS = 10;
5191 static int const ACE_MAX_ARGS = 128;
5192 static char* argv[ACE_MAX_ARGS] = { "ace_main", 0 };
5193 va_list pvar;
5194 int argc = 1;
5196 // Peel off arguments to spa () and put into argv. va_arg () isn't
5197 // necessarily supposed to return 0 when done, though since the
5198 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5199 // the unused ones.
5200 va_start (pvar, entry);
5202 int i = 0;
5203 for (char* str = va_arg (pvar, char*);
5204 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
5206 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
5209 // fill unused argv slots with 0 to get rid of leftovers
5210 // from previous invocations
5211 for (i = argc; i < ACE_MAX_ARGS; ++i)
5212 argv[i] = 0;
5214 // The hard-coded options are what ::sp () uses, except for the
5215 // larger stack size (instead of ::sp ()'s 20000).
5216 int const ret = ::taskSpawn (argv[0], // task name
5217 100, // task priority
5218 VX_FP_TASK, // task options
5219 ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
5220 entry, // entry point
5221 argc, // first argument to main ()
5222 (int) argv, // second argument to main ()
5223 0, 0, 0, 0, 0, 0, 0, 0);
5224 va_end (pvar);
5226 // ::taskSpawn () returns the taskID on success: return 0 instead if
5227 // successful
5228 return ret > 0 ? 0 : ret;
5231 // This global function can be used from the VxWorks shell to pass
5232 // arguments to a C main () function. The function will be run
5233 // within the shells task.
5235 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
5237 // All arguments must be within double quotes, even numbers.
5238 // Unlike the spae function, this fuction executes the supplied
5239 // routine in the foreground, rather than spawning it in a separate
5240 // task.
5242 spaef (FUNCPTR entry, ...)
5244 static int const WINDSH_ARGS = 10;
5245 static int const ACE_MAX_ARGS = 128;
5246 static char* argv[ACE_MAX_ARGS] = { "ace_main", 0 };
5247 va_list pvar;
5248 int argc = 1;
5250 // Peel off arguments to spa () and put into argv. va_arg () isn't
5251 // necessarily supposed to return 0 when done, though since the
5252 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5253 // the unused ones.
5254 va_start (pvar, entry);
5256 int i = 0;
5257 for (char* str = va_arg (pvar, char*);
5258 str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
5260 add_to_argv(argc, argv, ACE_MAX_ARGS, str);
5263 // fill unused argv slots with 0 to get rid of leftovers
5264 // from previous invocations
5265 for (i = argc; i < ACE_MAX_ARGS; ++i)
5266 argv[i] = 0;
5268 int ret = entry (argc, argv);
5270 va_end (pvar);
5272 // Return the return value of the invoked ace_main routine.
5273 return ret;
5276 // This global function can be used from the VxWorks shell to pass
5277 // arguments to and run a main () function (i.e. ace_main).
5279 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
5281 // All arguments must be within double quotes, even numbers.
5282 // This routine spawns the main () function in a separate task and waits till the
5283 // task has finished.
5284 static int _vx_call_rc = 0;
5286 static int
5287 _vx_call_entry(FUNCPTR entry, int argc, char* argv[])
5289 ACE_Service_Config::current (ACE_Service_Config::global());
5290 _vx_call_rc = entry (argc, argv);
5291 return _vx_call_rc;
5295 vx_execae (FUNCPTR entry, char* arg, int prio, int opt, int stacksz, ...)
5297 static int const ACE_MAX_ARGS = 128;
5298 static char* argv[ACE_MAX_ARGS] = { "ace_main", 0 };
5299 int argc = 1;
5301 // Peel off arguments to run_main () and put into argv.
5303 if (arg)
5304 add_to_argv(argc, argv, ACE_MAX_ARGS, arg);
5306 // fill unused argv slots with 0 to get rid of leftovers
5307 // from previous invocations
5308 for (int i = argc; i < ACE_MAX_ARGS; ++i)
5309 argv[i] = 0;
5311 // The hard-coded options are what ::sp () uses, except for the
5312 // larger stack size (instead of ::sp ()'s 20000).
5313 int const ret = ::taskSpawn (argv[0], // task name
5314 prio==0 ? 100 : prio, // task priority
5315 opt==0 ? VX_FP_TASK : opt, // task options
5316 stacksz==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE : stacksz, // stack size
5317 (FUNCPTR)_vx_call_entry, // entrypoint caller
5318 (int)entry, // entry point
5319 argc, // first argument to main ()
5320 (int) argv, // second argument to main ()
5321 0, 0, 0, 0, 0, 0, 0);
5323 if (ret == ERROR)
5324 return 255;
5326 while( ret > 0 && ::taskIdVerify (ret) != ERROR )
5327 ::taskDelay (3 * ::sysClkRateGet ());
5329 // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
5330 // successful
5331 return ret > 0 ? _vx_call_rc : 255;
5333 #endif /* ACE_VXWORKS && !__RTP__ */