1 #include "ace/OS_NS_Thread.h"
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"
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
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
53 ACE_Thread_ID::to_string (char *thr_string
) const
55 char format
[128]; // Converted format string
56 char *fp
= 0; // Current format pointer
58 *fp
++ = '%'; // Copy in the %
60 #if defined (ACE_WIN32)
61 ACE_OS::strcpy (fp
, "u");
62 ACE_OS::sprintf (thr_string
,
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)
72 # endif /* ACE_HAS_THREADS */
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
79 ACE_OS::strcpy (fp
, "u");
80 ACE_OS::sprintf (thr_string
, format
, thread_handle_
);
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
88 ACE_OS::strcpy (fp
, "lu");
89 ACE_OS::sprintf (thr_string
,
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
]
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_
;
117 # if defined (ACE_HAS_THR_C_FUNC)
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
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
134 # endif /* ACE_HAS_THR_C_FUNC */
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.
144 // Double-checked lock . . .
150 if (ACE_OS::thr_keycreate_native (&native_tss_key_
,
151 &ACE_TSS_Emulation_cleanup
) != 0)
154 return 0; // Major problems, this should *never* happen!
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)
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)
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
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
193 void **tss_base_p
= ts_storage
;
196 i
< ACE_TSS_THREAD_KEYS_MAX
;
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)
208 return 0; // This should not happen!
215 return ts_storage
? ts_storage
: old_ts_storage
;
217 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
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
]));
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
)
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
));
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
);
272 key
= ACE_OS::NULL_key
;
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)
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)
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
);
323 # else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
324 tss_base () = ts_storage
;
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
)
336 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
342 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
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
)
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.
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.
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
)
404 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
407 ACE_TSS_Info::ACE_TSS_Info (void)
408 : key_ (ACE_OS::NULL_key
),
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.
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.
440 ACE_TSS_Info::operator != (const ACE_TSS_Info
&info
) const
442 ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
444 return !(*this == info
);
448 ACE_TSS_Info::dump (void)
450 # if defined (ACE_HAS_DUMP)
451 // ACE_OS_TRACE ("ACE_TSS_Info::dump");
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
));
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;
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
);
486 find (key_index
, word
, bit
);
488 if (ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
))
494 ACE_SET_BITS (key_bit_words_
[word
], 1 << bit
);
500 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key
)
502 ACE_KEY_INDEX (key_index
, key
);
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
);
518 ACE_TSS_Keys::is_set (const ACE_thread_key_t key
) const
520 ACE_KEY_INDEX (key_index
, key
);
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
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);
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 (
565 ACE_TSS_Info::Destructor
& destructor
,
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
;
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
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
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
631 TSS_Cleanup_Instance (Purpose purpose
= USE
);
632 ~TSS_Cleanup_Instance();
635 ACE_TSS_Cleanup
* operator ->();
639 ACE_TSS_Cleanup
* operator *();
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_
;
648 ACE_TSS_Cleanup
* ptr_
;
649 unsigned short flags_
;
653 FLAG_VALID_CHECKED
= 2
657 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose
)
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.
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
)
677 instance_
= new ACE_TSS_Cleanup();
682 else if(purpose
== DESTROY
)
688 ACE_SET_BITS(flags_
, FLAG_DELETING
);
689 while (reference_count_
> 0)
695 else // must be normal use
697 ACE_ASSERT(purpose
== USE
);
706 TSS_Cleanup_Instance::~TSS_Cleanup_Instance (void)
708 // Variable to hold the mutex_ to delete outside the scope of the
710 ACE_Thread_Mutex
*del_mutex
= 0;
714 ACE_Guard
<ACE_Thread_Mutex
> guard (*mutex_
);
717 if (ACE_BIT_ENABLED (flags_
, FLAG_DELETING
))
719 ACE_ASSERT(instance_
== 0);
720 ACE_ASSERT(reference_count_
== 0);
727 ACE_ASSERT (reference_count_
> 0);
729 if (reference_count_
== 0 && instance_
== 0)
730 condition_
->signal ();
733 }// end of guard scope
744 TSS_Cleanup_Instance::valid()
746 ACE_SET_BITS(flags_
, FLAG_VALID_CHECKED
);
747 return (this->instance_
!= 0);
751 TSS_Cleanup_Instance::operator *()
753 ACE_ASSERT(ACE_BIT_ENABLED(flags_
, FLAG_VALID_CHECKED
));
758 TSS_Cleanup_Instance::operator ->()
760 ACE_ASSERT(ACE_BIT_ENABLED(flags_
, FLAG_VALID_CHECKED
));
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)
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;
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
) )
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)
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;
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_
;
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;
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_
;
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)
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
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
]);
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)
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
;
925 info
.destructor_
= 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;
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
];
947 if (!info
.key_in_use ())
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
);
963 ACE_TSS_Cleanup::thread_release (
965 ACE_TSS_Info::Destructor
& destructor
,
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_
;
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_
;
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
;
1016 # endif /* ACE_HAS_DUMP */
1020 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys
*& tss_keys
) const
1022 if (this->in_use_
== ACE_OS::NULL_key
)
1024 if (ACE_OS::thr_getspecific (in_use_
,
1025 reinterpret_cast<void **> (&tss_keys
)) == -1)
1028 return false; // This should not happen!
1030 return tss_keys
!= 0;
1034 ACE_TSS_Cleanup::tss_keys ()
1036 if (this->in_use_
== ACE_OS::NULL_key
)
1038 ACE_TSS_CLEANUP_GUARD
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
))
1047 return 0; // Major problems, this should *never* happen!
1053 if (ACE_OS::thr_getspecific (in_use_
, &ts_keys
) == -1)
1056 return 0; // This should not happen!
1061 ACE_NEW_RETURN (ts_keys
,
1064 // Store the dynamically allocated pointer in thread-specific
1066 if (ACE_OS::thr_setspecific (in_use_
, ts_keys
) == -1)
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
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 /*****************************************************************************/
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 */
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
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 /*****************************************************************************/
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
;
1159 ACE_OS::condattr_destroy (ACE_condattr_t
&)
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;
1185 ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
);
1189 // Wake up all the waiters.
1190 if (ACE_OS::sema_post (&cv
->sema_
, cv
->waiters_
) == -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)
1197 else if (ACE_OS::event_wait (&cv
->waiters_done_
) == -1)
1198 # endif /* ACE_VXWORKS */
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;
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_
);
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
)
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
)
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)
1255 cv
->was_broadcast_
= 0;
1258 if (ACE_OS::sema_init (&cv
->sema_
, 0, type
, name
, arg
) == -1)
1260 else if (ACE_OS::thread_mutex_init (&cv
->waiters_lock_
) == -1)
1262 # if defined (ACE_VXWORKS)
1263 else if (ACE_OS::sema_init (&cv
->waiters_done_
, 0, type
) == -1)
1265 else if (ACE_OS::event_init (&cv
->waiters_done_
) == -1)
1266 # endif /* ACE_VXWORKS */
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)
1285 cv
->was_broadcast_
= 0;
1288 if (ACE_OS::sema_init (&cv
->sema_
, 0, type
, name
, arg
) == -1)
1290 else if (ACE_OS::thread_mutex_init (&cv
->waiters_lock_
) == -1)
1292 # if defined (ACE_VXWORKS)
1293 else if (ACE_OS::sema_init (&cv
->waiters_done_
, 0, type
) == -1)
1295 else if (ACE_OS::event_init (&cv
->waiters_done_
) == -1)
1296 # endif /* ACE_VXWORKS */
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_
);
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_
);
1343 ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
);
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
),
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)
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.
1375 int last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1377 // Release the lock so that other collaborating threads can make
1379 ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
);
1382 // Bad things happened, so let's just return below.
1384 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1385 else if (external_mutex
->type_
== USYNC_PROCESS
)
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_
,
1398 // We must always regain the <external_mutex>, even when
1399 // errors occur because that's the guarantee that we give to
1401 ACE_OS::mutex_lock (external_mutex
);
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_
);
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
);
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.
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_
);
1443 ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
);
1446 ACE_Errno_Guard
error (errno
, 0);
1449 if (timeout
->sec () == 0 && timeout
->usec () == 0)
1450 msec_timeout
= 0; // Do a "poll."
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
)
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
1470 result
= ::SignalObjectAndWait (external_mutex
->proc_mutex_
,
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)
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_
,
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_
);
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
)
1520 error
= ::GetLastError ();
1525 # elif defined (ACE_VXWORKS)
1526 if (result
== ERROR
)
1530 case S_objLib_OBJ_TIMEOUT
:
1533 case S_objLib_OBJ_UNAVAILABLE
:
1534 if (msec_timeout
== 0)
1543 # endif /* ACE_WIN32 || VXWORKS */
1544 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1545 if (external_mutex
->type_
== USYNC_PROCESS
)
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_
,
1557 // We must always regain the <external_Mutex>, even when
1558 // errors occur because that's the guarantee that we give to
1560 ACE_OS::mutex_lock (external_mutex
);
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.
1570 // Release the signaler/broadcaster if we're the last waiter.
1571 # if defined (ACE_WIN32)
1572 ACE_OS::event_signal (&cv
->waiters_done_
);
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
);
1582 # endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
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.
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_
);
1606 ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
);
1612 if (timeout
->sec () == 0 && timeout
->usec () == 0)
1613 msec_timeout
= 0; // Do a "poll."
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
)
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)
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_
,
1642 if (result
== -1 && errno
== ETIME
)
1643 result
= WAIT_TIMEOUT
;
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_
);
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
)
1665 error
= ::GetLastError ();
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
);
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_
);
1693 ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
);
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)
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
);
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_
);
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
)
1735 error
= ::GetLastError ();
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...
1751 ACE_NOTSUP_RETURN (-1);
1752 # endif /* ACE_HAS_THREADS */
1754 # endif /* ACE_HAS_WTHREADS */
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
);
1768 #endif /* ACE_LACKS_COND_T */
1770 /*****************************************************************************/
1772 /*****************************************************************************/
1774 /*****************************************************************************/
1776 /*****************************************************************************/
1779 ACE_OS::mutex_init (ACE_mutex_t
*m
,
1782 ACE_mutexattr_t
*attributes
,
1783 LPSECURITY_ATTRIBUTES sa
,
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};
1799 pthread_mutexattr_t l_attributes
;
1802 if (attributes
== 0)
1803 attributes
= &l_attributes
;
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)
1814 attr_init
= 1; // we have initialized these attributes
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
,
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
,
1837 # endif /* ACE_HAS_RECURSIVE_MUTEXES */
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
));
1852 if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m
, attributes
), result
) == 0)
1855 result
= -1; // ACE_ADAPT_RETVAL used it for intermediate status
1858 // Only do the deletions if the <attributes> parameter wasn't
1860 if (attributes
== &l_attributes
&& attr_init
)
1861 ::pthread_mutexattr_destroy (&l_attributes
);
1864 # elif defined (ACE_HAS_STHREADS)
1865 ACE_UNUSED_ARG (name
);
1866 ACE_UNUSED_ARG (sa
);
1867 ACE_UNUSED_ARG (lock_type
);
1869 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m
,
1874 # elif defined (ACE_HAS_WTHREADS)
1875 m
->type_
= lock_scope
;
1877 SECURITY_ATTRIBUTES sa_buffer
;
1878 SECURITY_DESCRIPTOR sd_buffer
;
1882 # if defined (ACE_HAS_WINCE)
1883 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
1885 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1886 (sa
, &sa_buffer
, &sd_buffer
),
1888 ACE_Ascii_To_Wide (name
).wchar_rep ());
1889 # else /* ACE_HAS_WINCE */
1891 ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
1892 (sa
, &sa_buffer
, &sd_buffer
),
1895 # endif /* ACE_HAS_WINCE */
1896 if (m
->proc_mutex_
== 0)
1897 ACE_FAIL_RETURN (-1);
1900 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1901 ACE_OS::set_errno_to_last_error ();
1905 return ACE_OS::thread_mutex_init (&m
->thr_mutex_
,
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 */
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)
1941 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m
),
1943 # elif defined (ACE_HAS_STHREADS)
1945 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m
), result
), int, -1);
1946 # elif defined (ACE_HAS_WTHREADS)
1950 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m
->proc_mutex_
),
1954 return ACE_OS::thread_mutex_destroy (&m
->thr_mutex_
);
1960 # elif defined (ACE_VXWORKS)
1961 return ::semDelete (*m
) == OK
? 0 : -1;
1962 # endif /* Threads variety case */
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
,
1973 const wchar_t *name
,
1974 ACE_mutexattr_t
*attributes
,
1975 LPSECURITY_ATTRIBUTES sa
,
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
;
1986 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1987 (sa
, &sa_buffer
, &sd_buffer
),
1990 if (m
->proc_mutex_
== 0)
1991 ACE_FAIL_RETURN (-1);
1995 return ACE_OS::thread_mutex_init (&m
->thr_mutex_
,
2003 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2004 return ACE_OS::mutex_init (m
,
2006 ACE_Wide_To_Ascii (name
).char_rep (),
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.
2022 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m
), result
),
2024 # elif defined (ACE_HAS_STHREADS)
2026 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m
), result
), int, -1);
2027 # elif defined (ACE_HAS_WTHREADS)
2031 switch (::WaitForSingleObject (m
->proc_mutex_
, INFINITE
))
2034 // Timeout can't occur, so don't bother checking...
2037 case WAIT_ABANDONED
:
2038 // We will ignore abandonments in this method
2039 // Note that we still hold the lock
2042 // This is a hack, we need to find an appropriate mapping...
2043 ACE_OS::set_errno_to_last_error ();
2047 return ACE_OS::thread_mutex_lock (&m
->thr_mutex_
);
2053 # elif defined (ACE_VXWORKS)
2054 return ::semTake (*m
, WAIT_FOREVER
) == OK
? 0 : -1;
2055 # endif /* Threads variety case */
2058 ACE_NOTSUP_RETURN (-1);
2059 #endif /* ACE_HAS_THREADS */
2063 ACE_OS::mutex_lock (ACE_mutex_t
*m
,
2066 ACE_OS_TRACE ("ACE_OS::mutex_lock");
2067 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2072 switch (::WaitForSingleObject (m
->proc_mutex_
, INFINITE
))
2075 // Timeout can't occur, so don't bother checking...
2079 case WAIT_ABANDONED
:
2081 return 0; // something goofed, but we hold the lock ...
2083 // This is a hack, we need to find an appropriate mapping...
2084 ACE_OS::set_errno_to_last_error ();
2088 return ACE_OS::thread_mutex_lock (&m
->thr_mutex_
);
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)
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
)
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
2128 ACE_Time_Value
relative_time (timeout
- ACE_OS::gettimeofday ());
2133 switch (::WaitForSingleObject (m
->proc_mutex_
,
2134 relative_time
.msec ()))
2137 case WAIT_ABANDONED
:
2138 // We will ignore abandonments in this method
2139 // Note that we still hold the lock
2145 // This is a hack, we need to find an appropriate mapping...
2146 ACE_OS::set_errno_to_last_error ();
2150 ACE_NOTSUP_RETURN (-1);
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
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
2174 else if (errno
== S_objLib_OBJ_UNAVAILABLE
)
2180 # endif /* ACE_HAS_PTHREADS */
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.
2197 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m
), result
),
2199 # elif defined (ACE_HAS_STHREADS)
2201 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m
), result
), int, -1);
2202 # elif defined (ACE_HAS_WTHREADS)
2207 // Try for 0 milliseconds - i.e. nonblocking.
2208 switch (::WaitForSingleObject (m
->proc_mutex_
, 0))
2212 case WAIT_ABANDONED
:
2213 // We will ignore abandonments in this method. Note that
2214 // we still hold the lock.
2220 ACE_OS::set_errno_to_last_error ();
2225 return ACE_OS::thread_mutex_trylock (&m
->thr_mutex_
);
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
2243 // got the semaphore
2245 # endif /* Threads variety case */
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)
2261 // Try for 0 milliseconds - i.e. nonblocking.
2262 switch (::WaitForSingleObject (m
->proc_mutex_
, 0))
2266 case WAIT_ABANDONED
:
2268 return 0; // something goofed, but we hold the lock ...
2273 ACE_OS::set_errno_to_last_error ();
2278 return ACE_OS::thread_mutex_trylock (&m
->thr_mutex_
);
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.
2299 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m
), result
),
2301 # elif defined (ACE_HAS_STHREADS)
2303 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m
), result
), int, -1);
2304 # elif defined (ACE_HAS_WTHREADS)
2308 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m
->proc_mutex_
),
2312 return ACE_OS::thread_mutex_unlock (&m
->thr_mutex_
);
2318 # elif defined (ACE_VXWORKS)
2319 return ::semGive (*m
) == OK
? 0 : -1;
2320 # endif /* Threads variety case */
2323 ACE_NOTSUP_RETURN (-1);
2324 #endif /* ACE_HAS_THREADS */
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
);
2336 ACE_UNUSED_ARG (mutex
);
2337 # endif /* ACE_HAS_PTHREADS */
2339 ACE_UNUSED_ARG (mutex
);
2340 #endif /* ACE_HAS_THREADS */
2343 /*****************************************************************************/
2345 /*****************************************************************************/
2347 /*****************************************************************************/
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
)
2369 // Only destroy the event data if we're the ones who initialized
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
2379 while ((r1
= ACE_OS::mutex_destroy (&event
->eventdata_
->lock_
)) == -1
2382 ACE_OS::thr_yield ();
2385 r1
= ACE_OS::sema_destroy(&event
->lock_
);
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
2397 event
->eventdata_
->is_signaled_
= 1;
2398 ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
);
2399 ACE_OS::thr_yield ();
2402 r2
= ACE_OS::sema_destroy(&event
->semaphore_
);
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;
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_
);
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)))
2425 return ACE_OS::sema_destroy(&event
->semaphore_
);
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
2441 ACE_OS::thr_yield ();
2444 r1
= ACE_OS::sema_destroy(&event
->lock_
);
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
2456 event
->eventdata_
->is_signaled_
= 1;
2457 ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
);
2458 ACE_OS::thr_yield ();
2461 r2
= ACE_OS::sema_destroy(&event
->semaphore_
);
2463 delete event
->eventdata_
;
2464 return r1
!= 0 || r2
!= 0 ? -1 : 0;
2470 ACE_UNUSED_ARG (event
);
2471 ACE_NOTSUP_RETURN (-1);
2472 #endif /* ACE_WIN32 */
2476 ACE_OS::event_init (ACE_event_t
*event
,
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
),
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
),
2502 # endif /* ACE_HAS_WINCE */
2504 ACE_FAIL_RETURN (-1);
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
];
2520 ACE_OS::strsncpy (&adj_name
[1], name
, MAXPATHLEN
-1);
2529 # endif /* ACE_SHM_OPEN_REQUIRES_ONE_SLASH */
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
),
2540 ACE_DEFAULT_FILE_PERMS
);
2541 if (fd
== ACE_INVALID_HANDLE
) // Still can't get it.
2546 // We own this shared memory object! Let's set its size.
2547 if (ACE_OS::ftruncate (fd
, sizeof (ACE_eventdata_t
)) == -1)
2556 (ACE_eventdata_t
*) ACE_OS::mmap (0,
2557 sizeof (ACE_eventdata_t
),
2563 if (evtdata
== MAP_FAILED
)
2566 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
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
));
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
),
2595 ACE_OS::strncpy (sem_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_
,
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_
,
2613 (ACE_mutexattr_t
*) arg
);
2620 sizeof (lck_name
) - (1 + sizeof ("._ACE_EVTLCK_")));
2621 ACE_OS::strcat (lck_name
, "._ACE_EVTLCK_");
2622 result
= ACE_OS::sema_init (&event
->lock_
,
2628 result
= ACE_OS::sema_post (&event
->lock_
); /* Initially unlock */
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)))
2643 ACE_OS::strncpy (sem_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_
,
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)))
2664 sizeof (lck_name
) - (1 + sizeof ("._ACE_EVTLCK_")));
2665 ACE_OS::strcat (lck_name
, "._ACE_EVTLCK_");
2666 result
= ACE_OS::sema_init (&event
->lock_
,
2678 ACE_NEW_RETURN (evtdata
, ACE_eventdata_t
, -1);
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
),
2696 int result
= ACE_OS::sema_init (&event
->semaphore_
,
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_
,
2710 (ACE_mutexattr_t
*) arg
);
2712 result
= ACE_OS::sema_init (&event
->lock_
,
2718 result
= ACE_OS::sema_post(&event
->lock_
); /* initially unlock */
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)
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)
2751 if (ACE_OS::sema_wait (&event
->lock_
) == 0)
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)
2769 event
->eventdata_
->signal_count_
= event
->eventdata_
->waiting_threads_
;
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;
2781 while(event
->eventdata_
->signal_count_
!=0 && event
->eventdata_
->waiting_threads_
!=0)
2782 ACE_OS::thr_yield ();
2785 // Auto-reset event: wakeup one waiter.
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)
2793 if (ACE_OS::sema_post(&event
->semaphore_
) != 0)
2800 event
->eventdata_
->auto_event_signaled_
= true;
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_
);
2814 ACE_OS::sema_post (&event
->lock_
);
2817 // Reset errno in case mutex_unlock() also fails...
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)
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)
2844 if (ACE_OS::sema_wait (&event
->lock_
) == 0)
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_
);
2858 ACE_OS::sema_post (&event
->lock_
);
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)
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)
2886 if (ACE_OS::sema_wait (&event
->lock_
) == 0)
2889 // Manual-reset event.
2890 if (event
->eventdata_
->manual_reset_
== 1)
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)
2902 if (ACE_OS::sema_post(&event
->semaphore_
) != 0)
2911 event
->eventdata_
->is_signaled_
= 1;
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)
2925 else if (ACE_OS::sema_post(&event
->semaphore_
) != 0)
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_
);
2942 ACE_OS::sema_post (&event
->lock_
);
2946 // Reset errno in case mutex_unlock() also fails...
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
)
2965 // Wait indefinitely.
2966 return ACE_OS::event_wait (event
);
2968 #if defined (ACE_WIN32)
2971 if (timeout
->sec () == 0 && timeout
->usec () == 0)
2973 result
= ::WaitForSingleObject (*event
, 0);
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>.
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
)
2995 msec_timeout
= relative_time
.msec ();
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
);
3012 // This is a hack, we need to find an appropriate mapping...
3013 ACE_OS::set_errno_to_last_error ();
3016 #elif defined (ACE_HAS_THREADS)
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)
3027 if (ACE_OS::sema_wait (&event
->lock_
) == 0)
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;
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)
3067 if (event
->eventdata_
->signal_count_
> 0)
3069 event
->eventdata_
->signal_count_
--;
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)
3077 if (ACE_OS::sema_post (&event
->lock_
) != 0)
3080 event
->eventdata_
->waiting_threads_
--;
3084 if (ACE_OS::sema_wait(&event
->semaphore_
, absolute_timeout
) !=0)
3087 if (errno
== ETIMEDOUT
) // Semaphores time out with ETIMEDOUT (POSIX)
3093 bool signalled
= false;
3094 if (result
== 0 && event
->eventdata_
->signal_count_
> 0)
3096 event
->eventdata_
->signal_count_
--;
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)
3104 if (ACE_OS::sema_wait (&event
->lock_
) != 0)
3107 event
->eventdata_
->waiting_threads_
--; // yes, I know it's not save
3114 if (event
->eventdata_
->manual_reset_
== 1 && event
->eventdata_
->is_signaled_
== 1)
3115 if (ACE_OS::sema_post(&event
->semaphore_
) != 0)
3127 // Reset the auto_event_signaled_ to false now that we have
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_
);
3142 ACE_OS::sema_post (&event
->lock_
);
3146 // Reset errno in case mutex_unlock() also fails...
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
))
3170 ACE_OS::set_errno_to_last_error ();
3174 #elif defined (ACE_HAS_THREADS)
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)
3185 if (ACE_OS::sema_wait (&event
->lock_
) == 0)
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)
3210 // Something went wrong...
3213 if (event
->eventdata_
->signal_count_
> 0)
3215 event
->eventdata_
->signal_count_
--;
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)
3223 if (ACE_OS::sema_post (&event
->lock_
) != 0)
3226 event
->eventdata_
->waiting_threads_
--;
3230 if (ACE_OS::sema_wait (&event
->semaphore_
) !=0)
3236 bool signalled
= false;
3237 if (result
== 0 && event
->eventdata_
->signal_count_
> 0)
3239 event
->eventdata_
->signal_count_
--;
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)
3247 if (ACE_OS::sema_wait (&event
->lock_
) != 0)
3250 event
->eventdata_
->waiting_threads_
--;
3257 if (event
->eventdata_
->manual_reset_
== 1 && event
->eventdata_
->is_signaled_
== 1)
3258 if (ACE_OS::sema_post(&event
->semaphore_
) != 0)
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_
);
3284 ACE_OS::sema_post (&event
->lock_
);
3288 // Reset errno in case mutex_unlock() also fails...
3295 ACE_UNUSED_ARG (event
);
3296 ACE_NOTSUP_RETURN (-1);
3297 #endif /* ACE_WIN32 */
3300 /*****************************************************************************/
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.
3311 if (ACE_OS::scheduling_class ("RT", rt_id
) == -1
3312 || ACE_OS::scheduling_class ("TS", ts_id
) == -1)
3315 // Get this LWP's scheduling parameters.
3317 // The following is just to avoid Purify warnings about unitialized
3319 ACE_OS::memset (&pcparms
, 0, sizeof pcparms
);
3320 pcparms
.pc_cid
= PC_CLNULL
;
3322 if (ACE_OS::priority_control (P_LWPID
,
3325 (char *) &pcparms
) == -1)
3327 else if (pcparms
.pc_cid
== rt_id
)
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
);
3342 else if (pcparms
.pc_cid
== ts_id
)
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
);
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
,
3380 const ACE_TCHAR
*name
,
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
);
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_
,
3398 ACE_UNIQUE_NAME_LEN
);
3399 ACE_OS::unique_name ((const void *) &rw
->waiting_readers_
,
3401 ACE_UNIQUE_NAME_LEN
);
3402 ACE_OS::unique_name ((const void *) &rw
->waiting_writers_
,
3404 ACE_UNIQUE_NAME_LEN
);
3405 ACE_OS::unique_name ((const void *) &rw
->waiting_important_writer_
,
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)
3423 rw
->num_waiting_writers_
= 0;
3424 rw
->num_waiting_readers_
= 0;
3425 rw
->important_writer_
= 0;
3428 ACE_OS::condattr_destroy (attributes
);
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_
);
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
,
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
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 ¶m
) == -1 ? -1 : 0;
3485 # if defined (DIGITAL_UNIX)
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
)
3491 # else /* ! DIGITAL_UNIX */
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 ();
3501 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id
,
3502 sched_params
.policy (),
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
);
3513 else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
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
3524 # if defined (ACE_HAS_PHARLAP_RT)
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());
3535 if (sched_params
.quantum () != ACE_Time_Value::zero
)
3537 // I don't know of a way to set the quantum on Win32.
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 ();
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);
3577 = ::OpenProcess (PROCESS_SET_INFORMATION
,
3579 id
== ACE_SELF
? ::GetCurrentProcessId() : id
);
3582 ACE_OS::set_errno_to_last_error();
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
);
3601 ::CloseHandle (hProcess
);
3603 #endif /* ACE_HAS_PHARLAP_RT */
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
)
3625 // Set the thread priority on the current thread.
3626 return ACE_OS::thr_setprio (sched_params
.priority ());
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.
3640 // The following is just to avoid Purify warnings about unitialized
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 */,
3648 (char *) &pcinfo
) == -1)
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
,
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.
3674 if (ACE_OS::scheduling_class (sched_params
.policy() == ACE_SCHED_OTHER
?
3676 "RT", class_id
) == -1)
3682 // The following is just to avoid Purify warnings about unitialized
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.
3694 // The following is just to avoid Purify warnings about unitialized
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.
3714 // The following is just to avoid Purify warnings about unitialized
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
;
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
);
3741 if (ACE_OS::priority_control ((idtype_t
) (sched_params
.scope () == ACE_SCOPE_THREAD
3743 : sched_params
.scope ()),
3746 (char *) &pcparms
) < 0)
3748 return ACE_OS::last_error ();
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
,
3763 ACE_thread_t
*thr_id
,
3764 ACE_hthread_t
*thr_handle
,
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()),
3795 ACE_NEW_RETURN (thread_args
,
3796 ACE_OS_Thread_Adapter (func
, args
,
3797 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
),
3800 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
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
,
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
;
3823 ACE_hthread_t tmp_handle
;
3824 if (thr_handle
== 0)
3825 thr_handle
= &tmp_handle
;
3827 # if defined (ACE_HAS_PTHREADS)
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};
3836 pthread_attr_t attr
;
3838 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr
), result
) != 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)
3854 result
= ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr
, stack
, size
), result
);
3856 result
= ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr
, size
), result
);
3859 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr
, size
), result
) == -1)
3860 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3862 ::pthread_attr_destroy (&attr
);
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)
3875 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr
, stack
), result
) != 0)
3877 ::pthread_attr_destroy (&attr
);
3882 ACE_UNUSED_ARG (stack
);
3883 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3884 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3886 // *** Deal with various attributes
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
),
3902 ::pthread_attr_destroy (&attr
);
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 */
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
))
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
;
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
))
3951 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_IO
))
3956 # endif /* SCHED_IO */
3960 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3962 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr
, spolicy
),
3966 ::pthread_attr_destroy (&attr
);
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
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
);
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.
4028 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4030 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr
, &sparam
),
4034 ::pthread_attr_destroy (&attr
);
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
);
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
);
4069 ACE_UNUSED_ARG (thr_name
);
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
);
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
);
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
4113 int lwps
= ACE_OS::thr_getconcurrency ();
4116 if (errno
== ENOTSUP
)
4117 // Suppress the ENOTSUP because it's harmless.
4120 // This should never happen on SunOS:
4121 // ::thr_getconcurrency () should always succeed.
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?
4135 # endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */
4138 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id
,
4140 thread_args
->entry_point (),
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.
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.)
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
;
4173 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
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
,
4197 # if defined (ACE_NEEDS_LWP_PRIO_SET)
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
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
) ?
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? */);
4218 # endif /* ACE_NEEDS_LWP_PRIO_SET */
4220 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4221 auto_thread_args
.release ();
4223 # elif defined (ACE_HAS_STHREADS)
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 (),
4235 flags
, thr_id
), result
),
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
);
4255 if (start_suspended
== 0)
4257 result
= ACE_OS::thr_continue (*thr_id
);
4266 auto_thread_args
.release ();
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 (),
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 (),
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 !
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 (),
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
);
4328 *thr_handle
= ::CreateThread
4331 LPTHREAD_START_ROUTINE (thread_args
->entry_point ()),
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 ();
4347 ACE_FAIL_RETURN (-1);
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;
4366 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4370 ACE_UNUSED_ARG (stack
);
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,
4379 thread_args
->entry_point (),
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. */
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,
4398 (char *) stack
+ sizeof (WIND_TCB
),
4399 (int) (stacksize
- sizeof (WIND_TCB
)),
4400 thread_args
->entry_point (),
4402 0, 0, 0, 0, 0, 0, 0, 0, 0);
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
;
4424 if (thr_name
&& !(*thr_name
))
4425 *thr_name
= ::taskName (tid
);
4427 auto_thread_args
.release ();
4431 # endif /* ACE_HAS_STHREADS */
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 */
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)
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 ();
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 */);
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)
4481 ::AfxEndThread (status
);
4483 ACE_ENDTHREADEX (status
);
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
);
4495 ::AfxEndThread (status
);
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 */
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
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);
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
))
4541 // Whether the task exists or not
4542 // we will return a successful value
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.
4566 ACE_OS::thr_join (ACE_thread_t waiter_id
,
4567 ACE_thread_t
*thr_id
,
4568 ACE_THR_FUNC_RETURN
*status
)
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
);
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)
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)
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)
4628 ACE_UNUSED_ARG (thr_id
);
4629 ACE_UNUSED_ARG (cpu_set_size
);
4630 ACE_UNUSED_ARG (cpu_mask
);
4631 ACE_NOTSUP_RETURN (-1);
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)
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)
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)
4670 ACE_UNUSED_ARG (thr_id
);
4671 ACE_UNUSED_ARG (cpu_set_size
);
4672 ACE_UNUSED_ARG (cpu_mask
);
4673 ACE_NOTSUP_RETURN (-1);
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
);
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)
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)
4709 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key
, dest
),
4712 # elif defined (ACE_HAS_STHREADS)
4714 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key
, dest
),
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);
4724 # endif /* ACE_HAS_STHREADS */
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
,
4739 # endif /* ACE_HAS_THR_C_DEST */
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
);
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
);
4781 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4782 return ACE_OS::thr_keycreate_native (key
, dest
);
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);
4820 ACE_UNUSED_ARG (key
);
4821 ACE_NOTSUP_RETURN (-1);
4822 # endif /* ACE_HAS_PTHREADS */
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
);
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
);
4853 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4854 return ACE_OS::thr_keyfree_native (key
);
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);
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.)
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)
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
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
4900 #endif /* ACE_NEEDS_LWP_PRIO_SET */
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)
4913 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key
, data
),
4916 # elif defined (ACE_HAS_STHREADS)
4918 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key
, data
), result
), int, -1);
4919 # elif defined (ACE_HAS_WTHREADS)
4920 ::TlsSetValue (key
, data
);
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 */
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)
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.
4959 cleanup
->thread_detach_key (key
);
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.
4980 cleanup
->thread_detach_key (key
);
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 */
5002 ACE_OS::unique_name (const void *object
,
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
5011 char temp_name
[ACE_UNIQUE_NAME_LEN
];
5012 ACE_OS::sprintf (temp_name
,
5015 static_cast <int> (ACE_OS::getpid ()));
5016 ACE_OS::strsncpy (name
,
5021 #if defined (ACE_USES_WCHAR)
5023 ACE_OS::unique_name (const void *object
,
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
5032 wchar_t temp_name
[ACE_UNIQUE_NAME_LEN
];
5033 ACE_OS::sprintf (temp_name
,
5036 static_cast <int> (ACE_OS::getpid ()));
5037 ACE_OS::strsncpy (name
,
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
];
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)
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",
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
)
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);
5111 // ::taskSpawn () returns the taskID on success: return 0 instead if
5113 return ret
> 0 ? 0 : ret
;
5116 // A helper function for the extended spa functions
5118 add_to_argv (int& argc
, char** argv
, int max_args
, char* string
)
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] != '\\'))
5133 // We have just entered a double quoted string, so
5134 // save the starting position of the contents.
5139 // We have just left a double quoted string, so
5140 // zero out the ending double quote.
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);
5151 else if (!indouble
&&
5152 (ACE_OS::ace_isspace (string
[i
]) || string
[i
] == '\0'))
5155 if (argc
< max_args
)
5157 argv
[argc
] = string
+ previous
;
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
5174 // Make sure we don't skip over a character due
5175 // to the above loop to skip over whitespace
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 };
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
5200 va_start (pvar
, entry
);
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
)
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);
5226 // ::taskSpawn () returns the taskID on success: return 0 instead if
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
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 };
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
5254 va_start (pvar
, entry
);
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
)
5268 int ret
= entry (argc
, argv
);
5272 // Return the return value of the invoked ace_main routine.
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;
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
);
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 };
5301 // Peel off arguments to run_main () and put into argv.
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
)
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);
5326 while( ret
> 0 && ::taskIdVerify (ret
) != ERROR
)
5327 ::taskDelay (3 * ::sysClkRateGet ());
5329 // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
5331 return ret
> 0 ? _vx_call_rc
: 255;
5333 #endif /* ACE_VXWORKS && !__RTP__ */