1 #include "ace/OS_NS_Thread.h"
3 #if !defined (ACE_HAS_INLINED_OSCALLS)
4 # include "ace/OS_NS_Thread.inl"
5 #endif /* ACE_HAS_INLINED_OSCALLS */
7 #include "ace/OS_NS_stdio.h"
8 #include "ace/Sched_Params.h"
9 #include "ace/OS_Memory.h"
10 #include "ace/OS_Thread_Adapter.h"
11 #include "ace/Min_Max.h"
12 #include "ace/Object_Manager_Base.h"
13 #include "ace/OS_NS_errno.h"
14 #include "ace/OS_NS_ctype.h"
15 #include "ace/Log_Category.h" // for ACE_ASSERT
16 #include "ace/Auto_Ptr.h"
17 #include "ace/Thread_Mutex.h"
18 #include "ace/Condition_Thread_Mutex.h"
19 #include "ace/Guard_T.h"
21 # include "ace/OS_NS_sys_resource.h" // syscall for gettid impl
25 ACE_MUTEX_LOCK_CLEANUP_ADAPTER_NAME (void *args
)
27 ACE_VERSIONED_NAMESPACE_NAME::ACE_OS::mutex_lock_cleanup (args
);
30 #if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
31 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
32 (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID)
33 #elif defined (ACE_HAS_WINCE)
34 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
35 CreateThread (0, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & (CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION), (unsigned long *) THR_ID)
36 #elif defined(ACE_HAS_WTHREADS)
37 // Green Hills compiler gets confused when __stdcall is embedded in
38 // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
40 typedef unsigned (__stdcall
*ACE_WIN32THRFUNC_T
)(void*);
41 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
42 ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
43 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
45 /*****************************************************************************/
47 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
50 ACE_Thread_ID::to_string (char *thr_string
, size_t thr_string_len
) const
52 #if defined (ACE_WIN32)
53 ACE_OS::snprintf (thr_string
, thr_string_len
, "%u",
54 static_cast <unsigned> (this->thread_id_
));
56 // Yes, this is an ugly C-style cast, but the correct C++ cast is
57 // different depending on whether the t_id is an integral type or a
58 // pointer type. FreeBSD uses a pointer type, but doesn't have a _np
59 // function to get an integral type like other OSes, so use the
61 ACE_OS::snprintf (thr_string
, thr_string_len
, "%lu",
62 # ifdef ACE_THREAD_T_IS_A_STRUCT
63 *reinterpret_cast<const unsigned long *> (&
66 # endif // ACE_THREAD_T_IS_A_STRUCT
69 #endif /* ACE_WIN32 */
72 /*****************************************************************************/
74 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
76 #if defined (ACE_HAS_TSS_EMULATION)
77 u_int
ACE_TSS_Emulation::total_keys_
= 0;
79 ACE_TSS_Keys
* ACE_TSS_Emulation::tss_keys_used_
= 0;
81 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
82 ACE_TSS_Emulation::tss_destructor_
[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX
]
85 # if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) && defined (ACE_HAS_VXTHREADS)
87 # if (defined (_WRS_CONFIG_SMP) || defined (INCLUDE_AMP_CPU))
88 __thread
void* ACE_TSS_Emulation::ace_tss_keys
= 0;
89 # else /* ! VxWorks SMP */
90 void* ACE_TSS_Emulation::ace_tss_keys
= 0;
91 # endif /* ! VxWorks SMP */
93 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
95 bool ACE_TSS_Emulation::key_created_
= false;
97 ACE_OS_thread_key_t
ACE_TSS_Emulation::native_tss_key_
;
100 # if defined (ACE_HAS_THR_C_FUNC)
103 ACE_TSS_Emulation_cleanup (void *)
105 // Really this must be used for ACE_TSS_Emulation code to make the TSS
110 ACE_TSS_Emulation_cleanup (void *)
112 // Really this must be used for ACE_TSS_Emulation code to make the TSS
115 # endif /* ACE_HAS_THR_C_FUNC */
118 ACE_TSS_Emulation::tss_base (void* ts_storage
[], u_int
*ts_created
)
120 // TSS Singleton implementation.
122 // Create the one native TSS key, if necessary.
125 // Double-checked lock . . .
130 if (ACE_OS::thr_keycreate_native (&native_tss_key_
,
131 &ACE_TSS_Emulation_cleanup
) != 0)
134 return 0; // Major problems, this should *never* happen!
140 void **old_ts_storage
= 0;
142 // Get the tss_storage from thread-OS specific storage.
143 if (ACE_OS::thr_getspecific_native (native_tss_key_
,
144 (void **) &old_ts_storage
) == -1)
147 return 0; // This should not happen!
150 // Check to see if this is the first time in for this thread.
151 // This block can also be entered after a fork () in the child process.
152 if (old_ts_storage
== 0)
157 // Use the ts_storage passed as argument, if non-zero. It is
158 // possible that this has been implemented in the stack. At the
159 // moment, this is unknown. The cleanup must not do nothing.
160 // If ts_storage is zero, allocate (and eventually leak) the
164 #ifdef ACE_HAS_ALLOC_HOOKS
165 const size_t n
= ACE_TSS_THREAD_KEYS_MAX
* sizeof (void *);
166 ACE_Allocator
*const alloc
= ACE_Allocator::instance ();
167 ACE_ALLOCATOR_RETURN (ts_storage
,
168 static_cast<void **> (alloc
->malloc (n
)), 0);
170 ACE_NEW_RETURN (ts_storage
,
171 void*[ACE_TSS_THREAD_KEYS_MAX
],
175 // Zero the entire TSS array. Do it manually instead of
176 // using memset, for optimum speed. Though, memset may be
178 void **tss_base_p
= ts_storage
;
181 i
< ACE_TSS_THREAD_KEYS_MAX
;
186 // Store the pointer in thread-specific storage. It gets
187 // deleted via the ACE_TSS_Emulation_cleanup function when the
188 // thread terminates.
189 if (ACE_OS::thr_setspecific_native (native_tss_key_
,
190 (void *) ts_storage
) != 0)
193 return 0; // This should not happen!
200 return ts_storage
? ts_storage
: old_ts_storage
;
202 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
205 ACE_TSS_Emulation::total_keys ()
207 ACE_OS_Recursive_Thread_Mutex_Guard (
208 *static_cast <ACE_recursive_thread_mutex_t
*>
209 (ACE_OS_Object_Manager::preallocated_object
[
210 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
216 ACE_TSS_Emulation::next_key (ACE_thread_key_t
&key
)
218 ACE_OS_Recursive_Thread_Mutex_Guard (
219 *static_cast <ACE_recursive_thread_mutex_t
*>
220 (ACE_OS_Object_Manager::preallocated_object
[
221 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
223 // Initialize the tss_keys_used_ pointer on first use.
224 if (tss_keys_used_
== 0)
226 ACE_NEW_RETURN (tss_keys_used_
, ACE_TSS_Keys
, -1);
229 if (total_keys_
< ACE_TSS_THREAD_KEYS_MAX
)
232 // Loop through all possible keys and check whether a key is free
233 for ( ;counter
< ACE_TSS_THREAD_KEYS_MAX
; counter
++)
235 ACE_thread_key_t localkey
= counter
;
236 // If the key is not set as used, we can give out this key, if not
237 // we have to search further
238 if (tss_keys_used_
->is_set(localkey
) == 0)
240 tss_keys_used_
->test_and_set(localkey
);
251 key
= ACE_OS::NULL_key
;
257 ACE_TSS_Emulation::release_key (ACE_thread_key_t key
)
259 ACE_OS_Recursive_Thread_Mutex_Guard (
260 *static_cast <ACE_recursive_thread_mutex_t
*>
261 (ACE_OS_Object_Manager::preallocated_object
[
262 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
264 if (tss_keys_used_
!= 0 &&
265 tss_keys_used_
->test_and_clear (key
) == 0)
274 ACE_TSS_Emulation::is_key (ACE_thread_key_t key
)
276 ACE_OS_Recursive_Thread_Mutex_Guard (
277 *static_cast <ACE_recursive_thread_mutex_t
*>
278 (ACE_OS_Object_Manager::preallocated_object
[
279 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
281 if (tss_keys_used_
!= 0 &&
282 tss_keys_used_
->is_set (key
) == 1)
290 ACE_TSS_Emulation::tss_open (void *ts_storage
[ACE_TSS_THREAD_KEYS_MAX
])
292 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
293 // On VxWorks, in particular, don't check to see if the field
294 // is 0. It isn't always, specifically, when a program is run
295 // directly by the shell (without spawning a new task) after
296 // another program has been run.
298 u_int ts_created
= 0;
299 tss_base (ts_storage
, &ts_created
);
302 # else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
303 tss_base () = ts_storage
;
306 // Zero the entire TSS array. Do it manually instead of using
307 // memset, for optimum speed. Though, memset may be faster :-)
308 void **tss_base_p
= tss_base ();
309 for (u_int i
= 0; i
< ACE_TSS_THREAD_KEYS_MAX
; ++i
, ++tss_base_p
)
315 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
321 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
325 ACE_TSS_Emulation::tss_close ()
327 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
328 ACE_OS::thr_keyfree_native (native_tss_key_
);
329 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
332 #endif /* ACE_HAS_TSS_EMULATION */
334 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
336 /*****************************************************************************/
338 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
340 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
341 // the single file of template instantiations.
343 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id
)
346 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
349 ACE_TSS_Ref::ACE_TSS_Ref (void)
351 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
354 // Check for equality.
356 ACE_TSS_Ref::operator== (const ACE_TSS_Ref
&info
) const
358 ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
360 #ifdef ACE_THREAD_T_IS_A_STRUCT
361 return 0 == ACE_OS::memcmp (&this->tid_
, &info
.tid_
, sizeof tid_
);
363 return this->tid_
== info
.tid_
;
367 // Check for inequality.
369 ACE_TSS_Ref::operator != (const ACE_TSS_Ref
&tss_ref
) const
371 ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
373 return !(*this == tss_ref
);
376 // moved class ACE_TSS_Info declaration
377 // to OS.h so it can be visible to the
378 // single file of template instantiations
380 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key
,
381 ACE_TSS_Info::Destructor dest
)
386 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
389 ACE_TSS_Info::ACE_TSS_Info (void)
390 : key_ (ACE_OS::NULL_key
),
394 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
397 // Check for equality.
399 ACE_TSS_Info::operator== (const ACE_TSS_Info
&info
) const
401 ACE_OS_TRACE ("ACE_TSS_Info::operator==");
403 return this->key_
== info
.key_
;
406 // Check for inequality.
408 ACE_TSS_Info::operator != (const ACE_TSS_Info
&info
) const
410 ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
412 return !(*this == info
);
416 ACE_TSS_Info::dump (void)
418 # if defined (ACE_HAS_DUMP)
419 // ACE_OS_TRACE ("ACE_TSS_Info::dump");
422 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
423 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("key_ = %u\n"), this->key_
));
424 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("destructor_ = %u\n"), this->destructor_
));
425 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
427 # endif /* ACE_HAS_DUMP */
430 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
431 // to the single file of template instantiations.
433 ACE_TSS_Keys::ACE_TSS_Keys (void)
435 for (u_int i
= 0; i
< ACE_WORDS
; ++i
)
437 key_bit_words_
[i
] = 0;
443 ACE_TSS_Keys::find (const u_int key
, u_int
&word
, u_int
&bit
)
445 word
= key
/ ACE_BITS_PER_WORD
;
446 bit
= key
% ACE_BITS_PER_WORD
;
450 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key
)
453 find (key
, word
, bit
);
455 if (ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
))
461 ACE_SET_BITS (key_bit_words_
[word
], 1 << bit
);
467 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key
)
470 find (key
, word
, bit
);
472 if (word
< ACE_WORDS
&& ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
))
474 ACE_CLR_BITS (key_bit_words_
[word
], 1 << bit
);
484 ACE_TSS_Keys::is_set (const ACE_thread_key_t key
) const
487 find (key
, word
, bit
);
489 return word
< ACE_WORDS
? ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
) : 0;
493 * @class ACE_TSS_Cleanup
494 * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
496 class ACE_TSS_Cleanup
499 ACE_ALLOC_HOOK_DECLARE
;
501 /// Register a newly-allocated key
502 /// @param key the key to be monitored
503 /// @param destructor the function to call to delete objects stored via this key
504 int insert (ACE_thread_key_t key
, void (*destructor
)(void *));
506 /// Mark a key as being used by this thread.
507 void thread_use_key (ACE_thread_key_t key
);
509 /// This thread is no longer using this key
510 /// call destructor if appropriate
511 int thread_detach_key (ACE_thread_key_t key
);
513 /// This key is no longer used
514 /// Release key if use count == 0
515 /// fail if use_count != 0;
516 /// @param key the key to be released
517 int free_key (ACE_thread_key_t key
);
519 /// Cleanup the thread-specific objects. Does _NOT_ exit the thread.
520 /// For each used key perform the same actions as free_key.
521 void thread_exit (void);
526 /// Release a key used by this thread
527 /// @param info reference to the info for this key
528 /// @param destructor out arg to receive destructor function ptr
529 /// @param tss_obj out arg to receive pointer to deletable object
530 void thread_release (
532 ACE_TSS_Info::Destructor
& destructor
,
535 /// remove key if it's unused (thread_count == 0)
536 /// @param info reference to the info for this key
537 int remove_key (ACE_TSS_Info
&info
);
539 /// Find the TSS keys (if any) for this thread.
540 /// @param thread_keys reference to pointer to be filled in by this function.
541 /// @return false if keys don't exist.
542 bool find_tss_keys (ACE_TSS_Keys
*& thread_keys
) const;
544 /// Accessor for this threads ACE_TSS_Keys instance.
545 /// Creates the keys if necessary.
546 ACE_TSS_Keys
*tss_keys ();
548 /// Ensure singleton.
549 ACE_TSS_Cleanup (void);
550 ~ACE_TSS_Cleanup (void);
552 /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
553 friend class TSS_Cleanup_Instance
;
556 // Array of <ACE_TSS_Info> objects.
557 typedef ACE_TSS_Info ACE_TSS_TABLE
[ACE_DEFAULT_THREAD_KEYS
];
558 typedef ACE_TSS_Info
*ACE_TSS_TABLE_ITERATOR
;
560 /// Table of <ACE_TSS_Info>'s.
561 ACE_TSS_TABLE table_
;
563 /// Key for the thread-specific ACE_TSS_Keys
564 /// Used by find_tss_keys() or tss_keys() to find the
565 /// bit array that records whether each TSS key is in
566 /// use by this thread.
567 ACE_thread_key_t in_use_
;
570 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Cleanup
);
571 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Keys
);
573 /*****************************************************************************/
575 * @class TSS_Cleanup_Instance
576 * @A class to manage an instance pointer to ACE_TSS_Cleanup.
577 * Note: that the double checked locking pattern doesn't allow
579 * Callers who wish to access the singleton ACE_TSS_Cleanup must
580 * do so by instantiating a TSS_Cleanup_Instance, calling the valid
581 * method to be sure the ACE_TSS_Cleanup is available, then using
582 * the TSS_Cleanup_Instance as a pointer to the instance.
583 * Construction argument to the TSS_Cleanup_Instance determines how
585 * CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
586 * USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
587 * DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
588 * delete it when the TSS_Cleanup_Instance goes out of scope.
591 class TSS_Cleanup_Instance
600 explicit TSS_Cleanup_Instance (Purpose purpose
= USE
);
601 ~TSS_Cleanup_Instance();
604 ACE_TSS_Cleanup
* operator ->();
608 ACE_TSS_Cleanup
* operator *();
611 static unsigned int reference_count_
;
612 static ACE_TSS_Cleanup
* instance_
;
613 static ACE_Thread_Mutex
* mutex_
;
614 static ACE_Condition_Thread_Mutex
* condition_
;
617 ACE_TSS_Cleanup
* ptr_
;
618 unsigned short flags_
;
622 FLAG_VALID_CHECKED
= 2
626 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose
)
630 // During static construction or construction of the ACE_Object_Manager,
631 // there can be only one thread in this constructor at any one time, so
632 // it's safe to check for a zero mutex_. If it's zero, we create a new
633 // mutex and condition variable.
636 ACE_NEW (mutex_
, ACE_Thread_Mutex ());
637 ACE_NEW (condition_
, ACE_Condition_Thread_Mutex (*mutex_
));
640 ACE_GUARD (ACE_Thread_Mutex
, m
, *mutex_
);
642 if (purpose
== CREATE
)
646 instance_
= new ACE_TSS_Cleanup();
651 else if(purpose
== DESTROY
)
657 ACE_SET_BITS(flags_
, FLAG_DELETING
);
658 while (reference_count_
> 0)
664 else // must be normal use
666 ACE_ASSERT(purpose
== USE
);
675 TSS_Cleanup_Instance::~TSS_Cleanup_Instance (void)
677 // Variable to hold the mutex_ to delete outside the scope of the
679 ACE_Thread_Mutex
*del_mutex
= 0;
683 ACE_GUARD (ACE_Thread_Mutex
, guard
, *mutex_
);
686 if (ACE_BIT_ENABLED (flags_
, FLAG_DELETING
))
688 ACE_ASSERT(instance_
== 0);
689 ACE_ASSERT(reference_count_
== 0);
696 ACE_ASSERT (reference_count_
> 0);
698 if (reference_count_
== 0 && instance_
== 0)
699 condition_
->signal ();
702 }// end of guard scope
713 TSS_Cleanup_Instance::valid()
715 ACE_SET_BITS(flags_
, FLAG_VALID_CHECKED
);
716 return (this->instance_
!= 0);
720 TSS_Cleanup_Instance::operator *()
722 ACE_ASSERT(ACE_BIT_ENABLED(flags_
, FLAG_VALID_CHECKED
));
727 TSS_Cleanup_Instance::operator ->()
729 ACE_ASSERT(ACE_BIT_ENABLED(flags_
, FLAG_VALID_CHECKED
));
733 // = Static object initialization.
734 unsigned int TSS_Cleanup_Instance::reference_count_
= 0;
735 ACE_TSS_Cleanup
* TSS_Cleanup_Instance::instance_
= 0;
736 ACE_Thread_Mutex
* TSS_Cleanup_Instance::mutex_
= 0;
737 ACE_Condition_Thread_Mutex
* TSS_Cleanup_Instance::condition_
= 0;
739 ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void)
744 ACE_TSS_Cleanup::thread_exit (void)
746 ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
747 // variables to hold the destructors, keys
748 // and pointers to the object to be destructed
749 // the actual destruction is deferred until the guard is released
750 ACE_TSS_Info::Destructor destructor
[ACE_DEFAULT_THREAD_KEYS
];
751 void * tss_obj
[ACE_DEFAULT_THREAD_KEYS
];
752 ACE_thread_key_t keys
[ACE_DEFAULT_THREAD_KEYS
];
753 // count of items to be destroyed
754 unsigned int d_count
= 0;
758 ACE_TSS_CLEANUP_GUARD
760 // if not initialized or already cleaned up
761 ACE_TSS_Keys
*this_thread_keys
= 0;
762 if (! find_tss_keys (this_thread_keys
) )
767 // Minor hack: Iterating in reverse order means the LOG buffer which is
768 // accidentally allocated first will be accidentally deallocated (almost)
769 // last -- in case someone logs something from the other destructors.
770 // applications should not count on this behavior because platforms which
771 // do not use ACE_TSS_Cleanup may delete objects in other orders.
772 unsigned int key_index
= ACE_DEFAULT_THREAD_KEYS
;
773 while( key_index
> 0)
776 ACE_TSS_Info
& info
= this->table_
[key_index
];
777 // if this key is in use by this thread
778 if (info
.key_in_use () && this_thread_keys
->is_set(info
.key_
))
780 // defer deleting the in-use key until all others have been deleted
781 if(info
.key_
!= this->in_use_
)
783 destructor
[d_count
] = 0;
784 tss_obj
[d_count
] = 0;
786 this->thread_release (info
, destructor
[d_count
], tss_obj
[d_count
]);
787 if (destructor
[d_count
] != 0 && tss_obj
[d_count
] != 0)
789 keys
[d_count
] = info
.key_
;
796 // remove the in_use bit vector last
797 u_int use_index
= this->in_use_
;
798 ACE_TSS_Info
& info
= this->table_
[use_index
];
799 destructor
[d_count
] = 0;
800 tss_obj
[d_count
] = 0;
802 this->thread_release (info
, destructor
[d_count
], tss_obj
[d_count
]);
803 if (destructor
[d_count
] != 0 && tss_obj
[d_count
] != 0)
805 keys
[d_count
] = info
.key_
;
808 } // end of guard scope
809 for (unsigned int d_index
= 0; d_index
< d_count
; ++d_index
)
811 (*destructor
[d_index
])(tss_obj
[d_index
]);
812 #if defined (ACE_HAS_TSS_EMULATION)
813 ACE_TSS_Emulation::ts_object (keys
[d_index
]) = 0;
814 #else // defined (ACE_HAS_TSS_EMULATION)
815 ACE_OS::thr_setspecific_native (keys
[d_index
], 0);
816 #endif // defined (ACE_HAS_TSS_EMULATION)
821 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys
)
823 delete static_cast <ACE_TSS_Keys
*> (tss_keys
);
826 ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
827 : in_use_ (ACE_OS::NULL_key
)
829 ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
833 ACE_TSS_Cleanup::insert (ACE_thread_key_t key
,
834 void (*destructor
)(void *))
836 ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
837 ACE_TSS_CLEANUP_GUARD
839 u_int key_index
= key
;
840 ACE_ASSERT (key_index
< ACE_DEFAULT_THREAD_KEYS
);
841 if (key_index
< ACE_DEFAULT_THREAD_KEYS
)
843 ACE_ASSERT (table_
[key_index
].thread_count_
== -1);
844 table_
[key_index
] = ACE_TSS_Info (key
, destructor
);
845 table_
[key_index
].thread_count_
= 0; // inserting it does not use it
846 // but it does "allocate" it
856 ACE_TSS_Cleanup::free_key (ACE_thread_key_t key
)
858 ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
859 ACE_TSS_CLEANUP_GUARD
860 u_int key_index
= key
;
861 if (key_index
< ACE_DEFAULT_THREAD_KEYS
)
863 return remove_key (this->table_
[key_index
]);
869 ACE_TSS_Cleanup::remove_key (ACE_TSS_Info
&info
)
871 // assume CLEANUP_GUARD is held by caller
872 ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
874 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
875 // When this is done, any existing TSS objects controlled by this key are leaked
876 // There is no "right thing" to do in this case
878 // only remove it if all threads are done with it
879 if (info
.thread_count_
!= 0)
885 #if !defined (ACE_HAS_TSS_EMULATION)
886 ACE_OS_thread_key_t temp_key
= info
.key_
;
887 ACE_OS::thr_keyfree_native (temp_key
);
888 #endif /* !ACE_HAS_TSS_EMULATION */
889 if (info
.key_
== this->in_use_
)
891 this->in_use_
= ACE_OS::NULL_key
;
894 info
.destructor_
= 0;
899 ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key
)
901 // variables to hold the destructor and the object to be destructed
902 // the actual call is deferred until the guard is released
903 ACE_TSS_Info::Destructor destructor
= 0;
908 ACE_TSS_CLEANUP_GUARD
910 u_int key_index
= key
;
911 ACE_ASSERT (key_index
< sizeof(this->table_
)/sizeof(this->table_
[0]));
912 // If this entry was never set, just bug out. If it is set, but is the
913 // wrong key, assert.
914 if (this->table_
[key_index
].key_
== 0)
916 ACE_ASSERT (this->table_
[key_index
].key_
== key
);
917 ACE_TSS_Info
&info
= this->table_
[key_index
];
920 if (!info
.key_in_use ())
925 this->thread_release (info
, destructor
, tss_obj
);
926 } // end of scope for the Guard
927 // if there's a destructor and an object to be destroyed
928 if (destructor
!= 0 && tss_obj
!= 0)
930 (*destructor
) (tss_obj
);
936 ACE_TSS_Cleanup::thread_release (
938 ACE_TSS_Info::Destructor
& destructor
,
941 // assume guard is held by caller
942 // Find the TSS keys (if any) for this thread
943 // do not create them if they don't exist
944 ACE_TSS_Keys
* thread_keys
= 0;
945 if (find_tss_keys (thread_keys
))
947 // if this key is in use by this thread
948 if (thread_keys
->test_and_clear(info
.key_
) == 0)
950 // save destructor & pointer to tss object
951 // until after the guard is released
952 destructor
= info
.destructor_
;
953 ACE_OS::thr_getspecific (info
.key_
, &tss_obj
);
954 ACE_ASSERT (info
.thread_count_
> 0);
955 --info
.thread_count_
;
961 ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key
)
963 // If the key's ACE_TSS_Info in-use bit for this thread is not set,
964 // set it and increment the key's thread_count_.
965 if (! tss_keys ()->test_and_set (key
))
967 ACE_TSS_CLEANUP_GUARD
969 // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
970 u_int key_index
= key
;
971 ACE_TSS_Info
&key_info
= this->table_
[key_index
];
973 ACE_ASSERT (key_info
.key_in_use ());
974 ++key_info
.thread_count_
;
979 ACE_TSS_Cleanup::dump (void)
981 # if defined (ACE_HAS_DUMP)
982 // Iterate through all the thread-specific items and dump them all.
984 ACE_TSS_TABLE_ITERATOR key_info
= table_
;
985 for (unsigned int i
= 0;
986 i
< ACE_DEFAULT_THREAD_KEYS
;
989 # endif /* ACE_HAS_DUMP */
993 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys
*& tss_keys
) const
995 if (this->in_use_
== ACE_OS::NULL_key
)
997 if (ACE_OS::thr_getspecific (in_use_
,
998 reinterpret_cast<void **> (&tss_keys
)) == -1)
1001 return false; // This should not happen!
1003 return tss_keys
!= 0;
1007 ACE_TSS_Cleanup::tss_keys ()
1009 if (this->in_use_
== ACE_OS::NULL_key
)
1011 ACE_TSS_CLEANUP_GUARD
1013 if (in_use_
== ACE_OS::NULL_key
)
1015 // Initialize in_use_ with a new key.
1016 if (ACE_OS::thr_keycreate (&in_use_
,
1017 &ACE_TSS_Cleanup_keys_destroyer
))
1020 return 0; // Major problems, this should *never* happen!
1026 if (ACE_OS::thr_getspecific (in_use_
, &ts_keys
) == -1)
1029 return 0; // This should not happen!
1034 ACE_NEW_RETURN (ts_keys
,
1037 // Store the dynamically allocated pointer in thread-specific
1039 if (ACE_OS::thr_setspecific (in_use_
, ts_keys
) == -1)
1042 delete reinterpret_cast <ACE_TSS_Keys
*> (ts_keys
);
1043 return 0; // Major problems, this should *never* happen!
1047 return reinterpret_cast <ACE_TSS_Keys
*>(ts_keys
);
1050 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
1052 /*****************************************************************************/
1054 // = Static initialization.
1056 // This is necessary to deal with POSIX pthreads insanity. This
1057 // guarantees that we've got a "zero'd" thread id even when
1058 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
1059 // as structures... Under no circumstances should these be given
1061 // Note: these three objects require static construction.
1062 ACE_thread_t
ACE_OS::NULL_thread
;
1063 ACE_hthread_t
ACE_OS::NULL_hthread
;
1064 #if defined (ACE_HAS_TSS_EMULATION)
1065 ACE_thread_key_t
ACE_OS::NULL_key
= static_cast <ACE_thread_key_t
> (-1);
1066 #else /* ! ACE_HAS_TSS_EMULATION */
1067 ACE_thread_key_t
ACE_OS::NULL_key
;
1068 #endif /* ! ACE_HAS_TSS_EMULATION */
1070 /*****************************************************************************/
1073 ACE_OS::cleanup_tss (const u_int main_thread
)
1075 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
1076 { // scope the cleanup instance
1077 // Call TSS destructors for current thread.
1078 TSS_Cleanup_Instance cleanup
;
1079 if (cleanup
.valid ())
1081 cleanup
->thread_exit ();
1084 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
1088 #if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS)
1089 // Just close the ACE_Log_Msg for the current (which should be
1090 // main) thread. We don't have TSS emulation; if there's native
1091 // TSS, it should call its destructors when the main thread
1093 ACE_Base_Thread_Adapter::close_log_msg ();
1094 #endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
1096 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
1097 // Finally, free up the ACE_TSS_Cleanup instance. This method gets
1098 // called by the ACE_Object_Manager.
1099 TSS_Cleanup_Instance
cleanup(TSS_Cleanup_Instance::DESTROY
);
1100 if (cleanup
.valid ())
1102 ; // the pointer deletes the Cleanup when it goes out of scope
1105 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
1107 #if defined (ACE_HAS_TSS_EMULATION)
1108 ACE_TSS_Emulation::tss_close ();
1109 #endif /* ACE_HAS_TSS_EMULATION */
1113 /*****************************************************************************/
1115 /*****************************************************************************/
1117 #if defined (ACE_LACKS_COND_T)
1119 ACE_OS::cond_broadcast (ACE_cond_t
*cv
)
1121 ACE_OS_TRACE ("ACE_OS::cond_broadcast");
1122 # if defined (ACE_HAS_THREADS)
1123 // The <external_mutex> must be locked before this call is made.
1125 // This is needed to ensure that <waiters_> and <was_broadcast_> are
1126 // consistent relative to each other.
1127 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1132 bool have_waiters
= false;
1134 if (cv
->waiters_
> 0)
1136 // We are broadcasting, even if there is just one waiter...
1137 // Record the fact that we are broadcasting. This helps the
1138 // cond_wait() method know how to optimize itself. Be sure to
1139 // set this with the <waiters_lock_> held.
1140 cv
->was_broadcast_
= 1;
1141 have_waiters
= true;
1144 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1146 // This is really bad, we have the lock but can't release it anymore
1153 // Wake up all the waiters.
1154 if (ACE_OS::sema_post (&cv
->sema_
, cv
->waiters_
) == -1)
1156 // Wait for all the awakened threads to acquire their part of
1157 // the counting semaphore.
1158 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1159 else if (ACE_OS::sema_wait (&cv
->waiters_done_
) == -1)
1161 else if (ACE_OS::event_wait (&cv
->waiters_done_
) == -1)
1162 # endif /* ACE_VXWORKS */
1164 // This is okay, even without the <waiters_lock_> held because
1165 // no other waiter threads can wake up to access it.
1166 cv
->was_broadcast_
= 0;
1170 ACE_UNUSED_ARG (cv
);
1171 ACE_NOTSUP_RETURN (-1);
1172 # endif /* ACE_HAS_THREADS */
1176 ACE_OS::cond_destroy (ACE_cond_t
*cv
)
1178 ACE_OS_TRACE ("ACE_OS::cond_destroy");
1179 # if defined (ACE_HAS_THREADS)
1180 # if defined (ACE_HAS_WTHREADS)
1181 ACE_OS::event_destroy (&cv
->waiters_done_
);
1182 # elif defined (ACE_VXWORKS) || defined (ACE_MQX)
1183 ACE_OS::sema_destroy (&cv
->waiters_done_
);
1184 # endif /* ACE_VXWORKS */
1186 if (ACE_OS::thread_mutex_destroy (&cv
->waiters_lock_
) != 0)
1189 if (ACE_OS::sema_destroy (&cv
->sema_
) != 0)
1194 ACE_UNUSED_ARG (cv
);
1195 ACE_NOTSUP_RETURN (-1);
1196 # endif /* ACE_HAS_THREADS */
1200 ACE_OS::cond_init (ACE_cond_t
*cv
,
1201 ACE_condattr_t
&attributes
,
1202 const char *name
, void *arg
)
1205 ACE_OS::cond_init (cv
, static_cast<short> (attributes
.type
), name
, arg
);
1208 # if defined (ACE_HAS_WCHAR)
1210 ACE_OS::cond_init (ACE_cond_t
*cv
,
1211 ACE_condattr_t
&attributes
,
1212 const wchar_t *name
, void *arg
)
1215 ACE_OS::cond_init (cv
, static_cast<short> (attributes
.type
), name
, arg
);
1217 # endif /* ACE_HAS_WCHAR */
1220 ACE_OS::cond_init (ACE_cond_t
*cv
, short type
, const char *name
, void *arg
)
1222 ACE_OS_TRACE ("ACE_OS::cond_init");
1223 # if defined (ACE_HAS_THREADS)
1225 cv
->was_broadcast_
= 0;
1228 if (ACE_OS::sema_init (&cv
->sema_
, 0, type
, name
, arg
) == -1)
1230 else if (ACE_OS::thread_mutex_init (&cv
->waiters_lock_
) == -1)
1232 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1233 else if (ACE_OS::sema_init (&cv
->waiters_done_
, 0, type
) == -1)
1235 else if (ACE_OS::event_init (&cv
->waiters_done_
) == -1)
1236 # endif /* ACE_VXWORKS */
1240 ACE_UNUSED_ARG (cv
);
1241 ACE_UNUSED_ARG (type
);
1242 ACE_UNUSED_ARG (name
);
1243 ACE_UNUSED_ARG (arg
);
1244 ACE_NOTSUP_RETURN (-1);
1245 # endif /* ACE_HAS_THREADS */
1248 # if defined (ACE_HAS_WCHAR)
1250 ACE_OS::cond_init (ACE_cond_t
*cv
, short type
, const wchar_t *name
, void *arg
)
1252 ACE_OS_TRACE ("ACE_OS::cond_init");
1253 # if defined (ACE_HAS_THREADS)
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) || defined (ACE_MQX)
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 */
1277 # endif /* ACE_HAS_WCHAR */
1280 ACE_OS::cond_signal (ACE_cond_t
*cv
)
1282 ACE_OS_TRACE ("ACE_OS::cond_signal");
1283 # if defined (ACE_HAS_THREADS)
1284 // If there aren't any waiters, then this is a no-op. Note that
1285 // this function *must* be called with the <external_mutex> held
1286 // since other wise there is a race condition that can lead to the
1287 // lost wakeup bug... This is needed to ensure that the <waiters_>
1288 // value is not in an inconsistent internal state while being
1289 // updated by another thread.
1290 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1292 bool const have_waiters
= cv
->waiters_
> 0;
1293 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1297 return ACE_OS::sema_post (&cv
->sema_
);
1301 ACE_UNUSED_ARG (cv
);
1302 ACE_NOTSUP_RETURN (-1);
1303 # endif /* ACE_HAS_THREADS */
1307 ACE_OS::cond_wait (ACE_cond_t
*cv
,
1308 ACE_mutex_t
*external_mutex
)
1310 ACE_OS_TRACE ("ACE_OS::cond_wait");
1311 # if defined (ACE_HAS_THREADS)
1312 // Prevent race conditions on the <waiters_> count.
1313 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1318 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1323 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1324 if (external_mutex
->type_
== USYNC_PROCESS
)
1326 // This call will automatically release the mutex and wait on the semaphore.
1327 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex
->proc_mutex_
,
1328 cv
->sema_
, INFINITE
, FALSE
),
1335 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1337 // We keep the lock held just long enough to increment the count of
1338 // waiters by one. Note that we can't keep it held across the call
1339 // to ACE_OS::sema_wait() since that will deadlock other calls to
1340 // ACE_OS::cond_signal().
1341 if (ACE_OS::mutex_unlock (external_mutex
) != 0)
1344 // Wait to be awakened by a ACE_OS::cond_signal() or
1345 // ACE_OS::cond_broadcast().
1346 result
= ACE_OS::sema_wait (&cv
->sema_
);
1349 // Reacquire lock to avoid race conditions on the <waiters_> count.
1350 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1353 // We're ready to return, so there's one less waiter.
1356 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1358 // Release the lock so that other collaborating threads can make
1360 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1364 // Bad things happened, so let's just return below.
1366 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1367 else if (external_mutex
->type_
== USYNC_PROCESS
)
1371 // This call atomically signals the <waiters_done_> event and
1372 // waits until it can acquire the mutex. This is important to
1373 // prevent unfairness.
1374 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv
->waiters_done_
,
1375 external_mutex
->proc_mutex_
,
1380 // We must always regain the <external_mutex>, even when
1381 // errors occur because that's the guarantee that we give to
1383 if (ACE_OS::mutex_lock (external_mutex
) != 0)
1389 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1390 // If we're the last waiter thread during this particular broadcast
1391 // then let all the other threads proceed.
1392 else if (last_waiter
)
1393 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1394 ACE_OS::sema_post (&cv
->waiters_done_
);
1396 ACE_OS::event_signal (&cv
->waiters_done_
);
1397 # endif /* ACE_VXWORKS */
1399 // We must always regain the <external_mutex>, even when errors
1400 // occur because that's the guarantee that we give to our callers.
1401 ACE_OS::mutex_lock (external_mutex
);
1405 ACE_UNUSED_ARG (cv
);
1406 ACE_UNUSED_ARG (external_mutex
);
1407 ACE_NOTSUP_RETURN (-1);
1408 # endif /* ACE_HAS_THREADS */
1412 ACE_OS::cond_timedwait (ACE_cond_t
*cv
,
1413 ACE_mutex_t
*external_mutex
,
1414 ACE_Time_Value
*timeout
)
1416 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1417 # if defined (ACE_HAS_THREADS)
1418 // Handle the easy case first.
1420 return ACE_OS::cond_wait (cv
, external_mutex
);
1421 # if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS) || defined (ACE_MQX)
1423 // Prevent race conditions on the <waiters_> count.
1424 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1429 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1433 ACE_Errno_Guard
error (errno
, 0);
1434 int msec_timeout
= 0;
1436 if (timeout
!= 0 && *timeout
!= ACE_Time_Value::zero
)
1438 // Note that we must convert between absolute time (which is
1439 // passed as a parameter) and relative time (which is what
1440 // WaitForSingleObjects() expects).
1441 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
1443 // Watchout for situations where a context switch has caused the
1444 // current time to be > the timeout.
1445 if (relative_time
> ACE_Time_Value::zero
)
1446 msec_timeout
= relative_time
.msec ();
1449 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1450 if (external_mutex
->type_
== USYNC_PROCESS
)
1451 // This call will automatically release the mutex and wait on the
1453 result
= ::SignalObjectAndWait (external_mutex
->proc_mutex_
,
1458 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1460 // We keep the lock held just long enough to increment the count
1461 // of waiters by one. Note that we can't keep it held across
1462 // the call to WaitForSingleObject since that will deadlock
1463 // other calls to ACE_OS::cond_signal().
1464 if (ACE_OS::mutex_unlock (external_mutex
) != 0)
1467 // Wait to be awakened by a ACE_OS::signal() or
1468 // ACE_OS::broadcast().
1469 # if defined (ACE_WIN32)
1470 # if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1471 result
= ::WaitForSingleObject (cv
->sema_
, msec_timeout
);
1472 # else /* ACE_USES_WINCE_SEMA_SIMULATION */
1473 // Can't use Win32 API on our simulated semaphores.
1474 result
= ACE_OS::sema_wait (&cv
->sema_
,
1476 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1477 # elif defined (ACE_VXWORKS)
1478 // Inline the call to ACE_OS::sema_wait () because it takes an
1479 // ACE_Time_Value argument. Avoid the cost of that conversion . . .
1480 int const ticks_per_sec
= ::sysClkRateGet ();
1481 int const ticks
= msec_timeout
* ticks_per_sec
/ ACE_ONE_SECOND_IN_MSECS
;
1482 result
= ::semTake (cv
->sema_
.sema_
, ticks
);
1484 result
= ACE_OS::sema_wait (&cv
->sema_
, timeout
);
1485 # endif /* ACE_WIN32 || VXWORKS */
1488 // Reacquire lock to avoid race conditions.
1489 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1494 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1496 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1499 # if defined (ACE_WIN32)
1500 if (result
!= (int)WAIT_OBJECT_0
)
1508 error
= ::GetLastError ();
1513 # elif defined (ACE_VXWORKS)
1514 if (result
== ERROR
)
1518 case S_objLib_OBJ_TIMEOUT
:
1521 case S_objLib_OBJ_UNAVAILABLE
:
1522 if (msec_timeout
== 0)
1531 # endif /* ACE_WIN32 || VXWORKS */
1532 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1533 if (external_mutex
->type_
== USYNC_PROCESS
)
1536 // This call atomically signals the <waiters_done_> event and
1537 // waits until it can acquire the mutex. This is important to
1538 // prevent unfairness.
1539 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv
->waiters_done_
,
1540 external_mutex
->proc_mutex_
,
1546 // We must always regain the <external_Mutex>, even when
1547 // errors occur because that's the guarantee that we give to
1549 if (ACE_OS::mutex_lock (external_mutex
) != 0)
1556 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1557 // Note that this *must* be an "if" statement rather than an "else
1558 // if" statement since the caller may have timed out and hence the
1559 // result would have been -1 above.
1562 // Release the signaler/broadcaster if we're the last waiter.
1563 # if defined (ACE_WIN32)
1564 if (ACE_OS::event_signal (&cv
->waiters_done_
) != 0)
1566 if (ACE_OS::sema_post (&cv
->waiters_done_
) != 0)
1567 # endif /* ACE_WIN32 */
1571 // We must always regain the <external_mutex>, even when errors
1572 // occur because that's the guarantee that we give to our callers.
1573 if (ACE_OS::mutex_lock (external_mutex
) != 0)
1577 # endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
1579 ACE_UNUSED_ARG (cv
);
1580 ACE_UNUSED_ARG (external_mutex
);
1581 ACE_UNUSED_ARG (timeout
);
1582 ACE_NOTSUP_RETURN (-1);
1583 # endif /* ACE_HAS_THREADS */
1587 ACE_OS::cond_init (ACE_cond_t
*cv
, short type
, const char *name
, void *arg
)
1589 ACE_condattr_t attributes
;
1590 if (ACE_OS::condattr_init (attributes
, type
) == 0
1591 && ACE_OS::cond_init (cv
, attributes
, name
, arg
) == 0)
1593 (void) ACE_OS::condattr_destroy (attributes
);
1598 #endif /* ACE_LACKS_COND_T */
1600 #if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS)
1602 ACE_OS::cond_timedwait (ACE_cond_t
*cv
,
1603 ACE_thread_mutex_t
*external_mutex
,
1604 ACE_Time_Value
*timeout
)
1606 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1607 # if defined (ACE_HAS_THREADS)
1608 // Handle the easy case first.
1610 return ACE_OS::cond_wait (cv
, external_mutex
);
1612 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1613 int msec_timeout
= 0;
1616 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
1617 // Watchout for situations where a context switch has caused the
1618 // current time to be > the timeout.
1619 if (relative_time
> ACE_Time_Value::zero
)
1620 msec_timeout
= relative_time
.msec ();
1622 ACE_OSCALL (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv
, external_mutex
, msec_timeout
),
1627 // Prevent race conditions on the <waiters_> count.
1628 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1633 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1638 int msec_timeout
= 0;
1640 if (timeout
!= 0 && *timeout
!= ACE_Time_Value::zero
)
1642 // Note that we must convert between absolute time (which is
1643 // passed as a parameter) and relative time (which is what
1644 // WaitForSingleObjects() expects).
1645 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
1647 // Watchout for situations where a context switch has caused the
1648 // current time to be > the timeout.
1649 if (relative_time
> ACE_Time_Value::zero
)
1650 msec_timeout
= relative_time
.msec ();
1653 // We keep the lock held just long enough to increment the count of
1654 // waiters by one. Note that we can't keep it held across the call
1655 // to WaitForSingleObject since that will deadlock other calls to
1656 // ACE_OS::cond_signal().
1657 if (ACE_OS::thread_mutex_unlock (external_mutex
) != 0)
1660 // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
1661 # if defined (ACE_USES_WINCE_SEMA_SIMULATION)
1662 // Can't use Win32 API on simulated semaphores.
1663 result
= ACE_OS::sema_wait (&cv
->sema_
,
1666 if (result
== -1 && errno
== ETIME
)
1667 result
= WAIT_TIMEOUT
;
1669 result
= ::WaitForSingleObject (cv
->sema_
, msec_timeout
);
1670 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1672 // Reacquire lock to avoid race conditions.
1673 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1678 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1680 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1683 if (result
!= (int)WAIT_OBJECT_0
)
1691 error
= ::GetLastError ();
1699 // Release the signaler/broadcaster if we're the last waiter.
1700 if (ACE_OS::event_signal (&cv
->waiters_done_
) != 0)
1704 // We must always regain the <external_mutex>, even when errors
1705 // occur because that's the guarantee that we give to our callers.
1706 if (ACE_OS::thread_mutex_lock (external_mutex
) != 0)
1711 /* This assignment must only be done if error != 0,
1712 * since writing 0 to errno violates the POSIX specification.
1719 ACE_NOTSUP_RETURN (-1);
1720 # endif /* ACE_HAS_THREADS */
1724 ACE_OS::cond_wait (ACE_cond_t
*cv
,
1725 ACE_thread_mutex_t
*external_mutex
)
1727 ACE_OS_TRACE ("ACE_OS::cond_wait");
1728 # if defined (ACE_HAS_THREADS)
1729 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1731 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv
, external_mutex
, INFINITE
), result
),
1734 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1738 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1744 // We keep the lock held just long enough to increment the count of
1745 // waiters by one. Note that we can't keep it held across the call
1746 // to ACE_OS::sema_wait() since that will deadlock other calls to
1747 // ACE_OS::cond_signal().
1748 if (ACE_OS::thread_mutex_unlock (external_mutex
) != 0)
1751 // Wait to be awakened by a ACE_OS::cond_signal() or
1752 // ACE_OS::cond_broadcast().
1753 # if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
1754 result
= ::WaitForSingleObject (cv
->sema_
, INFINITE
);
1756 // Can't use Win32 API on simulated semaphores.
1757 result
= ACE_OS::sema_wait (&cv
->sema_
);
1759 if (result
!= WAIT_OBJECT_0
&& errno
== ETIME
)
1760 result
= WAIT_TIMEOUT
;
1762 # endif /* ACE_USES_WINCE_SEMA_SIMULATION */
1764 // Reacquire lock to avoid race conditions.
1765 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1770 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1772 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1775 if (result
!= (int)WAIT_OBJECT_0
)
1783 error
= ::GetLastError ();
1787 else if (last_waiter
)
1789 // Release the signaler/broadcaster if we're the last waiter.
1790 if (ACE_OS::event_signal (&cv
->waiters_done_
) != 0)
1794 // We must always regain the <external_mutex>, even when errors
1795 // occur because that's the guarantee that we give to our callers.
1796 if (ACE_OS::thread_mutex_lock (external_mutex
) != 0)
1799 // Reset errno in case mutex_lock() also fails...
1802 /* This assignment must only be done if error != 0,
1803 * since writing 0 to errno violates the POSIX specification.
1810 ACE_NOTSUP_RETURN (-1);
1811 # endif /* ACE_HAS_THREADS */
1813 # endif /* ACE_HAS_WTHREADS */
1815 /*****************************************************************************/
1817 /*****************************************************************************/
1819 /*****************************************************************************/
1821 /*****************************************************************************/
1824 ACE_OS::mutex_init (ACE_mutex_t
*m
,
1827 ACE_mutexattr_t
*attributes
,
1828 LPSECURITY_ATTRIBUTES sa
,
1831 // ACE_OS_TRACE ("ACE_OS::mutex_init");
1832 #if defined (ACE_HAS_THREADS)
1833 # if defined (ACE_HAS_PTHREADS)
1834 ACE_UNUSED_ARG (name
);
1835 ACE_UNUSED_ARG (sa
);
1837 # if defined (ACE_PTHREAD_MUTEXATTR_T_INITIALIZE)
1838 /* Tests show that VxWorks 6.x pthread lib does not only
1839 * require zeroing of mutex/condition objects to function correctly
1840 * but also of the attribute objects.
1842 pthread_mutexattr_t l_attributes
= {0};
1844 pthread_mutexattr_t l_attributes
;
1847 if (attributes
== 0)
1848 attributes
= &l_attributes
;
1850 int attr_init
= 0; // have we initialized the local attributes.
1852 // Only do these initializations if the <attributes> parameter
1853 // wasn't originally set.
1854 if (attributes
== &l_attributes
)
1856 if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes
), result
) == 0)
1859 attr_init
= 1; // we have initialized these attributes
1863 result
= -1; // ACE_ADAPT_RETVAL used it for intermediate status
1867 if (result
== 0 && lock_scope
!= 0)
1869 # if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
1870 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes
,
1873 # endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
1876 if (result
== 0 && lock_type
!= 0)
1878 # if defined (ACE_HAS_RECURSIVE_MUTEXES) && !defined (ACE_LACKS_PTHREAD_MUTEXATTR_SETTYPE)
1879 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes
,
1882 # endif /* ACE_HAS_RECURSIVE_MUTEXES */
1887 # if defined (ACE_PTHREAD_MUTEX_T_INITIALIZE)
1888 /* VxWorks 6.x API reference states:
1889 * If the memory for the mutex variable object has been allocated
1890 * dynamically, it is a good policy to always zero out the
1891 * block of memory so as to avoid spurious EBUSY return code
1892 * when calling this routine.
1893 * Tests shows this to be necessary.
1895 ACE_OS::memset (m
, 0, sizeof (*m
));
1897 if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m
, attributes
), result
) == 0)
1900 result
= -1; // ACE_ADAPT_RETVAL used it for intermediate status
1903 // Only do the deletions if the <attributes> parameter wasn't
1905 if (attributes
== &l_attributes
&& attr_init
)
1906 ::pthread_mutexattr_destroy (&l_attributes
);
1909 # elif defined (ACE_HAS_STHREADS)
1910 ACE_UNUSED_ARG (name
);
1911 ACE_UNUSED_ARG (sa
);
1912 ACE_UNUSED_ARG (lock_type
);
1914 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m
,
1919 # elif defined (ACE_HAS_WTHREADS)
1920 m
->type_
= lock_scope
;
1922 SECURITY_ATTRIBUTES sa_buffer
;
1923 SECURITY_DESCRIPTOR sd_buffer
;
1927 # if defined (ACE_HAS_WINCE)
1928 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
1930 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1931 (sa
, &sa_buffer
, &sd_buffer
),
1933 ACE_Ascii_To_Wide (name
).wchar_rep ());
1934 # else /* ACE_HAS_WINCE */
1936 ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
1937 (sa
, &sa_buffer
, &sd_buffer
),
1940 # endif /* ACE_HAS_WINCE */
1941 if (m
->proc_mutex_
== 0)
1942 ACE_FAIL_RETURN (-1);
1945 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1946 ACE_OS::set_errno_to_last_error ();
1950 return ACE_OS::thread_mutex_init (&m
->thr_mutex_
,
1960 # elif defined (ACE_VXWORKS)
1961 ACE_UNUSED_ARG (name
);
1962 ACE_UNUSED_ARG (attributes
);
1963 ACE_UNUSED_ARG (sa
);
1964 ACE_UNUSED_ARG (lock_type
);
1966 return (*m
= ::semMCreate (lock_scope
)) == 0 ? -1 : 0;
1967 # endif /* ACE_HAS_PTHREADS */
1970 ACE_UNUSED_ARG (lock_scope
);
1971 ACE_UNUSED_ARG (name
);
1972 ACE_UNUSED_ARG (attributes
);
1973 ACE_UNUSED_ARG (sa
);
1974 ACE_UNUSED_ARG (lock_type
);
1975 ACE_NOTSUP_RETURN (-1);
1976 #endif /* ACE_HAS_THREADS */
1980 ACE_OS::mutex_destroy (ACE_mutex_t
*m
)
1982 ACE_OS_TRACE ("ACE_OS::mutex_destroy");
1983 #if defined (ACE_HAS_THREADS)
1984 # if defined (ACE_HAS_PTHREADS)
1985 # if defined (ACE_LACKS_PTHREAD_MUTEX_DESTROY)
1987 ACE_NOTSUP_RETURN (-1);
1990 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m
),
1992 # endif /* ACE_LACKS_PTHREAD_MUTEX_DESTROY */
1993 # elif defined (ACE_HAS_STHREADS)
1995 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m
), result
), int, -1);
1996 # elif defined (ACE_HAS_WTHREADS)
2000 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m
->proc_mutex_
),
2004 return ACE_OS::thread_mutex_destroy (&m
->thr_mutex_
);
2010 # elif defined (ACE_VXWORKS)
2011 return ::semDelete (*m
) == OK
? 0 : -1;
2012 # endif /* Threads variety case */
2015 ACE_NOTSUP_RETURN (-1);
2016 #endif /* ACE_HAS_THREADS */
2019 #if defined (ACE_HAS_WCHAR)
2021 ACE_OS::mutex_init (ACE_mutex_t
*m
,
2023 const wchar_t *name
,
2024 ACE_mutexattr_t
*attributes
,
2025 LPSECURITY_ATTRIBUTES sa
,
2028 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2029 m
->type_
= lock_scope
;
2030 SECURITY_ATTRIBUTES sa_buffer
;
2031 SECURITY_DESCRIPTOR sd_buffer
;
2036 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
2037 (sa
, &sa_buffer
, &sd_buffer
),
2040 if (m
->proc_mutex_
== 0)
2041 ACE_FAIL_RETURN (-1);
2044 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
2045 ACE_OS::set_errno_to_last_error ();
2049 return ACE_OS::thread_mutex_init (&m
->thr_mutex_
,
2057 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2058 return ACE_OS::mutex_init (m
,
2060 ACE_Wide_To_Ascii (name
).char_rep (),
2064 #endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2066 #endif /* ACE_HAS_WCHAR */
2069 ACE_OS::mutex_lock (ACE_mutex_t
*m
)
2071 // ACE_OS_TRACE ("ACE_OS::mutex_lock");
2072 #if defined (ACE_HAS_THREADS)
2073 # if defined (ACE_HAS_PTHREADS)
2074 // Note, don't use "::" here since the following call is often a macro.
2076 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m
), result
),
2078 # elif defined (ACE_HAS_STHREADS)
2080 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m
), result
), int, -1);
2081 # elif defined (ACE_HAS_WTHREADS)
2085 switch (::WaitForSingleObject (m
->proc_mutex_
, INFINITE
))
2088 // Timeout can't occur, so don't bother checking...
2091 case WAIT_ABANDONED
:
2092 // We will ignore abandonments in this method
2093 // Note that we still hold the lock
2096 // This is a hack, we need to find an appropriate mapping...
2097 ACE_OS::set_errno_to_last_error ();
2101 return ACE_OS::thread_mutex_lock (&m
->thr_mutex_
);
2107 # elif defined (ACE_VXWORKS)
2108 return ::semTake (*m
, WAIT_FOREVER
) == OK
? 0 : -1;
2109 # endif /* Threads variety case */
2112 ACE_NOTSUP_RETURN (-1);
2113 #endif /* ACE_HAS_THREADS */
2117 ACE_OS::mutex_lock (ACE_mutex_t
*m
,
2120 ACE_OS_TRACE ("ACE_OS::mutex_lock");
2121 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2126 switch (::WaitForSingleObject (m
->proc_mutex_
, INFINITE
))
2129 // Timeout can't occur, so don't bother checking...
2133 case WAIT_ABANDONED
:
2135 return 0; // something goofed, but we hold the lock ...
2137 // This is a hack, we need to find an appropriate mapping...
2138 ACE_OS::set_errno_to_last_error ();
2142 return ACE_OS::thread_mutex_lock (&m
->thr_mutex_
);
2150 ACE_UNUSED_ARG (abandoned
);
2151 ACE_NOTSUP_RETURN (-1);
2152 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2156 ACE_OS::mutex_lock (ACE_mutex_t
*m
,
2157 const ACE_Time_Value
&timeout
)
2159 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
2161 # if defined (ACE_HAS_PTHREADS)
2164 // "timeout" should be an absolute time.
2166 timespec_t ts
= timeout
; // Calls ACE_Time_Value::operator timespec_t().
2168 // Note that the mutex should not be a recursive one, i.e., it
2169 // should only be a standard mutex or an error checking mutex.
2171 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m
, &ts
), result
), int, -1, result
);
2173 // We need to adjust this to make the errno values consistent.
2174 if (result
== -1 && errno
== ETIMEDOUT
)
2178 # elif defined (ACE_HAS_WTHREADS)
2179 // Note that we must convert between absolute time (which is passed
2180 // as a parameter) and relative time (which is what the system call
2182 ACE_Time_Value relative_time
= timeout
.to_relative_time ();
2187 switch (::WaitForSingleObject (m
->proc_mutex_
,
2188 relative_time
.msec ()))
2191 case WAIT_ABANDONED
:
2192 // We will ignore abandonments in this method
2193 // Note that we still hold the lock
2199 // This is a hack, we need to find an appropriate mapping...
2200 ACE_OS::set_errno_to_last_error ();
2204 ACE_NOTSUP_RETURN (-1);
2211 # elif defined (ACE_VXWORKS)
2213 // Note that we must convert between absolute time (which is passed
2214 // as a parameter) and relative time (which is what the system call
2216 ACE_Time_Value relative_time
= timeout
.to_relative_time ();
2218 int ticks_per_sec
= ::sysClkRateGet ();
2220 int ticks
= relative_time
.sec() * ticks_per_sec
+
2221 relative_time
.usec () * ticks_per_sec
/ ACE_ONE_SECOND_IN_USECS
;
2222 if (::semTake (*m
, ticks
) == ERROR
)
2224 if (errno
== S_objLib_OBJ_TIMEOUT
)
2225 // Convert the VxWorks errno to one that's common for to ACE
2228 else if (errno
== S_objLib_OBJ_UNAVAILABLE
)
2234 # endif /* ACE_HAS_PTHREADS */
2238 ACE_UNUSED_ARG (timeout
);
2239 ACE_NOTSUP_RETURN (-1);
2240 #endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
2244 ACE_OS::mutex_trylock (ACE_mutex_t
*m
)
2246 ACE_OS_TRACE ("ACE_OS::mutex_trylock");
2247 #if defined (ACE_HAS_THREADS)
2248 # if defined (ACE_HAS_PTHREADS)
2249 // Note, don't use "::" here since the following call is often a macro.
2251 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m
), result
),
2253 # elif defined (ACE_HAS_STHREADS)
2255 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m
), result
), int, -1);
2256 # elif defined (ACE_HAS_WTHREADS)
2261 // Try for 0 milliseconds - i.e. nonblocking.
2262 switch (::WaitForSingleObject (m
->proc_mutex_
, 0))
2266 case WAIT_ABANDONED
:
2267 // We will ignore abandonments in this method. Note that
2268 // we still hold the lock.
2274 ACE_OS::set_errno_to_last_error ();
2279 return ACE_OS::thread_mutex_trylock (&m
->thr_mutex_
);
2285 # elif defined (ACE_VXWORKS)
2286 if (::semTake (*m
, NO_WAIT
) == ERROR
)
2287 if (errno
== S_objLib_OBJ_UNAVAILABLE
)
2289 // couldn't get the semaphore
2297 // got the semaphore
2299 # endif /* Threads variety case */
2302 ACE_NOTSUP_RETURN (-1);
2303 #endif /* ACE_HAS_THREADS */
2307 ACE_OS::mutex_trylock (ACE_mutex_t
*m
, int &abandoned
)
2309 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2315 // Try for 0 milliseconds - i.e. nonblocking.
2316 switch (::WaitForSingleObject (m
->proc_mutex_
, 0))
2320 case WAIT_ABANDONED
:
2322 return 0; // something goofed, but we hold the lock ...
2327 ACE_OS::set_errno_to_last_error ();
2332 return ACE_OS::thread_mutex_trylock (&m
->thr_mutex_
);
2340 ACE_UNUSED_ARG (abandoned
);
2341 ACE_NOTSUP_RETURN (-1);
2342 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2346 ACE_OS::mutex_unlock (ACE_mutex_t
*m
)
2348 ACE_OS_TRACE ("ACE_OS::mutex_unlock");
2349 #if defined (ACE_HAS_THREADS)
2350 # if defined (ACE_HAS_PTHREADS)
2351 // Note, don't use "::" here since the following call is often a macro.
2353 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m
), result
),
2355 # elif defined (ACE_HAS_STHREADS)
2357 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m
), result
), int, -1);
2358 # elif defined (ACE_HAS_WTHREADS)
2362 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m
->proc_mutex_
),
2366 return ACE_OS::thread_mutex_unlock (&m
->thr_mutex_
);
2372 # elif defined (ACE_VXWORKS)
2373 return ::semGive (*m
) == OK
? 0 : -1;
2374 # endif /* Threads variety case */
2377 ACE_NOTSUP_RETURN (-1);
2378 #endif /* ACE_HAS_THREADS */
2382 ACE_OS::mutex_lock_cleanup (void *mutex
)
2384 ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
2385 #if defined (ACE_HAS_THREADS)
2386 # if defined (ACE_HAS_PTHREADS)
2387 ACE_mutex_t
*p_lock
= (ACE_mutex_t
*) mutex
;
2388 ACE_OS::mutex_unlock (p_lock
);
2390 ACE_UNUSED_ARG (mutex
);
2391 # endif /* ACE_HAS_PTHREADS */
2393 ACE_UNUSED_ARG (mutex
);
2394 #endif /* ACE_HAS_THREADS */
2397 /*****************************************************************************/
2399 /*****************************************************************************/
2401 /*****************************************************************************/
2403 /*****************************************************************************/
2407 int ACE_event_t::lock ()
2409 # if !ACE_EVENT_USE_MUTEX_PSHARED
2410 if (this->eventdata_
->type_
== USYNC_PROCESS
)
2411 return ACE_OS::sema_wait (&this->lock_
);
2413 return ACE_OS::mutex_lock (&this->eventdata_
->lock_
);
2416 int ACE_event_t::unlock ()
2418 # if !ACE_EVENT_USE_MUTEX_PSHARED
2419 if (this->eventdata_
->type_
== USYNC_PROCESS
)
2420 return ACE_OS::sema_post (&this->lock_
);
2422 return ACE_OS::mutex_unlock (&this->eventdata_
->lock_
);
2425 int ACE_event_t::wake_one ()
2427 # if !ACE_EVENT_USE_COND_PSHARED
2428 if (this->eventdata_
->type_
== USYNC_PROCESS
)
2430 if (ACE_OS::sema_post (&this->semaphore_
) != 0)
2435 if (ACE_OS::cond_signal (&this->eventdata_
->condition_
) != 0)
2440 #endif /* ACE_WIN32 */
2443 ACE_OS::event_destroy (ACE_event_t
*event
)
2445 #if defined (ACE_WIN32)
2446 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event
), ace_result_
), int, -1);
2447 #elif defined (ACE_HAS_THREADS)
2448 if (!event
->eventdata_
)
2454 // mutex_destroy()/cond_destroy() are called in a loop if the object
2455 // is BUSY. This avoids conditions where we fail to destroy these
2456 // objects because at time of destroy they were just being used in
2457 // another thread possibly causing deadlocks later on if they keep
2458 // being used after we're gone.
2460 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2465 # if ACE_EVENT_USE_MUTEX_PSHARED
2466 // First destroy the mutex so locking after this will return
2468 while ((r1
= ACE_OS::mutex_destroy (&event
->eventdata_
->lock_
)) == -1
2470 ACE_OS::thr_yield ();
2472 r1
= ACE_OS::sema_destroy (&event
->lock_
);
2475 # if ACE_EVENT_USE_COND_PSHARED
2476 // Now fix event to manual reset, raise signal and broadcast
2477 // until is's possible to destroy the condition.
2478 event
->eventdata_
->manual_reset_
= 1;
2479 while ((r2
= ACE_OS::cond_destroy (&event
->eventdata_
->condition_
))
2480 == -1 && errno
== EBUSY
)
2482 event
->eventdata_
->is_signaled_
= 1;
2483 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2485 ACE_OS::thr_yield ();
2488 r2
= ACE_OS::sema_destroy (&event
->semaphore_
);
2490 ACE_OS::munmap (event
->eventdata_
, sizeof (ACE_eventdata_t
));
2491 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (event
->name_
));
2492 # if defined (ACE_HAS_ALLOC_HOOKS)
2493 ACE_Allocator::instance ()->free (event
->name_
);
2495 ACE_OS::free (event
->name_
);
2496 # endif /* ACE_HAS_ALLOC_HOOKS */
2497 return r1
!= 0 || r2
!= 0 ? -1 : 0;
2499 else // !name_ (not owned by this process)
2501 ACE_OS::munmap (event
->eventdata_
, sizeof (ACE_eventdata_t
));
2503 # if !ACE_EVENT_USE_MUTEX_PSHARED
2504 ACE_OS::sema_destroy (&event
->lock_
);
2507 # if !ACE_EVENT_USE_COND_PSHARED
2508 return ACE_OS::sema_destroy (&event
->semaphore_
);
2512 else // USYNC_THREAD:
2515 // First destroy the mutex so locking after this will return errors.
2516 while ((r1
= ACE_OS::mutex_destroy (&event
->eventdata_
->lock_
)) == -1
2518 ACE_OS::thr_yield ();
2520 // Now fix event to manual reset, raise signal and broadcast until
2521 // it's possible to destroy the condition.
2522 event
->eventdata_
->manual_reset_
= 1;
2523 while ((r2
= ACE_OS::cond_destroy (&event
->eventdata_
->condition_
)) == -1
2526 event
->eventdata_
->is_signaled_
= 1;
2527 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2529 ACE_OS::thr_yield ();
2532 delete event
->eventdata_
;
2533 return r1
!= 0 || r2
!= 0 ? -1 : 0;
2538 ACE_UNUSED_ARG (event
);
2539 ACE_NOTSUP_RETURN (-1);
2540 #endif /* ACE_WIN32 */
2543 ACE_ALLOC_HOOK_DEFINE (ACE_eventdata_t
)
2547 int eventdata_init (ACE_eventdata_t
*evtdata
, int type
, int manual_reset
,
2548 int initial_state
, ACE_condattr_t
*attributes
,
2549 const char *name
, void *arg
, int init_condition
= 1,
2552 evtdata
->type_
= type
;
2553 evtdata
->manual_reset_
= manual_reset
;
2554 evtdata
->is_signaled_
= initial_state
;
2555 evtdata
->auto_event_signaled_
= false;
2556 evtdata
->waiting_threads_
= 0;
2557 evtdata
->signal_count_
= 0;
2561 const int result
= attributes
?
2562 ACE_OS::cond_init (&evtdata
->condition_
, *attributes
, name
, arg
) :
2563 ACE_OS::cond_init (&evtdata
->condition_
, type
, name
, arg
);
2569 return init_mutex
? ACE_OS::mutex_init (&evtdata
->lock_
, type
, name
,
2570 (ACE_mutexattr_t
*) arg
) : 0;
2573 template <size_t N
, size_t M
>
2574 void format_name (char (&str
)[N
], const char *name
, const char (&suffix
)[M
])
2576 ACE_OS::strncpy (str
, name
, N
- M
);
2577 ACE_OS::strcat (str
, suffix
);
2580 #endif /* ACE_WIN32 */
2583 ACE_OS::event_init (ACE_event_t
*event
,
2585 ACE_condattr_t
*attributes
,
2590 LPSECURITY_ATTRIBUTES sa
)
2592 #if defined (ACE_WIN32)
2593 ACE_UNUSED_ARG (type
);
2594 ACE_UNUSED_ARG (attributes
);
2595 ACE_UNUSED_ARG (arg
);
2596 SECURITY_ATTRIBUTES sa_buffer
;
2597 SECURITY_DESCRIPTOR sd_buffer
;
2598 # if defined (ACE_HAS_WINCE)
2599 // @@todo (brunsch) This idea should be moved into ACE_OS_Win32.
2600 *event
= ::CreateEventW (ACE_OS::default_win32_security_attributes_r
2601 (sa
, &sa_buffer
, &sd_buffer
),
2604 ACE_Ascii_To_Wide (name
).wchar_rep ());
2605 # else /* ACE_HAS_WINCE */
2606 *event
= ::CreateEventA (ACE_OS::default_win32_security_attributes_r
2607 (sa
, &sa_buffer
, &sd_buffer
),
2611 # endif /* ACE_HAS_WINCE */
2613 ACE_FAIL_RETURN (-1);
2616 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
2617 ACE_OS::set_errno_to_last_error ();
2620 #elif defined (ACE_HAS_THREADS)
2621 ACE_UNUSED_ARG (sa
);
2623 event
->eventdata_
= 0;
2625 if (type
== USYNC_PROCESS
)
2627 const char *name_p
= name
;
2628 # if defined (ACE_SHM_OPEN_REQUIRES_ONE_SLASH)
2629 char adj_name
[MAXPATHLEN
];
2633 ACE_OS::strsncpy (&adj_name
[1], name
, MAXPATHLEN
-1);
2636 # endif /* ACE_SHM_OPEN_REQUIRES_ONE_SLASH */
2639 // Let's see if the shared memory entity already exists.
2640 ACE_HANDLE fd
= ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p
),
2641 O_RDWR
| O_CREAT
| O_EXCL
,
2642 ACE_DEFAULT_FILE_PERMS
);
2643 if (fd
== ACE_INVALID_HANDLE
)
2645 if (errno
== EEXIST
)
2646 fd
= ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p
),
2648 ACE_DEFAULT_FILE_PERMS
);
2649 if (fd
== ACE_INVALID_HANDLE
) // Still can't get it.
2654 // We own this shared memory object! Let's set its size.
2655 if (ACE_OS::ftruncate (fd
, sizeof (ACE_eventdata_t
)) == -1)
2663 void *const mapped
= ACE_OS::mmap (0, sizeof (ACE_eventdata_t
),
2664 PROT_RDWR
, MAP_SHARED
, fd
);
2665 ACE_eventdata_t
*evtdata
= reinterpret_cast<ACE_eventdata_t
*> (mapped
);
2667 if (evtdata
== MAP_FAILED
)
2670 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
2674 event
->eventdata_
= evtdata
;
2678 event
->name_
= ACE_OS::strdup (name_p
);
2679 if (event
->name_
== 0 ||
2680 eventdata_init (event
->eventdata_
, USYNC_PROCESS
, manual_reset
,
2681 initial_state
, attributes
, name
, arg
,
2682 ACE_EVENT_USE_COND_PSHARED
,
2683 ACE_EVENT_USE_MUTEX_PSHARED
) != 0)
2685 ACE_OS::munmap (evtdata
, sizeof (ACE_eventdata_t
));
2686 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
2692 # if !ACE_EVENT_USE_COND_PSHARED
2693 char sem_name
[128] = {};
2694 format_name (sem_name
, name
, "._ACE_EVTSEM_");
2695 result
= ACE_OS::sema_init (&event
->semaphore_
, 0, type
, attributes
,
2699 # if !ACE_EVENT_USE_MUTEX_PSHARED
2702 char lck_name
[128] = {};
2703 format_name (lck_name
, name
, "._ACE_EVTLCK_");
2704 result
= ACE_OS::sema_init (&event
->lock_
, owner
, type
, attributes
,
2709 # if !ACE_EVENT_USE_COND_PSHARED || !ACE_EVENT_USE_MUTEX_PSHARED
2710 if (result
!= 0 && owner
)
2711 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
2718 ACE_NEW_RETURN (event
->eventdata_
, ACE_eventdata_t
, -1);
2719 return eventdata_init (event
->eventdata_
, USYNC_THREAD
, manual_reset
,
2720 initial_state
, attributes
, name
, arg
);
2723 ACE_UNUSED_ARG (event
);
2724 ACE_UNUSED_ARG (manual_reset
);
2725 ACE_UNUSED_ARG (initial_state
);
2726 ACE_UNUSED_ARG (type
);
2727 ACE_UNUSED_ARG (attributes
);
2728 ACE_UNUSED_ARG (name
);
2729 ACE_UNUSED_ARG (arg
);
2730 ACE_UNUSED_ARG (sa
);
2731 ACE_NOTSUP_RETURN (-1);
2732 #endif /* ACE_WIN32 */
2736 ACE_OS::event_pulse (ACE_event_t
*event
)
2738 #if defined (ACE_WIN32)
2739 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event
), ace_result_
), int, -1);
2740 #elif defined (ACE_HAS_THREADS)
2742 int result
= event
->lock ();
2746 if (event
->eventdata_
->waiting_threads_
> 0)
2748 if (event
->eventdata_
->manual_reset_
== 1)
2750 // Wakeup all waiters.
2751 # if !ACE_EVENT_USE_COND_PSHARED
2752 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2754 event
->eventdata_
->signal_count_
=
2755 event
->eventdata_
->waiting_threads_
;
2756 for (unsigned long i
= 0;
2757 i
< event
->eventdata_
->signal_count_
; ++i
)
2758 if (ACE_OS::sema_post (&event
->semaphore_
) != 0)
2760 event
->eventdata_
->signal_count_
= 0;
2766 while (event
->eventdata_
->signal_count_
!= 0 &&
2767 event
->eventdata_
->waiting_threads_
!= 0)
2768 ACE_OS::thr_yield ();
2772 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2778 event
->eventdata_
->signal_count_
=
2779 event
->eventdata_
->waiting_threads_
;
2781 else // Auto-reset event: wakeup one waiter.
2783 if (event
->wake_one () != 0)
2789 event
->eventdata_
->auto_event_signaled_
= true;
2793 event
->eventdata_
->is_signaled_
= 0;
2795 if (event
->unlock () != 0)
2803 ACE_UNUSED_ARG (event
);
2804 ACE_NOTSUP_RETURN (-1);
2805 #endif /* ACE_WIN32 */
2809 ACE_OS::event_reset (ACE_event_t
*event
)
2811 #if defined (ACE_WIN32)
2812 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event
), ace_result_
), int, -1);
2813 #elif defined (ACE_HAS_THREADS)
2814 if (event
->lock () != 0)
2817 event
->eventdata_
->is_signaled_
= 0;
2818 event
->eventdata_
->auto_event_signaled_
= false;
2820 return event
->unlock ();
2822 ACE_UNUSED_ARG (event
);
2823 ACE_NOTSUP_RETURN (-1);
2824 #endif /* ACE_WIN32 */
2828 ACE_OS::event_signal (ACE_event_t
*event
)
2830 #if defined (ACE_WIN32)
2831 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event
), ace_result_
), int, -1);
2832 #elif defined (ACE_HAS_THREADS)
2834 int result
= event
->lock ();
2839 if (event
->eventdata_
->manual_reset_
== 1)
2842 # if !ACE_EVENT_USE_COND_PSHARED
2843 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2845 if (ACE_OS::sema_post (&event
->semaphore_
) != 0)
2853 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2860 event
->eventdata_
->is_signaled_
= 1;
2862 else // Auto-reset event
2864 if (event
->eventdata_
->waiting_threads_
== 0)
2865 event
->eventdata_
->is_signaled_
= 1;
2866 else if (event
->wake_one () != 0)
2872 event
->eventdata_
->auto_event_signaled_
= true;
2875 if (event
->unlock () != 0)
2883 ACE_UNUSED_ARG (event
);
2884 ACE_NOTSUP_RETURN (-1);
2885 #endif /* ACE_WIN32 */
2889 ACE_OS::event_timedwait (ACE_event_t
*event
,
2890 ACE_Time_Value
*timeout
,
2891 int use_absolute_time
)
2893 #if defined (ACE_WIN32)
2896 if (timeout
&& *timeout
== ACE_Time_Value::zero
)
2898 result
= ::WaitForSingleObject (*event
, 0);
2901 // Wait for upto <relative_time> number of milliseconds. Note
2902 // that we must convert between absolute time (which is passed
2903 // as a parameter) and relative time (which is what
2904 // WaitForSingleObjects() expects).
2905 // <timeout> parameter is given in absolute or relative value
2906 // depending on parameter <use_absolute_time>.
2907 int msec_timeout
= 0;
2910 msec_timeout
= INFINITE
;
2912 else if (use_absolute_time
)
2914 // Time is given in absolute time, we should use
2915 // gettimeofday() to calculate relative time
2916 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
2918 // Watchout for situations where a context switch has caused
2919 // the current time to be > the timeout. Thanks to Norbert
2920 // Rapp <NRapp@nexus-informatics.de> for pointing this.
2921 if (relative_time
> ACE_Time_Value::zero
)
2922 msec_timeout
= relative_time
.msec ();
2925 // time is given in relative time, just convert it into
2926 // milliseconds and use it
2927 msec_timeout
= timeout
->msec ();
2928 result
= ::WaitForSingleObject (*event
, msec_timeout
);
2939 // This is a hack, we need to find an appropriate mapping...
2940 ACE_OS::set_errno_to_last_error ();
2943 #elif defined (ACE_HAS_THREADS)
2945 int result
= event
->lock ();
2950 if (event
->eventdata_
->is_signaled_
== 1)
2952 if (event
->eventdata_
->manual_reset_
== 0)
2954 // AUTO: reset state
2955 event
->eventdata_
->is_signaled_
= 0;
2956 event
->eventdata_
->auto_event_signaled_
= false;
2959 else // event is currently not signaled
2961 ++event
->eventdata_
->waiting_threads_
;
2963 ACE_Time_Value
*absolute_timeout
= timeout
, converted_time
;
2965 // cond_timedwait() expects absolute time, check <use_absolute_time> flag
2966 if (timeout
&& use_absolute_time
== 0)
2968 converted_time
= timeout
->to_absolute_time ();
2969 absolute_timeout
= &converted_time
;
2972 while (event
->eventdata_
->is_signaled_
== 0 &&
2973 !event
->eventdata_
->auto_event_signaled_
)
2974 # if !ACE_EVENT_USE_COND_PSHARED
2975 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2977 if (event
->unlock () != 0)
2979 --event
->eventdata_
->waiting_threads_
;
2983 if (ACE_OS::sema_wait (&event
->semaphore_
, absolute_timeout
) != 0)
2986 error
= (errno
== ETIMEDOUT
) // Semaphores use ETIMEDOUT (POSIX)
2990 bool signalled
= false;
2991 if (result
== 0 && event
->eventdata_
->signal_count_
> 0)
2993 --event
->eventdata_
->signal_count_
;
2997 if (event
->lock () != 0)
2999 --event
->eventdata_
->waiting_threads_
;
3006 if (event
->eventdata_
->manual_reset_
== 1 &&
3007 event
->eventdata_
->is_signaled_
== 1 &&
3008 ACE_OS::sema_post (&event
->semaphore_
) != 0)
3021 if (ACE_OS::cond_timedwait (&event
->eventdata_
->condition_
,
3022 &event
->eventdata_
->lock_
,
3023 absolute_timeout
) != 0)
3030 if (event
->eventdata_
->signal_count_
> 0)
3032 --event
->eventdata_
->signal_count_
;
3037 // Reset the auto_event_signaled_ to false now that we have woken up.
3038 if (event
->eventdata_
->auto_event_signaled_
)
3039 event
->eventdata_
->auto_event_signaled_
= false;
3041 --event
->eventdata_
->waiting_threads_
;
3044 if (event
->unlock () != 0)
3052 ACE_UNUSED_ARG (event
);
3053 ACE_UNUSED_ARG (timeout
);
3054 ACE_UNUSED_ARG (use_absolute_time
);
3055 ACE_NOTSUP_RETURN (-1);
3056 #endif /* ACE_WIN32 */
3059 /*****************************************************************************/
3061 /*****************************************************************************/
3064 ACE_OS::lwp_getparams (ACE_Sched_Params
&sched_params
)
3066 #if defined (ACE_HAS_STHREADS) || defined (sun)
3067 // Get the class TS and RT class IDs.
3070 if (ACE_OS::scheduling_class ("RT", rt_id
) == -1
3071 || ACE_OS::scheduling_class ("TS", ts_id
) == -1)
3074 // Get this LWP's scheduling parameters.
3076 // The following is just to avoid Purify warnings about unitialized
3078 ACE_OS::memset (&pcparms
, 0, sizeof pcparms
);
3079 pcparms
.pc_cid
= PC_CLNULL
;
3081 if (ACE_OS::priority_control (P_LWPID
,
3084 (char *) &pcparms
) == -1)
3086 else if (pcparms
.pc_cid
== rt_id
)
3090 ACE_OS::memcpy (&rtparms
, pcparms
.pc_clparms
, sizeof rtparms
);
3092 sched_params
.policy (ACE_SCHED_FIFO
);
3093 sched_params
.priority (rtparms
.rt_pri
);
3094 sched_params
.scope (ACE_SCOPE_THREAD
);
3095 ACE_Time_Value
quantum (rtparms
.rt_tqsecs
,
3096 rtparms
.rt_tqnsecs
== RT_TQINF
3097 ? 0 : rtparms
.rt_tqnsecs
* 1000);
3098 sched_params
.quantum (quantum
);
3101 else if (pcparms
.pc_cid
== ts_id
)
3105 ACE_OS::memcpy (&tsparms
, pcparms
.pc_clparms
, sizeof tsparms
);
3107 sched_params
.policy (ACE_SCHED_OTHER
);
3108 sched_params
.priority (tsparms
.ts_upri
);
3109 sched_params
.scope (ACE_SCOPE_THREAD
);
3115 #else /* ! ACE_HAS_STHREADS && ! sun */
3116 ACE_UNUSED_ARG (sched_params
);
3117 ACE_NOTSUP_RETURN (-1);
3118 #endif /* ! ACE_HAS_STHREADS && ! sun */
3122 ACE_OS::lwp_setparams (const ACE_Sched_Params
&sched_params
)
3124 #if defined (ACE_HAS_STHREADS) || defined (sun)
3125 ACE_Sched_Params
lwp_params (sched_params
);
3126 lwp_params
.scope (ACE_SCOPE_LWP
);
3127 return ACE_OS::sched_params (lwp_params
);
3128 #else /* ! ACE_HAS_STHREADS && ! sun */
3129 ACE_UNUSED_ARG (sched_params
);
3130 ACE_NOTSUP_RETURN (-1);
3131 #endif /* ! ACE_HAS_STHREADS && ! sun */
3134 #if defined ACE_HAS_THREADS && defined ACE_LACKS_RWLOCK_T
3137 UniqueName (int type
, const void *addr
)
3140 if (type
== USYNC_THREAD
)
3142 this->named_
= false;
3145 this->named_
= true;
3147 ACE_UNUSED_ARG (type
);
3149 ACE_OS::unique_name (addr
, &this->buffer_
[0], ACE_UNIQUE_NAME_LEN
);
3152 operator const ACE_TCHAR
* () const
3160 return &this->buffer_
[0];
3163 ACE_TCHAR buffer_
[ACE_UNIQUE_NAME_LEN
];
3169 enum RWLockCleanup
{RWLC_CondAttr
, RWLC_Lock
, RWLC_CondReaders
, RWLC_CondWriters
};
3171 struct RWLockCleaner
{
3172 RWLockCleaner (ACE_condattr_t
&attr
, ACE_rwlock_t
*rw
)
3173 : state_ (RWLC_CondAttr
)
3180 ACE_Errno_Guard
error (errno
);
3181 switch (this->state_
)
3183 case RWLC_CondWriters
:
3184 ACE_OS::cond_destroy (&this->rw_
->waiting_writers_
);
3186 case RWLC_CondReaders
:
3187 ACE_OS::cond_destroy (&this->rw_
->waiting_readers_
);
3190 ACE_OS::mutex_destroy (&this->rw_
->lock_
);
3193 ACE_OS::condattr_destroy (this->attr_
);
3197 RWLockCleanup state_
;
3198 ACE_condattr_t
&attr_
;
3204 #if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T)
3206 ACE_OS::rwlock_init (ACE_rwlock_t
*rw
,
3211 // ACE_OS_TRACE ("ACE_OS::rwlock_init");
3212 # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
3213 // NT, POSIX, and VxWorks don't support this natively.
3215 ACE_condattr_t attributes
;
3216 if (ACE_OS::condattr_init (attributes
, type
) != 0)
3219 RWLockCleaner
cleanup (attributes
, rw
);
3221 if (ACE_OS::mutex_init (&rw
->lock_
, type
, UniqueName (type
, &rw
->lock_
),
3222 (ACE_mutexattr_t
*) arg
) != 0)
3225 cleanup
.state_
= RWLC_Lock
;
3226 if (ACE_OS::cond_init (&rw
->waiting_readers_
, attributes
,
3227 UniqueName (type
, &rw
->waiting_readers_
), arg
) != 0)
3230 cleanup
.state_
= RWLC_CondReaders
;
3231 if (ACE_OS::cond_init (&rw
->waiting_writers_
, attributes
,
3232 UniqueName (type
, &rw
->waiting_writers_
), arg
) != 0)
3235 cleanup
.state_
= RWLC_CondWriters
;
3236 if (ACE_OS::cond_init (&rw
->waiting_important_writer_
, attributes
,
3237 UniqueName (type
, &rw
->waiting_important_writer_
),
3241 cleanup
.state_
= RWLC_CondAttr
;
3243 rw
->num_waiting_writers_
= 0;
3244 rw
->num_waiting_readers_
= 0;
3245 rw
->important_writer_
= false;
3248 ACE_UNUSED_ARG (rw
);
3249 ACE_UNUSED_ARG (type
);
3250 ACE_UNUSED_ARG (arg
);
3251 ACE_NOTSUP_RETURN (-1);
3252 # endif /* ACE_HAS_THREADS */
3254 #endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
3257 ACE_OS::sched_params (const ACE_Sched_Params
&sched_params
,
3260 ACE_OS_TRACE ("ACE_OS::sched_params");
3261 #if defined (ACE_HAS_STHREADS)
3262 return ACE_OS::set_scheduling_params (sched_params
, id
);
3263 #elif defined (ACE_HAS_PTHREADS) && \
3264 (!defined (ACE_LACKS_SETSCHED) || \
3265 defined (ACE_HAS_PTHREAD_SCHEDPARAM))
3266 if (sched_params
.quantum () != ACE_Time_Value::zero
)
3268 // quantums not supported
3273 // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
3274 // providing this code for 1003.1c PThreads. Please note that this
3275 // has only been tested for POSIX 1003.1c threads, and may cause
3276 // problems with other PThreads flavors!
3278 struct sched_param param
;
3279 param
.sched_priority
= sched_params
.priority ();
3281 if (sched_params
.scope () == ACE_SCOPE_PROCESS
)
3283 # if defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3284 ACE_UNUSED_ARG (id
);
3285 ACE_NOTSUP_RETURN (-1);
3286 # else /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3287 int result
= ::sched_setscheduler (id
== ACE_SELF
? 0 : id
,
3288 sched_params
.policy (),
3289 ¶m
) == -1 ? -1 : 0;
3291 # endif /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3293 else if (sched_params
.scope () == ACE_SCOPE_THREAD
)
3295 ACE_thread_t thr_id
= ACE_OS::thr_self ();
3298 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id
,
3299 sched_params
.policy (),
3305 // We need to be able to set LWP priorities on Suns, even without
3306 // ACE_HAS_STHREADS, to obtain preemption.
3307 else if (sched_params
.scope () == ACE_SCOPE_LWP
)
3308 return ACE_OS::set_scheduling_params (sched_params
, id
);
3310 else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
3316 #elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
3318 // PharLap ETS can act on the current thread - it can set the
3319 // quantum also, unlike Win32. All this only works on the RT
3321 # if defined (ACE_HAS_PHARLAP_RT)
3323 ACE_NOTSUP_RETURN (-1);
3325 # if !defined (ACE_PHARLAP_LABVIEW_RT)
3326 if (sched_params
.quantum() != ACE_Time_Value::zero
)
3327 EtsSetTimeSlice (sched_params
.quantum().msec());
3332 if (sched_params
.quantum () != ACE_Time_Value::zero
)
3334 // I don't know of a way to set the quantum on Win32.
3339 # endif /* ACE_HAS_PHARLAP_RT */
3341 if (sched_params
.scope () == ACE_SCOPE_THREAD
)
3344 // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
3345 // a VERY BAD THING. This include guard will allow people
3346 // to easily disable this feature in ACE.
3347 // It won't work at all for Pharlap since there's no SetPriorityClass.
3348 #if !defined (ACE_HAS_PHARLAP) && \
3349 !defined (ACE_DISABLE_WIN32_INCREASE_PRIORITY)
3350 // Set the priority class of this process to the REALTIME process class
3351 // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL.
3352 if (!::SetPriorityClass (::GetCurrentProcess (),
3353 (sched_params
.policy () == ACE_SCHED_FIFO
||
3354 sched_params
.policy () == ACE_SCHED_RR
)
3355 ? REALTIME_PRIORITY_CLASS
3356 : NORMAL_PRIORITY_CLASS
))
3358 ACE_OS::set_errno_to_last_error ();
3361 #endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
3363 // Now that we have set the priority class of the process, set the
3364 // priority of the current thread to the desired value.
3365 return ACE_OS::thr_setprio (sched_params
.priority ());
3367 else if (sched_params
.scope () == ACE_SCOPE_PROCESS
)
3370 # if defined (ACE_HAS_PHARLAP_RT)
3371 ACE_NOTSUP_RETURN (-1);
3374 = ::OpenProcess (PROCESS_SET_INFORMATION
,
3376 id
== ACE_SELF
? ::GetCurrentProcessId() : id
);
3379 ACE_OS::set_errno_to_last_error();
3382 // There is no way for us to set the priority of the thread when we
3383 // are setting the priority of a different process. So just ignore
3384 // the priority argument when ACE_SCOPE_PROCESS is specified.
3385 // Setting the priority class will automatically increase the base
3386 // priority of all the threads within a process while maintaining the
3387 // relative priorities of the threads within it.
3388 if (!::SetPriorityClass (hProcess
,
3389 (sched_params
.policy () == ACE_SCHED_FIFO
||
3390 sched_params
.policy () == ACE_SCHED_RR
)
3391 ? REALTIME_PRIORITY_CLASS
3392 : NORMAL_PRIORITY_CLASS
))
3394 ACE_OS::set_errno_to_last_error ();
3395 ::CloseHandle (hProcess
);
3398 ::CloseHandle (hProcess
);
3400 #endif /* ACE_HAS_PHARLAP_RT */
3408 #elif defined (ACE_VXWORKS)
3409 ACE_UNUSED_ARG (id
);
3411 // There is only one class of priorities on VxWorks, and no time
3412 // quanta. So, just set the current thread's priority.
3414 if (sched_params
.policy () != ACE_SCHED_FIFO
3415 || sched_params
.scope () != ACE_SCOPE_PROCESS
3416 || sched_params
.quantum () != ACE_Time_Value::zero
)
3422 // Set the thread priority on the current thread.
3423 return ACE_OS::thr_setprio (sched_params
.priority ());
3425 ACE_UNUSED_ARG (sched_params
);
3426 ACE_UNUSED_ARG (id
);
3427 ACE_NOTSUP_RETURN (-1);
3428 #endif /* ACE_HAS_STHREADS */
3432 ACE_OS::scheduling_class (const char *class_name
, ACE_id_t
&id
)
3434 #if defined (ACE_HAS_PRIOCNTL)
3435 // Get the priority class ID.
3437 // The following is just to avoid Purify warnings about unitialized
3439 ACE_OS::memset (&pcinfo
, 0, sizeof pcinfo
);
3441 ACE_OS::strcpy (pcinfo
.pc_clname
, class_name
);
3442 if (ACE_OS::priority_control (P_ALL
/* ignored */,
3443 P_MYID
/* ignored */,
3445 (char *) &pcinfo
) == -1)
3454 #else /* ! ACE_HAS_PRIOCNTL */
3455 ACE_UNUSED_ARG (class_name
);
3456 ACE_UNUSED_ARG (id
);
3457 ACE_NOTSUP_RETURN (-1);
3458 #endif /* ! ACE_HAS_PRIOCNTL */
3462 ACE_OS::set_scheduling_params (const ACE_Sched_Params
&sched_params
,
3465 #if defined (ACE_HAS_PRIOCNTL)
3466 // Set priority class, priority, and quantum of this LWP or process as
3467 // specified in sched_params.
3469 // Get the priority class ID.
3471 if (ACE_OS::scheduling_class (sched_params
.policy() == ACE_SCHED_OTHER
?
3473 "RT", class_id
) == -1)
3479 // The following is just to avoid Purify warnings about unitialized
3481 ACE_OS::memset (&pcparms
, 0, sizeof pcparms
);
3483 pcparms
.pc_cid
= class_id
;
3485 if (sched_params
.policy () == ACE_SCHED_OTHER
&&
3486 sched_params
.quantum () == ACE_Time_Value::zero
)
3487 // SunOS doesn't support non-zero quantums in time-sharing class: use
3488 // real-time class instead.
3491 // The following is just to avoid Purify warnings about unitialized
3493 ACE_OS::memset (&tsparms
, 0, sizeof tsparms
);
3495 // Don't change ts_uprilim (user priority limit)
3496 tsparms
.ts_uprilim
= TS_NOCHANGE
;
3497 tsparms
.ts_upri
= sched_params
.priority ();
3499 // Package up the TS class ID and parameters for the
3500 // priority_control () call.
3501 ACE_OS::memcpy (pcparms
.pc_clparms
, &tsparms
, sizeof tsparms
);
3503 else if (sched_params
.policy () == ACE_SCHED_FIFO
||
3504 (sched_params
.policy () == ACE_SCHED_RR
&&
3505 sched_params
.quantum () != ACE_Time_Value::zero
))
3506 // must have non-zero quantum for RR, to make it meaningful
3507 // A zero quantum with FIFO has special significance: it actually
3508 // means infinite time quantum, i.e., run-to-completion.
3511 // The following is just to avoid Purify warnings about unitialized
3513 ACE_OS::memset (&rtparms
, 0, sizeof rtparms
);
3515 rtparms
.rt_pri
= sched_params
.priority ();
3517 if (sched_params
.quantum () == ACE_Time_Value::zero
)
3519 // rtparms.rt_tqsecs is ignored with RT_TQINF
3520 rtparms
.rt_tqnsecs
= RT_TQINF
;
3524 rtparms
.rt_tqsecs
= (ulong
) sched_params
.quantum ().sec ();
3525 rtparms
.rt_tqnsecs
= sched_params
.quantum ().usec () * 1000;
3528 // Package up the RT class ID and parameters for the
3529 // priority_control () call.
3530 ACE_OS::memcpy (pcparms
.pc_clparms
, &rtparms
, sizeof rtparms
);
3538 if (ACE_OS::priority_control ((idtype_t
) (sched_params
.scope () == ACE_SCOPE_THREAD
3540 : sched_params
.scope ()),
3543 (char *) &pcparms
) < 0)
3545 return ACE_OS::last_error ();
3549 #else /* ! ACE_HAS_PRIOCNTL */
3550 ACE_UNUSED_ARG (sched_params
);
3551 ACE_UNUSED_ARG (id
);
3552 ACE_NOTSUP_RETURN (-1);
3553 #endif /* ! ACE_HAS_PRIOCNTL */
3557 ACE_OS::thr_create (ACE_THR_FUNC func
,
3560 ACE_thread_t
*thr_id
,
3561 ACE_hthread_t
*thr_handle
,
3565 ACE_Base_Thread_Adapter
*thread_adapter
,
3566 const char** thr_name
)
3568 ACE_OS_TRACE ("ACE_OS::thr_create");
3570 if (ACE_BIT_DISABLED (flags
, THR_DETACHED
) &&
3571 ACE_BIT_DISABLED (flags
, THR_JOINABLE
))
3572 ACE_SET_BITS (flags
, THR_JOINABLE
);
3574 #if defined (ACE_NO_THREAD_ADAPTER)
3575 # define ACE_THREAD_FUNCTION func
3576 # define ACE_THREAD_ARGUMENT args
3577 #else /* ! defined (ACE_NO_THREAD_ADAPTER) */
3578 # define ACE_THREAD_FUNCTION thread_args->entry_point ()
3579 # define ACE_THREAD_ARGUMENT thread_args
3580 #endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
3582 ACE_Base_Thread_Adapter
*thread_args
= 0;
3583 if (thread_adapter
== 0)
3584 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
3585 ACE_NEW_RETURN (thread_args
,
3586 ACE_OS_Thread_Adapter (func
, args
,
3587 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
,
3588 ACE_OS_Object_Manager::seh_except_selector(),
3589 ACE_OS_Object_Manager::seh_except_handler(),
3593 ACE_NEW_RETURN (thread_args
,
3594 ACE_OS_Thread_Adapter (func
, args
,
3595 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
,
3599 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
3601 thread_args
= thread_adapter
;
3603 std::unique_ptr
<ACE_Base_Thread_Adapter
> auto_thread_args
;
3605 if (thread_adapter
== 0)
3606 ACE_auto_ptr_reset (auto_thread_args
,
3609 #if defined (ACE_HAS_THREADS)
3611 // *** Set Stack Size
3612 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3613 if (stacksize
< ACE_NEEDS_HUGE_THREAD_STACKSIZE
)
3614 stacksize
= ACE_NEEDS_HUGE_THREAD_STACKSIZE
;
3615 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
3617 ACE_thread_t tmp_thr
;
3621 ACE_hthread_t tmp_handle
;
3622 if (thr_handle
== 0)
3623 thr_handle
= &tmp_handle
;
3625 # if defined (ACE_HAS_PTHREADS)
3627 # if defined (ACE_PTHREAD_ATTR_T_INITIALIZE)
3628 /* Tests show that VxWorks 6.x pthread lib does not only
3629 * require zeroing of mutex/condition objects to function correctly
3630 * but also of the attribute objects.
3632 pthread_attr_t attr
= {0};
3634 pthread_attr_t attr
;
3636 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr
), result
) != 0)
3641 size_t size
= stacksize
;
3643 # if defined (PTHREAD_STACK_MIN)
3644 if (size
< static_cast <size_t> (PTHREAD_STACK_MIN
))
3645 size
= PTHREAD_STACK_MIN
;
3646 # endif /* PTHREAD_STACK_MIN */
3648 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
3649 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3652 result
= ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr
, stack
, size
), result
);
3654 result
= ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr
, size
), result
);
3657 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr
, size
), result
) == -1)
3658 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3660 ::pthread_attr_destroy (&attr
);
3664 ACE_UNUSED_ARG (size
);
3665 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
3668 // *** Set Stack Address
3669 # if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3670 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
3673 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr
, stack
), result
) != 0)
3675 ::pthread_attr_destroy (&attr
);
3680 ACE_UNUSED_ARG (stack
);
3681 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3682 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3684 // *** Deal with various attributes
3687 // *** Set Detach state
3688 # if !defined (ACE_LACKS_SETDETACH)
3689 if (ACE_BIT_ENABLED (flags
, THR_DETACHED
)
3690 || ACE_BIT_ENABLED (flags
, THR_JOINABLE
))
3692 int dstate
= PTHREAD_CREATE_JOINABLE
;
3694 if (ACE_BIT_ENABLED (flags
, THR_DETACHED
))
3695 dstate
= PTHREAD_CREATE_DETACHED
;
3697 if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr
, dstate
),
3700 ::pthread_attr_destroy (&attr
);
3705 // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
3706 // call ::pthread_detach () below. If THR_DETACHED is not
3707 // enabled, we call ::pthread_detach () in the Thread_Manager,
3708 // after joining with the thread.
3709 # endif /* ACE_LACKS_SETDETACH */
3712 # if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3713 // If we wish to set the priority explicitly, we have to enable
3714 // explicit scheduling, and a policy, too.
3715 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
3717 ACE_SET_BITS (flags
, THR_EXPLICIT_SCHED
);
3718 if (ACE_BIT_DISABLED (flags
, THR_SCHED_FIFO
)
3719 && ACE_BIT_DISABLED (flags
, THR_SCHED_RR
)
3720 && ACE_BIT_DISABLED (flags
, THR_SCHED_DEFAULT
))
3721 ACE_SET_BITS (flags
, THR_SCHED_DEFAULT
);
3724 if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
)
3725 || ACE_BIT_ENABLED (flags
, THR_SCHED_RR
)
3726 || ACE_BIT_ENABLED (flags
, THR_SCHED_DEFAULT
))
3730 # if defined (ACE_HAS_ONLY_SCHED_OTHER)
3731 // SunOS, thru version 5.6, only supports SCHED_OTHER.
3732 spolicy
= SCHED_OTHER
;
3733 # elif defined (ACE_HAS_ONLY_SCHED_FIFO)
3734 // NonStop OSS standard pthread supports only SCHED_FIFO.
3735 spolicy
= SCHED_FIFO
;
3737 // Make sure to enable explicit scheduling, in case we didn't
3738 // enable it above (for non-default priority).
3739 ACE_SET_BITS (flags
, THR_EXPLICIT_SCHED
);
3741 if (ACE_BIT_ENABLED (flags
, THR_SCHED_DEFAULT
))
3742 spolicy
= SCHED_OTHER
;
3743 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
))
3744 spolicy
= SCHED_FIFO
;
3745 # if defined (SCHED_IO)
3746 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_IO
))
3749 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_IO
))
3754 # endif /* SCHED_IO */
3758 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3760 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr
, spolicy
),
3764 ::pthread_attr_destroy (&attr
);
3769 // *** Set Priority (use reasonable default priorities)
3770 # if defined(ACE_HAS_PTHREADS)
3771 // If we wish to explicitly set a scheduling policy, we also
3772 // have to specify a priority. We choose a "middle" priority as
3773 // default. Maybe this is also necessary on other POSIX'ish
3775 if ((ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
)
3776 || ACE_BIT_ENABLED (flags
, THR_SCHED_RR
)
3777 || ACE_BIT_ENABLED (flags
, THR_SCHED_DEFAULT
))
3778 && priority
== ACE_DEFAULT_THREAD_PRIORITY
)
3780 if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
))
3781 priority
= ACE_THR_PRI_FIFO_DEF
;
3782 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_RR
))
3783 priority
= ACE_THR_PRI_RR_DEF
;
3784 else // THR_SCHED_DEFAULT
3785 priority
= ACE_THR_PRI_OTHER_DEF
;
3787 # endif /* ACE_HAS_PTHREADS */
3788 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
3790 struct sched_param sparam
;
3791 ACE_OS::memset ((void *) &sparam
, 0, sizeof sparam
);
3793 # if defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
3794 /* For MIT pthreads... */
3795 sparam
.prio
= ACE_MIN (priority
, PTHREAD_MAX_PRIORITY
);
3796 # elif defined(ACE_HAS_PTHREADS) && !defined (ACE_HAS_STHREADS)
3797 // The following code forces priority into range.
3798 if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
))
3799 sparam
.sched_priority
=
3800 ACE_MIN (ACE_THR_PRI_FIFO_MAX
,
3801 ACE_MAX (ACE_THR_PRI_FIFO_MIN
, priority
));
3802 else if (ACE_BIT_ENABLED(flags
, THR_SCHED_RR
))
3803 sparam
.sched_priority
=
3804 ACE_MIN (ACE_THR_PRI_RR_MAX
,
3805 ACE_MAX (ACE_THR_PRI_RR_MIN
, priority
));
3806 else // Default policy, whether set or not
3807 sparam
.sched_priority
=
3808 ACE_MIN (ACE_THR_PRI_OTHER_MAX
,
3809 ACE_MAX (ACE_THR_PRI_OTHER_MIN
, priority
));
3810 # elif defined (PRIORITY_MAX)
3811 sparam
.sched_priority
= ACE_MIN (priority
,
3812 (long) PRIORITY_MAX
);
3814 sparam
.sched_priority
= priority
;
3815 # endif /* PTHREAD_MAX_PRIORITY */
3818 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
3819 // SunOS, through 5.6, POSIX only allows priorities > 0 to
3820 // ::pthread_attr_setschedparam. If a priority of 0 was
3821 // requested, set the thread priority after creating it, below.
3823 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
3825 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr
, &sparam
),
3829 ::pthread_attr_destroy (&attr
);
3836 # if !defined (ACE_LACKS_SETINHERITSCHED)
3837 // *** Set scheduling explicit or inherited
3838 if (ACE_BIT_ENABLED (flags
, THR_INHERIT_SCHED
)
3839 || ACE_BIT_ENABLED (flags
, THR_EXPLICIT_SCHED
))
3841 int sched
= PTHREAD_EXPLICIT_SCHED
;
3842 if (ACE_BIT_ENABLED (flags
, THR_INHERIT_SCHED
))
3843 sched
= PTHREAD_INHERIT_SCHED
;
3844 if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr
, sched
), result
) != 0)
3846 ::pthread_attr_destroy (&attr
);
3850 # endif /* ACE_LACKS_SETINHERITSCHED */
3851 # else /* ACE_LACKS_SETSCHED */
3852 ACE_UNUSED_ARG (priority
);
3853 # endif /* ACE_LACKS_SETSCHED */
3855 // *** Set pthread name
3856 # if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3857 if (thr_name
&& *thr_name
)
3859 if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr
, const_cast<char*>(*thr_name
)), result
) != 0)
3861 ::pthread_attr_destroy (&attr
);
3866 ACE_UNUSED_ARG (thr_name
);
3870 # if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
3871 if (ACE_BIT_ENABLED (flags
, THR_SCOPE_SYSTEM
)
3872 || ACE_BIT_ENABLED (flags
, THR_SCOPE_PROCESS
))
3874 # if defined (ACE_LACKS_PTHREAD_SCOPE_PROCESS)
3875 int scope
= PTHREAD_SCOPE_SYSTEM
;
3876 # else /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3877 int scope
= PTHREAD_SCOPE_PROCESS
;
3878 # endif /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3879 if (ACE_BIT_ENABLED (flags
, THR_SCOPE_SYSTEM
))
3880 scope
= PTHREAD_SCOPE_SYSTEM
;
3882 if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr
, scope
), result
) != 0)
3884 ::pthread_attr_destroy (&attr
);
3888 # endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
3890 # ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
3891 if (ACE_BIT_ENABLED (flags
, THR_SUSPENDED
))
3893 if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr
), result
) != 0)
3896 ::pthread_attr_destroy (&attr
);
3900 # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
3902 # if ! defined(ACE_LACKS_THR_CONCURRENCY_FUNCS)
3903 if (ACE_BIT_ENABLED (flags
, THR_NEW_LWP
))
3905 // Increment the number of LWPs by one to emulate the
3907 int lwps
= ACE_OS::thr_getconcurrency ();
3910 if (errno
== ENOTSUP
)
3911 // Suppress the ENOTSUP because it's harmless.
3914 // This should never happen on SunOS:
3915 // ::thr_getconcurrency () should always succeed.
3918 else if (ACE_OS::thr_setconcurrency (lwps
+ 1) == -1)
3920 if (errno
== ENOTSUP
)
3922 // Unlikely: ::thr_getconcurrency () is supported
3923 // but ::thr_setconcurrency () is not?
3929 # endif /* ! ACE_LACKS_THR_CONCURRENCY_FUNCS */
3932 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id
,
3934 thread_args
->entry_point (),
3938 ::pthread_attr_destroy (&attr
);
3940 // This is a SunOS or POSIX implementation of pthreads, where we
3941 // assume that ACE_thread_t and ACE_hthread_t are the same. If this
3942 // *isn't* correct on some platform, please let us know.
3944 *thr_handle
= *thr_id
;
3946 # if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER)
3947 // SunOS prior to 5.7:
3949 // If the priority is 0, then we might have to set it now because we
3950 // couldn't set it with ::pthread_attr_setschedparam, as noted
3951 // above. This doesn't provide strictly correct behavior, because
3952 // the thread was created (above) with the priority of its parent.
3953 // (That applies regardless of the inherit_sched attribute: if it
3954 // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
3955 // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then "attr"
3956 // was initialized by the SunOS ::pthread_attr_init () to contain
3957 // NULL for the priority, which indicated to SunOS ::pthread_create
3958 // () to inherit the parent priority.)
3961 // Check the priority of this thread, which is the parent
3962 // of the newly created thread. If it is 0, then the
3963 // newly created thread will have inherited the priority
3964 // of 0, so there's no need to explicitly set it.
3965 struct sched_param sparam
;
3967 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
3973 // The only policy supported by by SunOS, thru version 5.6,
3974 // is SCHED_OTHER, so that's hard-coded here.
3975 policy
= ACE_SCHED_OTHER
;
3977 if (sparam
.sched_priority
!= 0)
3979 ACE_OS::memset ((void *) &sparam
, 0, sizeof sparam
);
3980 // The memset to 0 sets the priority to 0, so we don't need
3981 // to explicitly set sparam.sched_priority.
3983 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id
,
3991 # if defined (ACE_NEEDS_LWP_PRIO_SET)
3993 // It would be useful if we could make this work. But, it requires
3994 // a mechanism for determining the ID of an LWP to which another
3995 // thread is bound. Is there a way to do that? Instead, just rely
3996 // on the code in ACE_Thread_Adapter::invoke () to set the LWP
3999 // If the thread is bound, then set the priority on its LWP.
4000 if (ACE_BIT_ENABLED (flags
, THR_BOUND
))
4002 ACE_Sched_Params
sched_params (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
) ||
4003 ACE_BIT_ENABLED (flags
, THR_SCHED_RR
) ?
4007 result
= ACE_OS::lwp_setparams (sched_params
,
4008 /* ? How do we find the ID of the LWP
4009 to which *thr_id is bound? */);
4012 # endif /* ACE_NEEDS_LWP_PRIO_SET */
4014 # endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
4015 auto_thread_args
.release ();
4017 # elif defined (ACE_HAS_STHREADS)
4019 int start_suspended
= ACE_BIT_ENABLED (flags
, THR_SUSPENDED
);
4021 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
4022 // If we need to set the priority, then we need to start the
4023 // thread in a suspended mode.
4024 ACE_SET_BITS (flags
, THR_SUSPENDED
);
4026 ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack
, stacksize
,
4027 thread_args
->entry_point (),
4029 flags
, thr_id
), result
),
4034 // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
4035 *thr_handle
= *thr_id
;
4037 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
4039 // Set the priority of the new thread and then let it
4040 // continue, but only if the user didn't start it suspended
4041 // in the first place!
4042 result
= ACE_OS::thr_setprio (*thr_id
, priority
);
4049 if (start_suspended
== 0)
4051 result
= ACE_OS::thr_continue (*thr_id
);
4060 auto_thread_args
.release ();
4062 # elif defined (ACE_HAS_WTHREADS)
4063 ACE_UNUSED_ARG (thr_name
);
4064 ACE_UNUSED_ARG (stack
);
4065 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4066 if (ACE_BIT_ENABLED (flags
, THR_USE_AFX
))
4068 CWinThread
*cwin_thread
=
4069 ::AfxBeginThread ((AFX_THREADPROC
) thread_args
->entry_point (),
4073 flags
| THR_SUSPENDED
);
4074 // Have to duplicate the handle because
4075 // CWinThread::~CWinThread() closes the original handle.
4076 # if !defined (ACE_HAS_WINCE)
4077 (void) ::DuplicateHandle (::GetCurrentProcess (),
4078 cwin_thread
->m_hThread
,
4079 ::GetCurrentProcess (),
4083 DUPLICATE_SAME_ACCESS
);
4084 # endif /* ! ACE_HAS_WINCE */
4085 *thr_id
= cwin_thread
->m_nThreadID
;
4087 if (ACE_BIT_ENABLED (flags
, THR_SUSPENDED
) == 0)
4088 cwin_thread
->ResumeThread ();
4089 // cwin_thread will be deleted in AfxThreadExit()
4090 // Warning: If AfxThreadExit() is called from within the
4091 // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
4094 # endif /* ACE_HAS_MFC */
4096 int const start_suspended
= ACE_BIT_ENABLED (flags
, THR_SUSPENDED
);
4098 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
4099 // If we need to set the priority, then we need to start the
4100 // thread in a suspended mode.
4101 ACE_SET_BITS (flags
, THR_SUSPENDED
);
4103 *thr_handle
= (void *) ACE_BEGINTHREADEX (0,
4104 static_cast <u_int
> (stacksize
),
4105 thread_args
->entry_point (),
4110 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
&& *thr_handle
!= 0)
4112 // Set the priority of the new thread and then let it
4113 // continue, but only if the user didn't start it suspended
4114 // in the first place!
4115 if (ACE_OS::thr_setprio (*thr_handle
, priority
) != 0)
4120 if (start_suspended
== 0)
4122 ACE_OS::thr_continue (*thr_handle
);
4127 // Close down the handle if no one wants to use it.
4128 if (thr_handle
== &tmp_handle
&& tmp_handle
!= 0)
4129 ::CloseHandle (tmp_handle
);
4131 if (*thr_handle
!= 0)
4133 auto_thread_args
.release ();
4137 ACE_FAIL_RETURN (-1);
4140 # elif defined (ACE_VXWORKS)
4141 // The hard-coded values below are what ::sp () would use. (::sp ()
4142 // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
4143 // 20,000.) stacksize should be an even integer. If a stack is not
4144 // specified, ::taskSpawn () is used so that we can set the
4145 // priority, flags, and stacksize. If a stack is specified,
4146 // ::taskInit ()/::taskActivate() are used.
4148 // If called with thr_create() defaults, use same default values as ::sp ():
4149 if (priority
== ACE_DEFAULT_THREAD_PRIORITY
) priority
= 100;
4150 // Assumes that there is a floating point coprocessor. As noted
4151 // above, ::sp () hardcodes this, so we should be safe with it.
4152 if (flags
== 0) flags
= VX_FP_TASK
;
4153 if (stacksize
== 0) stacksize
= 20000;
4156 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4160 ACE_UNUSED_ARG (stack
);
4162 // The call below to ::taskSpawn () causes VxWorks to assign a
4163 // unique task name of the form: "t" + an integer, because the
4164 // first argument is 0.
4165 tid
= ::taskSpawn (thr_name
&& *thr_name
? const_cast <char*> (*thr_name
) : 0,
4169 thread_args
->entry_point (),
4170 (ACE_VX_USR_ARG_T
) thread_args
,
4171 0, 0, 0, 0, 0, 0, 0, 0, 0);
4172 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
4176 // If a task name (thr_id) was not supplied, then the task will
4177 // not have a unique name. That's VxWorks' behavior.
4179 // Carve out a TCB at the beginning of the stack space. The TCB
4180 // occupies 400 bytes with VxWorks 5.3.1/I386.
4181 WIND_TCB
*tcb
= (WIND_TCB
*) stack
;
4183 // The TID is defined to be the address of the TCB.
4184 int status
= ::taskInit (tcb
,
4185 thr_name
&& *thr_name
? const_cast <char*>(*thr_name
) : 0,
4188 (char *) stack
+ sizeof (WIND_TCB
),
4189 (int) (stacksize
- sizeof (WIND_TCB
)),
4190 thread_args
->entry_point (),
4192 0, 0, 0, 0, 0, 0, 0, 0, 0);
4196 // The task was successfully initialized, now activate it.
4197 status
= ::taskActivate ((ACE_hthread_t
) tcb
);
4200 tid
= status
== OK
? (ACE_thread_t
) tcb
: ERROR
;
4204 if (tid
== ACE_VX_TASK_ID_ERROR
)
4214 if (thr_name
&& !(*thr_name
))
4215 *thr_name
= ::taskName (tid
);
4217 auto_thread_args
.release ();
4221 # endif /* ACE_HAS_STHREADS */
4223 ACE_UNUSED_ARG (func
);
4224 ACE_UNUSED_ARG (args
);
4225 ACE_UNUSED_ARG (flags
);
4226 ACE_UNUSED_ARG (thr_id
);
4227 ACE_UNUSED_ARG (thr_handle
);
4228 ACE_UNUSED_ARG (priority
);
4229 ACE_UNUSED_ARG (stack
);
4230 ACE_UNUSED_ARG (stacksize
);
4231 ACE_UNUSED_ARG (thr_name
);
4232 ACE_NOTSUP_RETURN (-1);
4233 #endif /* ACE_HAS_THREADS */
4237 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status
)
4239 ACE_OS_TRACE ("ACE_OS::thr_exit");
4240 #if defined (ACE_HAS_THREADS)
4241 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_EXIT)
4242 ::pthread_exit (status
);
4243 # elif defined (ACE_HAS_STHREADS)
4244 ::thr_exit (status
);
4245 # elif defined (ACE_HAS_WTHREADS)
4246 // Can't call it here because on NT, the thread is exited
4247 // directly by ACE_Thread_Adapter::invoke ().
4248 // ACE_TSS_Cleanup::instance ()->thread_exit (status);
4250 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4252 // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
4253 // But without #including ace/Thread_Manager.h, we don't know that.
4254 ACE_OS_Thread_Descriptor
*td
=
4255 ACE_Base_Thread_Adapter::thr_desc_log_msg ();
4257 using_afx
= ACE_BIT_ENABLED (td
->flags (), THR_USE_AFX
);
4258 # endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
4260 // Call TSS destructors.
4261 ACE_OS::cleanup_tss (0 /* not main thread */);
4264 // Allow CWinThread-destructor to be invoked from AfxEndThread.
4265 // _endthreadex will be called from AfxEndThread so don't exit the
4266 // thread now if we are running an MFC thread.
4267 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
4268 if (using_afx
!= -1)
4271 ::AfxEndThread (status
);
4273 ACE_ENDTHREADEX (status
);
4277 // Not spawned by ACE_Thread_Manager, use the old buggy
4278 // version. You should seriously consider using
4279 // ACE_Thread_Manager to spawn threads. The following code is
4280 // know to cause some problem.
4281 CWinThread
*pThread
= ::AfxGetThread ();
4282 if (!pThread
|| pThread
->m_nThreadID
!= ACE_OS::thr_self ())
4283 ACE_ENDTHREADEX (status
);
4285 ::AfxEndThread (status
);
4288 ACE_ENDTHREADEX (status
);
4289 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
4291 # elif defined (ACE_HAS_VXTHREADS)
4292 ACE_UNUSED_ARG (status
);
4293 ::taskDelete (ACE_OS::thr_self ());
4295 ACE_UNUSED_ARG (status
);
4296 # endif /* ACE_HAS_PTHREADS */
4298 ACE_UNUSED_ARG (status
);
4299 #endif /* ACE_HAS_THREADS */
4302 #if defined (ACE_HAS_VXTHREADS)
4303 // Leave this in the global scope to allow
4304 // users to adjust the delay value.
4305 int ACE_THR_JOIN_DELAY
= 5;
4308 ACE_OS::thr_join (ACE_hthread_t thr_handle
,
4309 ACE_THR_FUNC_RETURN
*status
)
4311 // We can't get the status of the thread
4317 // This method can not support joining all threads
4318 if (ACE_OS::thr_cmp (thr_handle
, ACE_OS::NULL_hthread
))
4320 ACE_NOTSUP_RETURN (-1);
4324 ACE_thread_t current
= ACE_OS::thr_self ();
4326 // Make sure we are not joining ourself
4327 if (ACE_OS::thr_cmp (thr_handle
, current
))
4333 // Whether the task exists or not
4334 // we will return a successful value
4337 // Verify that the task id still exists
4338 while (taskIdVerify (thr_handle
) == OK
)
4340 // Wait a bit to see if the task is still active.
4341 ACE_OS::sleep (ACE_THR_JOIN_DELAY
);
4345 // Adapt the return value into errno and return value.
4346 // The ACE_ADAPT_RETVAL macro doesn't exactly do what
4347 // we need to do here, so we do it manually.
4358 ACE_OS::thr_join (ACE_thread_t waiter_id
,
4359 ACE_thread_t
*thr_id
,
4360 ACE_THR_FUNC_RETURN
*status
)
4363 return ACE_OS::thr_join (waiter_id
, status
);
4365 #endif /* ACE_HAS_VXTHREADS */
4368 ACE_OS::thr_key_detach (ACE_thread_key_t key
)
4370 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
4371 TSS_Cleanup_Instance cleanup
;
4372 if (cleanup
.valid ())
4374 return cleanup
->thread_detach_key (key
);
4381 ACE_UNUSED_ARG (key
);
4382 ACE_NOTSUP_RETURN (-1);
4383 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
4387 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id
,
4388 size_t cpu_set_size
,
4389 cpu_set_t
* cpu_mask
)
4391 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
4392 // Handle of the thread, which is NPTL thread-id, normally a big number
4393 if (::pthread_getaffinity_np (thr_id
, cpu_set_size
, cpu_mask
) != 0)
4398 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
4399 // The process-id is expected as <thr_id>, which can be a thread-id of
4400 // linux-thread, thus making binding to cpu of that particular thread only.
4401 // If you are using this flag for NPTL-threads, however, please pass as a
4402 // thr_id process id obtained by ACE_OS::getpid ()
4403 ACE_UNUSED_ARG (cpu_set_size
);
4404 if (::sched_getaffinity(thr_id
, cpu_mask
) == -1)
4409 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
4410 // The process-id is expected as <thr_id>, which can be a thread-id of
4411 // linux-thread, thus making binding to cpu of that particular thread only.
4412 // If you are using this flag for NPTL-threads, however, please pass as a
4413 // thr_id process id obtained by ACE_OS::getpid ()
4414 if (::sched_getaffinity(thr_id
, cpu_set_size
, cpu_mask
) == -1)
4419 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4420 ACE_UNUSED_ARG (cpu_set_size
);
4422 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id
, *cpu_mask
), result
) == -1)
4428 ACE_UNUSED_ARG (thr_id
);
4429 ACE_UNUSED_ARG (cpu_set_size
);
4430 ACE_UNUSED_ARG (cpu_mask
);
4431 ACE_NOTSUP_RETURN (-1);
4436 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id
,
4437 size_t cpu_set_size
,
4438 const cpu_set_t
* cpu_mask
)
4440 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
4441 if (::pthread_setaffinity_np (thr_id
, cpu_set_size
, cpu_mask
) != 0)
4446 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
4447 // The process-id is expected as <thr_id>, which can be a thread-id of
4448 // linux-thread, thus making binding to cpu of that particular thread only.
4449 // If you are using this flag for NPTL-threads, however, please pass as a
4450 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4452 ACE_UNUSED_ARG (cpu_set_size
);
4453 if (::sched_setaffinity (thr_id
, cpu_mask
) == -1)
4458 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
4459 // The process-id is expected as <thr_id>, which can be a thread-id of
4460 // linux-thread, thus making binding to cpu of that particular thread only.
4461 // If you are using this flag for NPTL-threads, however, please pass as a
4462 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4464 if (::sched_setaffinity (thr_id
, cpu_set_size
, cpu_mask
) == -1)
4469 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4470 ACE_UNUSED_ARG (cpu_set_size
);
4472 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id
, *cpu_mask
), result
) == -1)
4478 ACE_UNUSED_ARG (thr_id
);
4479 ACE_UNUSED_ARG (cpu_set_size
);
4480 ACE_UNUSED_ARG (cpu_mask
);
4481 ACE_NOTSUP_RETURN (-1);
4486 ACE_OS::thr_key_used (ACE_thread_key_t key
)
4488 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
4489 TSS_Cleanup_Instance cleanup
;
4490 if (cleanup
.valid ())
4492 cleanup
->thread_use_key (key
);
4497 ACE_UNUSED_ARG (key
);
4498 ACE_NOTSUP_RETURN (-1);
4499 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
4502 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4504 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t
*key
,
4505 # if defined (ACE_HAS_THR_C_DEST)
4509 # endif /* ACE_HAS_THR_C_DEST */
4512 // can't trace here. Trace uses TSS
4513 // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
4514 # if defined (ACE_HAS_THREADS)
4515 # if defined (ACE_HAS_PTHREADS)
4517 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key
, dest
),
4520 # elif defined (ACE_HAS_STHREADS)
4522 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key
, dest
),
4525 # elif defined (ACE_HAS_WTHREADS)
4526 ACE_UNUSED_ARG (dest
);
4527 *key
= ::TlsAlloc ();
4529 if (*key
== ACE_SYSCALL_FAILED
)
4530 ACE_FAIL_RETURN (-1);
4532 # endif /* ACE_HAS_STHREADS */
4534 ACE_UNUSED_ARG (key
);
4535 ACE_UNUSED_ARG (dest
);
4536 ACE_NOTSUP_RETURN (-1);
4537 # endif /* ACE_HAS_THREADS */
4539 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4542 ACE_OS::thr_keycreate (ACE_thread_key_t
*key
,
4543 # if defined (ACE_HAS_THR_C_DEST)
4544 ACE_THR_C_DEST dest
)
4547 # endif /* ACE_HAS_THR_C_DEST */
4549 // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
4550 #if defined (ACE_HAS_THREADS)
4551 # if defined (ACE_HAS_TSS_EMULATION)
4552 if (ACE_TSS_Emulation::next_key (*key
) == 0)
4554 ACE_TSS_Emulation::tss_destructor (*key
, dest
);
4556 // Extract out the thread-specific table instance and stash away
4557 // the key and destructor so that we can free it up later on...
4558 TSS_Cleanup_Instance
cleanup (TSS_Cleanup_Instance::CREATE
);
4559 if (cleanup
.valid ())
4561 return cleanup
->insert (*key
, dest
);
4570 # elif defined (ACE_HAS_WTHREADS)
4571 if (ACE_OS::thr_keycreate_native (key
, dest
) == 0)
4573 // Extract out the thread-specific table instance and stash away
4574 // the key and destructor so that we can free it up later on...
4575 TSS_Cleanup_Instance
cleanup (TSS_Cleanup_Instance::CREATE
);
4576 if (cleanup
.valid ())
4578 return cleanup
->insert (*key
, dest
);
4588 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4589 return ACE_OS::thr_keycreate_native (key
, dest
);
4591 ACE_UNUSED_ARG (key
);
4592 ACE_UNUSED_ARG (dest
);
4593 ACE_NOTSUP_RETURN (-1);
4594 # endif /* ACE_HAS_TSS_EMULATION */
4595 # else /* ACE_HAS_THREADS */
4596 ACE_UNUSED_ARG (key
);
4597 ACE_UNUSED_ARG (dest
);
4598 ACE_NOTSUP_RETURN (-1);
4599 # endif /* ACE_HAS_THREADS */
4602 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4604 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key
)
4606 ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
4607 # if defined (ACE_HAS_THREADS)
4608 # if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
4609 // For some systems, e.g. LynxOS, we need to ensure that
4610 // any registered thread destructor action for this slot
4611 // is now disabled. Otherwise in the event of a dynamic library
4612 // unload of libACE, by a program not linked with libACE,
4613 // ACE_TSS_cleanup will be invoked again at the thread exit
4614 // after libACE has been actually been unmapped from memory.
4615 (void) ACE_OS::thr_setspecific_native (key
, 0);
4616 # endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
4617 # if defined (ACE_HAS_PTHREADS)
4618 # if defined (ACE_LACKS_PTHREAD_KEY_DELETE)
4619 ACE_UNUSED_ARG (key
);
4620 ACE_NOTSUP_RETURN (-1);
4622 return ::pthread_key_delete (key
);
4623 # endif /* ACE_LACKS_PTHREAD_KEY_DELETE */
4624 # elif defined (ACE_HAS_THR_KEYDELETE)
4625 return ::thr_keydelete (key
);
4626 # elif defined (ACE_HAS_STHREADS)
4627 ACE_UNUSED_ARG (key
);
4628 ACE_NOTSUP_RETURN (-1);
4629 # elif defined (ACE_HAS_WTHREADS)
4630 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key
), ace_result_
), int, -1);
4632 ACE_UNUSED_ARG (key
);
4633 ACE_NOTSUP_RETURN (-1);
4634 # endif /* ACE_HAS_PTHREADS */
4636 ACE_UNUSED_ARG (key
);
4637 ACE_NOTSUP_RETURN (-1);
4638 # endif /* ACE_HAS_THREADS */
4640 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4643 ACE_OS::thr_keyfree (ACE_thread_key_t key
)
4645 ACE_OS_TRACE ("ACE_OS::thr_keyfree");
4646 # if defined (ACE_HAS_THREADS)
4647 # if defined (ACE_HAS_TSS_EMULATION)
4648 // Release the key in the TSS_Emulation administration
4649 ACE_TSS_Emulation::release_key (key
);
4650 TSS_Cleanup_Instance cleanup
;
4651 if (cleanup
.valid ())
4653 return cleanup
->free_key (key
);
4656 # elif defined (ACE_HAS_WTHREADS)
4657 // Extract out the thread-specific table instance and free up
4658 // the key and destructor.
4659 TSS_Cleanup_Instance cleanup
;
4660 if (cleanup
.valid ())
4662 return cleanup
->free_key (key
);
4665 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4666 return ACE_OS::thr_keyfree_native (key
);
4668 ACE_UNUSED_ARG (key
);
4669 ACE_NOTSUP_RETURN (-1);
4670 # endif /* ACE_HAS_TSS_EMULATION */
4671 # else /* ACE_HAS_THREADS */
4672 ACE_UNUSED_ARG (key
);
4673 ACE_NOTSUP_RETURN (-1);
4675 # endif /* ACE_HAS_THREADS */
4679 ACE_OS::thr_setprio (const ACE_Sched_Priority prio
)
4681 // Set the thread priority on the current thread.
4682 ACE_hthread_t my_thread_id
;
4683 ACE_OS::thr_self (my_thread_id
);
4685 int const status
= ACE_OS::thr_setprio (my_thread_id
, prio
);
4687 #if defined (ACE_NEEDS_LWP_PRIO_SET)
4688 // If the thread is in the RT class, then set the priority on its
4689 // LWP. (Instead of doing this if the thread is in the RT class, it
4690 // should be done for all bound threads. But, there doesn't appear
4691 // to be an easy way to determine if the thread is bound.)
4695 // Find what scheduling class the thread's LWP is in.
4696 ACE_Sched_Params
sched_params (ACE_SCHED_OTHER
, 0);
4697 if (ACE_OS::lwp_getparams (sched_params
) == -1)
4701 else if (sched_params
.policy () == ACE_SCHED_FIFO
||
4702 sched_params
.policy () == ACE_SCHED_RR
)
4704 // This thread's LWP is in the RT class, so we need to set
4706 sched_params
.priority (prio
);
4707 return ACE_OS::lwp_setparams (sched_params
);
4709 // else this is not an RT thread. Nothing more needs to be
4712 #endif /* ACE_NEEDS_LWP_PRIO_SET */
4717 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4719 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key
, void *data
)
4721 // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
4722 # if defined (ACE_HAS_THREADS)
4723 # if defined (ACE_HAS_PTHREADS)
4725 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key
, data
),
4728 # elif defined (ACE_HAS_STHREADS)
4730 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key
, data
), result
), int, -1);
4731 # elif defined (ACE_HAS_WTHREADS)
4732 ::TlsSetValue (key
, data
);
4734 # else /* ACE_HAS_STHREADS */
4735 ACE_UNUSED_ARG (key
);
4736 ACE_UNUSED_ARG (data
);
4737 ACE_NOTSUP_RETURN (-1);
4738 # endif /* ACE_HAS_STHREADS */
4740 ACE_UNUSED_ARG (key
);
4741 ACE_UNUSED_ARG (data
);
4742 ACE_NOTSUP_RETURN (-1);
4743 # endif /* ACE_HAS_THREADS */
4745 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4748 ACE_OS::thr_setspecific (ACE_thread_key_t key
, void *data
)
4750 // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
4751 #if defined (ACE_HAS_THREADS)
4752 # if defined (ACE_HAS_TSS_EMULATION)
4753 if (ACE_TSS_Emulation::is_key (key
) == 0)
4761 ACE_TSS_Emulation::ts_object (key
) = data
;
4762 TSS_Cleanup_Instance cleanup
;
4763 if (cleanup
.valid ())
4765 cleanup
->thread_use_key (key
);
4766 // for TSS_Cleanup purposes treat stetting data to zero
4767 // like detaching. This is a consequence of POSIX allowing
4768 // deletion of a "used" key.
4771 cleanup
->thread_detach_key (key
);
4780 # elif defined (ACE_HAS_WTHREADS)
4781 if (ACE_OS::thr_setspecific_native (key
, data
) == 0)
4783 TSS_Cleanup_Instance cleanup
;
4784 if (cleanup
.valid ())
4786 cleanup
->thread_use_key (key
);
4787 // for TSS_Cleanup purposes treat stetting data to zero
4788 // like detaching. This is a consequence of POSIX allowing
4789 // deletion of a "used" key.
4792 cleanup
->thread_detach_key (key
);
4799 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4800 return ACE_OS::thr_setspecific_native (key
, data
);
4801 # else /* ACE_HAS_TSS_EMULATION */
4802 ACE_UNUSED_ARG (key
);
4803 ACE_UNUSED_ARG (data
);
4804 ACE_NOTSUP_RETURN (-1);
4805 # endif /* ACE_HAS_TSS_EMULATION */
4806 # else /* ACE_HAS_THREADS */
4807 ACE_UNUSED_ARG (key
);
4808 ACE_UNUSED_ARG (data
);
4809 ACE_NOTSUP_RETURN (-1);
4810 # endif /* ACE_HAS_THREADS */
4814 ACE_OS::unique_name (const void *object
,
4818 // The process ID will provide uniqueness between processes on the
4819 // same machine. The "this" pointer of the <object> will provide
4820 // uniqueness between other "live" objects in the same process. The
4821 // uniqueness of this name is therefore only valid for the life of
4823 ACE_OS::snprintf (name
, length
, "%p%d", object
,
4824 static_cast<int> (ACE_OS::getpid ()));
4827 #if defined (ACE_USES_WCHAR)
4829 ACE_OS::unique_name (const void *object
,
4833 // The process ID will provide uniqueness between processes on the
4834 // same machine. The "this" pointer of the <object> will provide
4835 // uniqueness between other "live" objects in the same process. The
4836 // uniqueness of this name is therefore only valid for the life of
4838 ACE_OS::snprintf (name
, length
, ACE_TEXT ("%p%d"), object
,
4839 static_cast<int> (ACE_OS::getpid ()));
4844 ACE_OS::thr_gettid ()
4846 #ifdef ACE_HAS_GETTID
4847 return syscall (SYS_gettid
);
4849 ACE_NOTSUP_RETURN (-1);
4853 ACE_END_VERSIONED_NAMESPACE_DECL
4855 #if defined (ACE_VXWORKS) && !defined (__RTP__)
4856 # include /**/ <usrLib.h> /* for ::sp() */
4857 # include /**/ <sysLib.h> /* for ::sysClkRateGet() */
4858 # include "ace/Service_Config.h"
4860 #if !defined (ACE_LACKS_VA_FUNCTIONS)
4862 // This global function can be used from the VxWorks shell to pass
4863 // arguments to a C main () function.
4865 // usage: -> spa main, "arg1", "arg2"
4867 // All arguments must be quoted, even numbers.
4869 spa (FUNCPTR entry
, ...)
4871 // The called entrypoint can get the function name plus the normal 10
4872 // optional arguments.
4873 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 1 + 10;
4874 static char *argv
[ACE_MAX_ARGS
] = { 0 };
4876 ACE_VX_USR_ARG_T argc
;
4878 // Hardcode a program name because the real one isn't available
4879 // through the VxWorks shell.
4880 argv
[0] = const_cast<char*> ("ace_main");
4882 // Peel off arguments to spa () and put into argv. va_arg () isn't
4883 // necessarily supposed to return 0 when done, though since the
4884 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4885 // the unused ones. This function could be used to increase that
4886 // limit, but then it couldn't depend on the trailing 0. So, the
4887 // number of arguments would have to be passed.
4888 va_start (pvar
, entry
);
4890 for (argc
= 1; argc
< ACE_MAX_ARGS
; ++argc
)
4892 argv
[argc
] = va_arg (pvar
, char *);
4894 if (argv
[argc
] == 0)
4898 if (argc
>= ACE_MAX_ARGS
&& argv
[ACE_MAX_ARGS
- 1] != 0)
4900 // Try to read another arg, and warn user if the limit was exceeded.
4902 // Note that the VxWorks shell arguments change from int to long when
4903 // using a 64bit compiler. Cast the argument up so that the format
4904 // specifier remains correct for either build type.
4905 if (va_arg (pvar
, char *) != 0)
4906 ACE_OS::fprintf (stderr
, "spa(): number of arguments limited to %ld\n",
4907 (long)ACE_MAX_ARGS
);
4911 // fill unused argv slots with 0 to get rid of leftovers
4912 // from previous invocations
4913 for (ACE_VX_USR_ARG_T i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
4917 // The hard-coded options are what ::sp () uses, except for the
4918 // larger stack size (instead of ::sp ()'s 20000).
4919 ACE_VX_TASK_ID
const ret
= ::taskSpawn (argv
[0], // task name
4920 100, // task priority
4921 VX_FP_TASK
, // task options
4922 ACE_NEEDS_HUGE_THREAD_STACKSIZE
, // stack size
4923 entry
, // entry point
4924 argc
, // first argument to main ()
4925 (ACE_VX_USR_ARG_T
) argv
, // second argument to main ()
4926 0, 0, 0, 0, 0, 0, 0, 0);
4929 // ::taskSpawn () returns the taskID on success: return 0 instead if
4931 return ret
> 0 ? 0 : -1;
4933 #endif /* !ACE_LACKS_VA_FUNCTIONS */
4935 // A helper function for the extended spa functions
4937 add_to_argv (ACE_VX_USR_ARG_T
& argc
, char** argv
, int max_args
, char* string
)
4940 size_t previous
= 0;
4941 size_t length
= ACE_OS::strlen (string
);
4945 // We use <= to make sure that we get the last argument
4946 for (size_t i
= 0; i
<= length
; i
++)
4948 // Is it a double quote that hasn't been escaped?
4949 if (string
[i
] == '\"' && (i
== 0 || string
[i
- 1] != '\\'))
4954 // We have just entered a double quoted string, so
4955 // save the starting position of the contents.
4960 // We have just left a double quoted string, so
4961 // zero out the ending double quote.
4965 else if (string
[i
] == '\\') // Escape the next character
4967 // The next character is automatically skipped because
4968 // of the memmove().
4969 ACE_OS::memmove (string
+ i
, string
+ i
+ 1, length
);
4972 else if (!indouble
&&
4973 (ACE_OS::ace_isspace (string
[i
]) || string
[i
] == '\0'))
4976 if (argc
< max_args
)
4978 argv
[argc
] = string
+ previous
;
4983 ACE_OS::fprintf (stderr
, "spae(): number of arguments "
4984 "limited to %d\n", max_args
);
4987 // Skip over whitespace in between arguments
4988 for(++i
; i
< length
&& ACE_OS::ace_isspace (string
[i
]); ++i
)
4992 // Save the starting point for the next time around
4995 // Make sure we don't skip over a character due
4996 // to the above loop to skip over whitespace
5003 #if !defined (ACE_LACKS_VA_FUNCTIONS)
5005 // This global function can be used from the VxWorks shell to pass
5006 // arguments to a C main () function.
5008 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
5010 // All arguments must be within double quotes, even numbers.
5012 spae (FUNCPTR entry
, ...)
5014 static int const WINDSH_ARGS
= 10;
5015 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 128;
5016 static char* argv
[ACE_MAX_ARGS
] = { const_cast<char*> ("ace_main"), 0 };
5018 ACE_VX_USR_ARG_T argc
= 1;
5020 // Peel off arguments to spa () and put into argv. va_arg () isn't
5021 // necessarily supposed to return 0 when done, though since the
5022 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5024 va_start (pvar
, entry
);
5027 for (char* str
= va_arg (pvar
, char*);
5028 str
!= 0 && i
< WINDSH_ARGS
; str
= va_arg (pvar
, char*), ++i
)
5030 add_to_argv(argc
, argv
, ACE_MAX_ARGS
, str
);
5033 // fill unused argv slots with 0 to get rid of leftovers
5034 // from previous invocations
5035 for (i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
5038 // The hard-coded options are what ::sp () uses, except for the
5039 // larger stack size (instead of ::sp ()'s 20000).
5040 ACE_VX_TASK_ID
const ret
= ::taskSpawn (argv
[0], // task name
5041 100, // task priority
5042 VX_FP_TASK
, // task options
5043 ACE_NEEDS_HUGE_THREAD_STACKSIZE
, // stack size
5044 entry
, // entry point
5045 argc
, // first argument to main ()
5046 (ACE_VX_USR_ARG_T
) argv
, // second argument to main ()
5047 0, 0, 0, 0, 0, 0, 0, 0);
5050 // ::taskSpawn () returns the taskID on success: return 0 instead if
5052 return ret
> 0 ? 0 : -1;
5055 // This global function can be used from the VxWorks shell to pass
5056 // arguments to a C main () function. The function will be run
5057 // within the shells task.
5059 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
5061 // All arguments must be within double quotes, even numbers.
5062 // Unlike the spae function, this fuction executes the supplied
5063 // routine in the foreground, rather than spawning it in a separate
5066 spaef (FUNCPTR entry
, ...)
5068 static int const WINDSH_ARGS
= 10;
5069 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 128;
5070 static char* argv
[ACE_MAX_ARGS
] = { const_cast<char*> ("ace_main"), 0 };
5072 ACE_VX_USR_ARG_T argc
= 1;
5074 // Peel off arguments to spa () and put into argv. va_arg () isn't
5075 // necessarily supposed to return 0 when done, though since the
5076 // VxWorks shell uses a fixed number (10) of arguments, it might 0
5078 va_start (pvar
, entry
);
5081 for (char* str
= va_arg (pvar
, char*);
5082 str
!= 0 && i
< WINDSH_ARGS
; str
= va_arg (pvar
, char*), ++i
)
5084 add_to_argv(argc
, argv
, ACE_MAX_ARGS
, str
);
5087 // fill unused argv slots with 0 to get rid of leftovers
5088 // from previous invocations
5089 for (i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
5092 int ret
= entry (argc
, argv
);
5096 // Return the return value of the invoked ace_main routine.
5099 #endif /* !ACE_LACKS_VA_FUNCTIONS */
5101 // This global function can be used from the VxWorks shell to pass
5102 // arguments to and run a main () function (i.e. ace_main).
5104 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
5106 // All arguments must be within double quotes, even numbers.
5107 // This routine spawns the main () function in a separate task and waits till the
5108 // task has finished.
5109 static int _vx_call_rc
= 0;
5112 _vx_call_entry(FUNCPTR entry
, int argc
, char* argv
[])
5114 ACE_Service_Config::current (ACE_Service_Config::global());
5115 _vx_call_rc
= entry (argc
, argv
);
5120 vx_execae (FUNCPTR entry
, char* arg
, int prio
, int opt
, size_t stacksz
, ...)
5122 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 128;
5123 static char* argv
[ACE_MAX_ARGS
] = { const_cast<char*> ("ace_main"), 0 };
5124 ACE_VX_USR_ARG_T argc
= 1;
5126 // Peel off arguments to run_main () and put into argv.
5129 add_to_argv(argc
, argv
, ACE_MAX_ARGS
, arg
);
5132 // fill unused argv slots with 0 to get rid of leftovers
5133 // from previous invocations
5134 for (ACE_VX_USR_ARG_T i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
5137 // The hard-coded options are what ::sp () uses, except for the
5138 // larger stack size (instead of ::sp ()'s 20000).
5139 ACE_VX_TASK_ID
const ret
= ::taskSpawn (argv
[0], // task name
5140 prio
==0 ? 100 : prio
, // task priority
5141 opt
==0 ? VX_FP_TASK
: opt
, // task options
5142 stacksz
==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE
: stacksz
, // stack size
5143 (FUNCPTR
)_vx_call_entry
, // entrypoint caller
5144 (ACE_VX_USR_ARG_T
)entry
, // entry point
5145 argc
, // first argument to main ()
5146 (ACE_VX_USR_ARG_T
) argv
, // second argument to main ()
5147 0, 0, 0, 0, 0, 0, 0);
5149 if (ret
== ACE_VX_TASK_ID_ERROR
)
5152 while( ret
> 0 && ::taskIdVerify (ret
) != ERROR
)
5153 ::taskDelay (3 * ::sysClkRateGet ());
5155 // ::taskSpawn () returns the taskID on success: return _vx_call_rc instead if
5157 return ret
> 0 ? _vx_call_rc
: 255;
5160 #if defined(ACE_AS_STATIC_LIBS) && defined (ACE_VXWORKS_DEBUGGING_HELPER)
5161 /** Wind River workbench allows the user to spawn a kernel task as a
5162 "Debug Configuration". Use this function as the entrypoint so that
5163 the arguments are translated into the form that ace_main() requires.
5165 int ace_wb_exec (int arg0
, int arg1
, int arg2
, int arg3
, int arg4
,
5166 int arg5
, int arg6
, int arg7
, int arg8
, int arg9
)
5168 return spaef ((FUNCPTR
) ace_main
, arg0
, arg1
, arg2
, arg3
, arg4
,
5169 arg5
, arg6
, arg7
, arg8
, arg9
);
5171 #endif /* ACE_AS_STATIC_LIBS && ... */
5173 #endif /* ACE_VXWORKS && !__RTP__ */