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/Thread_Mutex.h"
17 #include "ace/Condition_Thread_Mutex.h"
18 #include "ace/Guard_T.h"
20 # 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_WTHREADS)
34 // Green Hills compiler gets confused when __stdcall is embedded in
35 // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
37 typedef unsigned (__stdcall
*ACE_WIN32THRFUNC_T
)(void*);
38 # define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
39 ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
40 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
42 /*****************************************************************************/
44 ACE_BEGIN_VERSIONED_NAMESPACE_DECL
47 ACE_Thread_ID::to_string (char *thr_string
, size_t thr_string_len
) const
49 #if defined (ACE_WIN32)
50 ACE_OS::snprintf (thr_string
, thr_string_len
, "%u",
51 static_cast <unsigned> (this->thread_id_
));
53 // Yes, this is an ugly C-style cast, but the correct C++ cast is
54 // different depending on whether the t_id is an integral type or a
55 // pointer type. FreeBSD uses a pointer type, but doesn't have a _np
56 // function to get an integral type like other OSes, so use the
58 ACE_OS::snprintf (thr_string
, thr_string_len
, "%lu",
59 # ifdef ACE_THREAD_T_IS_A_STRUCT
60 *reinterpret_cast<const unsigned long *> (&
63 # endif // ACE_THREAD_T_IS_A_STRUCT
66 #endif /* ACE_WIN32 */
69 /*****************************************************************************/
71 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
73 #if defined (ACE_HAS_TSS_EMULATION)
74 u_int
ACE_TSS_Emulation::total_keys_
= 0;
76 ACE_TSS_Keys
* ACE_TSS_Emulation::tss_keys_used_
= 0;
78 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
79 ACE_TSS_Emulation::tss_destructor_
[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX
]
82 # if !defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) && defined (ACE_HAS_VXTHREADS)
84 # if (defined (_WRS_CONFIG_SMP) || defined (INCLUDE_AMP_CPU))
85 __thread
void* ACE_TSS_Emulation::ace_tss_keys
= 0;
86 # else /* ! VxWorks SMP */
87 void* ACE_TSS_Emulation::ace_tss_keys
= 0;
88 # endif /* ! VxWorks SMP */
90 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
92 bool ACE_TSS_Emulation::key_created_
= false;
94 ACE_OS_thread_key_t
ACE_TSS_Emulation::native_tss_key_
;
97 # if defined (ACE_HAS_THR_C_FUNC)
100 ACE_TSS_Emulation_cleanup (void *)
102 // Really this must be used for ACE_TSS_Emulation code to make the TSS
107 ACE_TSS_Emulation_cleanup (void *)
109 // Really this must be used for ACE_TSS_Emulation code to make the TSS
112 # endif /* ACE_HAS_THR_C_FUNC */
115 ACE_TSS_Emulation::tss_base (void* ts_storage
[], u_int
*ts_created
)
117 // TSS Singleton implementation.
119 // Create the one native TSS key, if necessary.
122 // Double-checked lock . . .
127 if (ACE_OS::thr_keycreate_native (&native_tss_key_
,
128 &ACE_TSS_Emulation_cleanup
) != 0)
131 return 0; // Major problems, this should *never* happen!
137 void **old_ts_storage
= 0;
139 // Get the tss_storage from thread-OS specific storage.
140 if (ACE_OS::thr_getspecific_native (native_tss_key_
,
141 (void **) &old_ts_storage
) == -1)
144 return 0; // This should not happen!
147 // Check to see if this is the first time in for this thread.
148 // This block can also be entered after a fork () in the child process.
149 if (old_ts_storage
== 0)
154 // Use the ts_storage passed as argument, if non-zero. It is
155 // possible that this has been implemented in the stack. At the
156 // moment, this is unknown. The cleanup must not do nothing.
157 // If ts_storage is zero, allocate (and eventually leak) the
161 #ifdef ACE_HAS_ALLOC_HOOKS
162 const size_t n
= ACE_TSS_THREAD_KEYS_MAX
* sizeof (void *);
163 ACE_Allocator
*const alloc
= ACE_Allocator::instance ();
164 ACE_ALLOCATOR_RETURN (ts_storage
,
165 static_cast<void **> (alloc
->malloc (n
)), 0);
167 ACE_NEW_RETURN (ts_storage
,
168 void*[ACE_TSS_THREAD_KEYS_MAX
],
172 // Zero the entire TSS array. Do it manually instead of
173 // using memset, for optimum speed. Though, memset may be
175 void **tss_base_p
= ts_storage
;
178 i
< ACE_TSS_THREAD_KEYS_MAX
;
183 // Store the pointer in thread-specific storage. It gets
184 // deleted via the ACE_TSS_Emulation_cleanup function when the
185 // thread terminates.
186 if (ACE_OS::thr_setspecific_native (native_tss_key_
,
187 (void *) ts_storage
) != 0)
190 return 0; // This should not happen!
197 return ts_storage
? ts_storage
: old_ts_storage
;
199 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
202 ACE_TSS_Emulation::total_keys ()
204 ACE_OS_Recursive_Thread_Mutex_Guard (
205 *static_cast <ACE_recursive_thread_mutex_t
*>
206 (ACE_OS_Object_Manager::preallocated_object
[
207 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
213 ACE_TSS_Emulation::next_key (ACE_thread_key_t
&key
)
215 ACE_OS_Recursive_Thread_Mutex_Guard (
216 *static_cast <ACE_recursive_thread_mutex_t
*>
217 (ACE_OS_Object_Manager::preallocated_object
[
218 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
220 // Initialize the tss_keys_used_ pointer on first use.
221 if (tss_keys_used_
== 0)
223 ACE_NEW_RETURN (tss_keys_used_
, ACE_TSS_Keys
, -1);
226 if (total_keys_
< ACE_TSS_THREAD_KEYS_MAX
)
229 // Loop through all possible keys and check whether a key is free
230 for ( ;counter
< ACE_TSS_THREAD_KEYS_MAX
; counter
++)
232 ACE_thread_key_t localkey
= counter
;
233 // If the key is not set as used, we can give out this key, if not
234 // we have to search further
235 if (tss_keys_used_
->is_set(localkey
) == 0)
237 tss_keys_used_
->test_and_set(localkey
);
248 key
= ACE_OS::NULL_key
;
254 ACE_TSS_Emulation::release_key (ACE_thread_key_t key
)
256 ACE_OS_Recursive_Thread_Mutex_Guard (
257 *static_cast <ACE_recursive_thread_mutex_t
*>
258 (ACE_OS_Object_Manager::preallocated_object
[
259 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
261 if (tss_keys_used_
!= 0 &&
262 tss_keys_used_
->test_and_clear (key
) == 0)
271 ACE_TSS_Emulation::is_key (ACE_thread_key_t key
)
273 ACE_OS_Recursive_Thread_Mutex_Guard (
274 *static_cast <ACE_recursive_thread_mutex_t
*>
275 (ACE_OS_Object_Manager::preallocated_object
[
276 ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK
]));
278 if (tss_keys_used_
!= 0 &&
279 tss_keys_used_
->is_set (key
) == 1)
287 ACE_TSS_Emulation::tss_open (void *ts_storage
[ACE_TSS_THREAD_KEYS_MAX
])
289 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
290 // On VxWorks, in particular, don't check to see if the field
291 // is 0. It isn't always, specifically, when a program is run
292 // directly by the shell (without spawning a new task) after
293 // another program has been run.
295 u_int ts_created
= 0;
296 tss_base (ts_storage
, &ts_created
);
299 # else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
300 tss_base () = ts_storage
;
303 // Zero the entire TSS array. Do it manually instead of using
304 // memset, for optimum speed. Though, memset may be faster :-)
305 void **tss_base_p
= tss_base ();
306 for (u_int i
= 0; i
< ACE_TSS_THREAD_KEYS_MAX
; ++i
, ++tss_base_p
)
312 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
318 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
322 ACE_TSS_Emulation::tss_close ()
324 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
325 ACE_OS::thr_keyfree_native (native_tss_key_
);
326 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
329 #endif /* ACE_HAS_TSS_EMULATION */
331 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
333 /*****************************************************************************/
335 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
337 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
338 // the single file of template instantiations.
340 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id
)
343 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
346 ACE_TSS_Ref::ACE_TSS_Ref ()
348 ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
351 // Check for equality.
353 ACE_TSS_Ref::operator== (const ACE_TSS_Ref
&info
) const
355 ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
357 #ifdef ACE_THREAD_T_IS_A_STRUCT
358 return 0 == ACE_OS::memcmp (&this->tid_
, &info
.tid_
, sizeof tid_
);
360 return this->tid_
== info
.tid_
;
364 // Check for inequality.
366 ACE_TSS_Ref::operator != (const ACE_TSS_Ref
&tss_ref
) const
368 ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
370 return !(*this == tss_ref
);
373 // moved class ACE_TSS_Info declaration
374 // to OS.h so it can be visible to the
375 // single file of template instantiations
377 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key
,
378 ACE_TSS_Info::Destructor dest
)
383 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
386 ACE_TSS_Info::ACE_TSS_Info ()
387 : key_ (ACE_OS::NULL_key
),
391 ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
394 // Check for equality.
396 ACE_TSS_Info::operator== (const ACE_TSS_Info
&info
) const
398 ACE_OS_TRACE ("ACE_TSS_Info::operator==");
400 return this->key_
== info
.key_
;
403 // Check for inequality.
405 ACE_TSS_Info::operator != (const ACE_TSS_Info
&info
) const
407 ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
409 return !(*this == info
);
413 ACE_TSS_Info::dump ()
415 # if defined (ACE_HAS_DUMP)
416 // ACE_OS_TRACE ("ACE_TSS_Info::dump");
419 ACELIB_DEBUG ((LM_DEBUG
, ACE_BEGIN_DUMP
, this));
420 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("key_ = %u\n"), this->key_
));
421 ACELIB_DEBUG ((LM_DEBUG
, ACE_TEXT ("destructor_ = %u\n"), this->destructor_
));
422 ACELIB_DEBUG ((LM_DEBUG
, ACE_END_DUMP
));
424 # endif /* ACE_HAS_DUMP */
427 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
428 // to the single file of template instantiations.
430 ACE_TSS_Keys::ACE_TSS_Keys ()
432 for (u_int i
= 0; i
< ACE_WORDS
; ++i
)
434 key_bit_words_
[i
] = 0;
440 ACE_TSS_Keys::find (const u_int key
, u_int
&word
, u_int
&bit
)
442 word
= key
/ ACE_BITS_PER_WORD
;
443 bit
= key
% ACE_BITS_PER_WORD
;
447 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key
)
450 find (key
, word
, bit
);
452 if (ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
))
458 ACE_SET_BITS (key_bit_words_
[word
], 1 << bit
);
464 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key
)
467 find (key
, word
, bit
);
469 if (word
< ACE_WORDS
&& ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
))
471 ACE_CLR_BITS (key_bit_words_
[word
], 1 << bit
);
481 ACE_TSS_Keys::is_set (const ACE_thread_key_t key
) const
484 find (key
, word
, bit
);
486 return word
< ACE_WORDS
? ACE_BIT_ENABLED (key_bit_words_
[word
], 1 << bit
) : 0;
490 * @class ACE_TSS_Cleanup
491 * @brief Singleton that helps to manage the lifetime of TSS objects and keys.
493 class ACE_TSS_Cleanup
496 ACE_ALLOC_HOOK_DECLARE
;
498 /// Register a newly-allocated key
499 /// @param key the key to be monitored
500 /// @param destructor the function to call to delete objects stored via this key
501 int insert (ACE_thread_key_t key
, void (*destructor
)(void *));
503 /// Mark a key as being used by this thread.
504 void thread_use_key (ACE_thread_key_t key
);
506 /// This thread is no longer using this key
507 /// call destructor if appropriate
508 int thread_detach_key (ACE_thread_key_t key
);
510 /// This key is no longer used
511 /// Release key if use count == 0
512 /// fail if use_count != 0;
513 /// @param key the key to be released
514 int free_key (ACE_thread_key_t key
);
516 /// Cleanup the thread-specific objects. Does _NOT_ exit the thread.
517 /// For each used key perform the same actions as free_key.
523 /// Release a key used by this thread
524 /// @param info reference to the info for this key
525 /// @param destructor out arg to receive destructor function ptr
526 /// @param tss_obj out arg to receive pointer to deletable object
527 void thread_release (
529 ACE_TSS_Info::Destructor
& destructor
,
532 /// remove key if it's unused (thread_count == 0)
533 /// @param info reference to the info for this key
534 int remove_key (ACE_TSS_Info
&info
);
536 /// Find the TSS keys (if any) for this thread.
537 /// @param thread_keys reference to pointer to be filled in by this function.
538 /// @return false if keys don't exist.
539 bool find_tss_keys (ACE_TSS_Keys
*& thread_keys
) const;
541 /// Accessor for this threads ACE_TSS_Keys instance.
542 /// Creates the keys if necessary.
543 ACE_TSS_Keys
*tss_keys ();
545 /// Ensure singleton.
549 /// ACE_TSS_Cleanup access only via TSS_Cleanup_Instance
550 friend class TSS_Cleanup_Instance
;
553 // Array of <ACE_TSS_Info> objects.
554 typedef ACE_TSS_Info ACE_TSS_TABLE
[ACE_DEFAULT_THREAD_KEYS
];
555 typedef ACE_TSS_Info
*ACE_TSS_TABLE_ITERATOR
;
557 /// Table of <ACE_TSS_Info>'s.
558 ACE_TSS_TABLE table_
;
560 /// Key for the thread-specific ACE_TSS_Keys
561 /// Used by find_tss_keys() or tss_keys() to find the
562 /// bit array that records whether each TSS key is in
563 /// use by this thread.
564 ACE_thread_key_t in_use_
;
567 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Cleanup
);
568 ACE_ALLOC_HOOK_DEFINE (ACE_TSS_Keys
);
570 /*****************************************************************************/
572 * @class TSS_Cleanup_Instance
573 * @A class to manage an instance pointer to ACE_TSS_Cleanup.
574 * Note: that the double checked locking pattern doesn't allow
576 * Callers who wish to access the singleton ACE_TSS_Cleanup must
577 * do so by instantiating a TSS_Cleanup_Instance, calling the valid
578 * method to be sure the ACE_TSS_Cleanup is available, then using
579 * the TSS_Cleanup_Instance as a pointer to the instance.
580 * Construction argument to the TSS_Cleanup_Instance determines how
582 * CREATE means allow this call to create an ACE_TSS_Cleanup if necessary.
583 * USE means use the existing ACE_TSS_Cleanup, but do not create a new one.
584 * DESTROY means provide exclusive access to the ACE_TSS_Cleanup, then
585 * delete it when the TSS_Cleanup_Instance goes out of scope.
588 class TSS_Cleanup_Instance
597 explicit TSS_Cleanup_Instance (Purpose purpose
= USE
);
598 ~TSS_Cleanup_Instance();
601 ACE_TSS_Cleanup
* operator ->();
604 ACE_TSS_Cleanup
* operator *();
607 static unsigned int reference_count_
;
608 static ACE_TSS_Cleanup
* instance_
;
609 static ACE_Thread_Mutex
* mutex_
;
610 static ACE_Condition_Thread_Mutex
* condition_
;
613 ACE_TSS_Cleanup
* ptr_
;
614 unsigned short flags_
;
618 FLAG_VALID_CHECKED
= 2
622 TSS_Cleanup_Instance::TSS_Cleanup_Instance (Purpose purpose
)
626 // During static construction or construction of the ACE_Object_Manager,
627 // there can be only one thread in this constructor at any one time, so
628 // it's safe to check for a zero mutex_. If it's zero, we create a new
629 // mutex and condition variable.
632 ACE_NEW (mutex_
, ACE_Thread_Mutex ());
633 ACE_NEW (condition_
, ACE_Condition_Thread_Mutex (*mutex_
));
636 ACE_GUARD (ACE_Thread_Mutex
, m
, *mutex_
);
638 if (purpose
== CREATE
)
642 instance_
= new ACE_TSS_Cleanup();
647 else if(purpose
== DESTROY
)
653 ACE_SET_BITS(flags_
, FLAG_DELETING
);
654 while (reference_count_
> 0)
660 else // must be normal use
662 ACE_ASSERT(purpose
== USE
);
671 TSS_Cleanup_Instance::~TSS_Cleanup_Instance ()
673 // Variable to hold the mutex_ to delete outside the scope of the
675 ACE_Thread_Mutex
*del_mutex
= 0;
679 ACE_GUARD (ACE_Thread_Mutex
, guard
, *mutex_
);
682 if (ACE_BIT_ENABLED (flags_
, FLAG_DELETING
))
684 ACE_ASSERT(instance_
== 0);
685 ACE_ASSERT(reference_count_
== 0);
692 ACE_ASSERT (reference_count_
> 0);
694 if (reference_count_
== 0 && instance_
== 0)
695 condition_
->signal ();
698 }// end of guard scope
709 TSS_Cleanup_Instance::valid()
711 ACE_SET_BITS(flags_
, FLAG_VALID_CHECKED
);
712 return (this->instance_
!= 0);
716 TSS_Cleanup_Instance::operator *()
718 ACE_ASSERT(ACE_BIT_ENABLED(flags_
, FLAG_VALID_CHECKED
));
723 TSS_Cleanup_Instance::operator ->()
725 ACE_ASSERT(ACE_BIT_ENABLED(flags_
, FLAG_VALID_CHECKED
));
729 // = Static object initialization.
730 unsigned int TSS_Cleanup_Instance::reference_count_
= 0;
731 ACE_TSS_Cleanup
* TSS_Cleanup_Instance::instance_
= 0;
732 ACE_Thread_Mutex
* TSS_Cleanup_Instance::mutex_
= 0;
733 ACE_Condition_Thread_Mutex
* TSS_Cleanup_Instance::condition_
= 0;
735 ACE_TSS_Cleanup::~ACE_TSS_Cleanup ()
740 ACE_TSS_Cleanup::thread_exit ()
742 ACE_OS_TRACE ("ACE_TSS_Cleanup::thread_exit");
743 // variables to hold the destructors, keys
744 // and pointers to the object to be destructed
745 // the actual destruction is deferred until the guard is released
746 ACE_TSS_Info::Destructor destructor
[ACE_DEFAULT_THREAD_KEYS
];
747 void * tss_obj
[ACE_DEFAULT_THREAD_KEYS
];
748 ACE_thread_key_t keys
[ACE_DEFAULT_THREAD_KEYS
];
749 // count of items to be destroyed
750 unsigned int d_count
= 0;
754 ACE_TSS_CLEANUP_GUARD
756 // if not initialized or already cleaned up
757 ACE_TSS_Keys
*this_thread_keys
= 0;
758 if (! find_tss_keys (this_thread_keys
) )
763 // Minor hack: Iterating in reverse order means the LOG buffer which is
764 // accidentally allocated first will be accidentally deallocated (almost)
765 // last -- in case someone logs something from the other destructors.
766 // applications should not count on this behavior because platforms which
767 // do not use ACE_TSS_Cleanup may delete objects in other orders.
768 unsigned int key_index
= ACE_DEFAULT_THREAD_KEYS
;
769 while( key_index
> 0)
772 ACE_TSS_Info
& info
= this->table_
[key_index
];
773 // if this key is in use by this thread
774 if (info
.key_in_use () && this_thread_keys
->is_set(info
.key_
))
776 // defer deleting the in-use key until all others have been deleted
777 if(info
.key_
!= this->in_use_
)
779 destructor
[d_count
] = 0;
780 tss_obj
[d_count
] = 0;
782 this->thread_release (info
, destructor
[d_count
], tss_obj
[d_count
]);
783 if (destructor
[d_count
] != 0 && tss_obj
[d_count
] != 0)
785 keys
[d_count
] = info
.key_
;
792 // remove the in_use bit vector last
793 u_int use_index
= this->in_use_
;
794 ACE_TSS_Info
& info
= this->table_
[use_index
];
795 destructor
[d_count
] = 0;
796 tss_obj
[d_count
] = 0;
798 this->thread_release (info
, destructor
[d_count
], tss_obj
[d_count
]);
799 if (destructor
[d_count
] != 0 && tss_obj
[d_count
] != 0)
801 keys
[d_count
] = info
.key_
;
804 } // end of guard scope
805 for (unsigned int d_index
= 0; d_index
< d_count
; ++d_index
)
807 (*destructor
[d_index
])(tss_obj
[d_index
]);
808 #if defined (ACE_HAS_TSS_EMULATION)
809 ACE_TSS_Emulation::ts_object (keys
[d_index
]) = 0;
810 #else // defined (ACE_HAS_TSS_EMULATION)
811 ACE_OS::thr_setspecific_native (keys
[d_index
], 0);
812 #endif // defined (ACE_HAS_TSS_EMULATION)
817 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys
)
819 delete static_cast <ACE_TSS_Keys
*> (tss_keys
);
822 ACE_TSS_Cleanup::ACE_TSS_Cleanup ()
823 : in_use_ (ACE_OS::NULL_key
)
825 ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
829 ACE_TSS_Cleanup::insert (ACE_thread_key_t key
,
830 void (*destructor
)(void *))
832 ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
833 ACE_TSS_CLEANUP_GUARD
835 u_int key_index
= key
;
836 ACE_ASSERT (key_index
< ACE_DEFAULT_THREAD_KEYS
);
837 if (key_index
< ACE_DEFAULT_THREAD_KEYS
)
839 ACE_ASSERT (table_
[key_index
].thread_count_
== -1);
840 table_
[key_index
] = ACE_TSS_Info (key
, destructor
);
841 table_
[key_index
].thread_count_
= 0; // inserting it does not use it
842 // but it does "allocate" it
852 ACE_TSS_Cleanup::free_key (ACE_thread_key_t key
)
854 ACE_OS_TRACE ("ACE_TSS_Cleanup::free_key");
855 ACE_TSS_CLEANUP_GUARD
856 u_int key_index
= key
;
857 if (key_index
< ACE_DEFAULT_THREAD_KEYS
)
859 return remove_key (this->table_
[key_index
]);
865 ACE_TSS_Cleanup::remove_key (ACE_TSS_Info
&info
)
867 // assume CLEANUP_GUARD is held by caller
868 ACE_OS_TRACE ("ACE_TSS_Cleanup::remove_key");
870 #if 0 // This was a good idea, but POSIX says it's legal to delete used keys.
871 // When this is done, any existing TSS objects controlled by this key are leaked
872 // There is no "right thing" to do in this case
874 // only remove it if all threads are done with it
875 if (info
.thread_count_
!= 0)
881 #if !defined (ACE_HAS_TSS_EMULATION)
882 ACE_OS_thread_key_t temp_key
= info
.key_
;
883 ACE_OS::thr_keyfree_native (temp_key
);
884 #endif /* !ACE_HAS_TSS_EMULATION */
885 if (info
.key_
== this->in_use_
)
887 this->in_use_
= ACE_OS::NULL_key
;
890 info
.destructor_
= 0;
895 ACE_TSS_Cleanup::thread_detach_key (ACE_thread_key_t key
)
897 // variables to hold the destructor and the object to be destructed
898 // the actual call is deferred until the guard is released
899 ACE_TSS_Info::Destructor destructor
= 0;
904 ACE_TSS_CLEANUP_GUARD
906 u_int key_index
= key
;
907 ACE_ASSERT (key_index
< sizeof(this->table_
)/sizeof(this->table_
[0]));
908 // If this entry was never set, just bug out. If it is set, but is the
909 // wrong key, assert.
910 if (this->table_
[key_index
].key_
== 0)
912 ACE_ASSERT (this->table_
[key_index
].key_
== key
);
913 ACE_TSS_Info
&info
= this->table_
[key_index
];
916 if (!info
.key_in_use ())
921 this->thread_release (info
, destructor
, tss_obj
);
922 } // end of scope for the Guard
923 // if there's a destructor and an object to be destroyed
924 if (destructor
!= 0 && tss_obj
!= 0)
926 (*destructor
) (tss_obj
);
932 ACE_TSS_Cleanup::thread_release (
934 ACE_TSS_Info::Destructor
& destructor
,
937 // assume guard is held by caller
938 // Find the TSS keys (if any) for this thread
939 // do not create them if they don't exist
940 ACE_TSS_Keys
* thread_keys
= 0;
941 if (find_tss_keys (thread_keys
))
943 // if this key is in use by this thread
944 if (thread_keys
->test_and_clear(info
.key_
) == 0)
946 // save destructor & pointer to tss object
947 // until after the guard is released
948 destructor
= info
.destructor_
;
949 ACE_OS::thr_getspecific (info
.key_
, &tss_obj
);
950 ACE_ASSERT (info
.thread_count_
> 0);
951 --info
.thread_count_
;
957 ACE_TSS_Cleanup::thread_use_key (ACE_thread_key_t key
)
959 // If the key's ACE_TSS_Info in-use bit for this thread is not set,
960 // set it and increment the key's thread_count_.
961 if (! tss_keys ()->test_and_set (key
))
963 ACE_TSS_CLEANUP_GUARD
965 // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
966 u_int key_index
= key
;
967 ACE_TSS_Info
&key_info
= this->table_
[key_index
];
969 ACE_ASSERT (key_info
.key_in_use ());
970 ++key_info
.thread_count_
;
975 ACE_TSS_Cleanup::dump ()
977 # if defined (ACE_HAS_DUMP)
978 // Iterate through all the thread-specific items and dump them all.
980 ACE_TSS_TABLE_ITERATOR key_info
= table_
;
981 for (unsigned int i
= 0;
982 i
< ACE_DEFAULT_THREAD_KEYS
;
985 # endif /* ACE_HAS_DUMP */
989 ACE_TSS_Cleanup::find_tss_keys (ACE_TSS_Keys
*& tss_keys
) const
991 if (this->in_use_
== ACE_OS::NULL_key
)
993 if (ACE_OS::thr_getspecific (in_use_
,
994 reinterpret_cast<void **> (&tss_keys
)) == -1)
997 return false; // This should not happen!
999 return tss_keys
!= 0;
1003 ACE_TSS_Cleanup::tss_keys ()
1005 if (this->in_use_
== ACE_OS::NULL_key
)
1007 ACE_TSS_CLEANUP_GUARD
1009 if (in_use_
== ACE_OS::NULL_key
)
1011 // Initialize in_use_ with a new key.
1012 if (ACE_OS::thr_keycreate (&in_use_
,
1013 &ACE_TSS_Cleanup_keys_destroyer
))
1016 return 0; // Major problems, this should *never* happen!
1022 if (ACE_OS::thr_getspecific (in_use_
, &ts_keys
) == -1)
1025 return 0; // This should not happen!
1030 ACE_NEW_RETURN (ts_keys
,
1033 // Store the dynamically allocated pointer in thread-specific
1035 if (ACE_OS::thr_setspecific (in_use_
, ts_keys
) == -1)
1038 delete reinterpret_cast <ACE_TSS_Keys
*> (ts_keys
);
1039 return 0; // Major problems, this should *never* happen!
1043 return reinterpret_cast <ACE_TSS_Keys
*>(ts_keys
);
1046 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
1048 /*****************************************************************************/
1050 // = Static initialization.
1052 // This is necessary to deal with POSIX pthreads insanity. This
1053 // guarantees that we've got a "zero'd" thread id even when
1054 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
1055 // as structures... Under no circumstances should these be given
1057 // Note: these three objects require static construction.
1058 ACE_thread_t
ACE_OS::NULL_thread
;
1059 ACE_hthread_t
ACE_OS::NULL_hthread
;
1060 #if defined (ACE_HAS_TSS_EMULATION)
1061 ACE_thread_key_t
ACE_OS::NULL_key
= static_cast <ACE_thread_key_t
> (-1);
1062 #else /* ! ACE_HAS_TSS_EMULATION */
1063 ACE_thread_key_t
ACE_OS::NULL_key
;
1064 #endif /* ! ACE_HAS_TSS_EMULATION */
1066 /*****************************************************************************/
1069 ACE_OS::cleanup_tss (const u_int main_thread
)
1071 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32)
1072 { // scope the cleanup instance
1073 // Call TSS destructors for current thread.
1074 TSS_Cleanup_Instance cleanup
;
1075 if (cleanup
.valid ())
1077 cleanup
->thread_exit ();
1080 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 */
1084 #if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS)
1085 // Just close the ACE_Log_Msg for the current (which should be
1086 // main) thread. We don't have TSS emulation; if there's native
1087 // TSS, it should call its destructors when the main thread
1089 ACE_Base_Thread_Adapter::close_log_msg ();
1090 #endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */
1092 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
1093 // Finally, free up the ACE_TSS_Cleanup instance. This method gets
1094 // called by the ACE_Object_Manager.
1095 TSS_Cleanup_Instance
cleanup(TSS_Cleanup_Instance::DESTROY
);
1096 if (cleanup
.valid ())
1098 ; // the pointer deletes the Cleanup when it goes out of scope
1101 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
1103 #if defined (ACE_HAS_TSS_EMULATION)
1104 ACE_TSS_Emulation::tss_close ();
1105 #endif /* ACE_HAS_TSS_EMULATION */
1109 /*****************************************************************************/
1111 /*****************************************************************************/
1113 #if defined (ACE_LACKS_COND_T)
1115 ACE_OS::cond_broadcast (ACE_cond_t
*cv
)
1117 ACE_OS_TRACE ("ACE_OS::cond_broadcast");
1118 # if defined (ACE_HAS_THREADS)
1119 // The <external_mutex> must be locked before this call is made.
1121 // This is needed to ensure that <waiters_> and <was_broadcast_> are
1122 // consistent relative to each other.
1123 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1128 bool have_waiters
= false;
1130 if (cv
->waiters_
> 0)
1132 // We are broadcasting, even if there is just one waiter...
1133 // Record the fact that we are broadcasting. This helps the
1134 // cond_wait() method know how to optimize itself. Be sure to
1135 // set this with the <waiters_lock_> held.
1136 cv
->was_broadcast_
= 1;
1137 have_waiters
= true;
1140 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1142 // This is really bad, we have the lock but can't release it anymore
1149 // Wake up all the waiters.
1150 if (ACE_OS::sema_post (&cv
->sema_
, cv
->waiters_
) == -1)
1152 // Wait for all the awakened threads to acquire their part of
1153 // the counting semaphore.
1154 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1155 else if (ACE_OS::sema_wait (&cv
->waiters_done_
) == -1)
1157 else if (ACE_OS::event_wait (&cv
->waiters_done_
) == -1)
1158 # endif /* ACE_VXWORKS */
1160 // This is okay, even without the <waiters_lock_> held because
1161 // no other waiter threads can wake up to access it.
1162 cv
->was_broadcast_
= 0;
1166 ACE_UNUSED_ARG (cv
);
1167 ACE_NOTSUP_RETURN (-1);
1168 # endif /* ACE_HAS_THREADS */
1172 ACE_OS::cond_destroy (ACE_cond_t
*cv
)
1174 ACE_OS_TRACE ("ACE_OS::cond_destroy");
1175 # if defined (ACE_HAS_THREADS)
1176 # if defined (ACE_HAS_WTHREADS)
1177 ACE_OS::event_destroy (&cv
->waiters_done_
);
1178 # elif defined (ACE_VXWORKS) || defined (ACE_MQX)
1179 ACE_OS::sema_destroy (&cv
->waiters_done_
);
1180 # endif /* ACE_VXWORKS */
1182 if (ACE_OS::thread_mutex_destroy (&cv
->waiters_lock_
) != 0)
1185 if (ACE_OS::sema_destroy (&cv
->sema_
) != 0)
1190 ACE_UNUSED_ARG (cv
);
1191 ACE_NOTSUP_RETURN (-1);
1192 # endif /* ACE_HAS_THREADS */
1196 ACE_OS::cond_init (ACE_cond_t
*cv
,
1197 ACE_condattr_t
&attributes
,
1198 const char *name
, void *arg
)
1201 ACE_OS::cond_init (cv
, static_cast<short> (attributes
.type
), name
, arg
);
1204 # if defined (ACE_HAS_WCHAR)
1206 ACE_OS::cond_init (ACE_cond_t
*cv
,
1207 ACE_condattr_t
&attributes
,
1208 const wchar_t *name
, void *arg
)
1211 ACE_OS::cond_init (cv
, static_cast<short> (attributes
.type
), name
, arg
);
1213 # endif /* ACE_HAS_WCHAR */
1216 ACE_OS::cond_init (ACE_cond_t
*cv
, short type
, const char *name
, void *arg
)
1218 ACE_OS_TRACE ("ACE_OS::cond_init");
1219 # if defined (ACE_HAS_THREADS)
1221 cv
->was_broadcast_
= 0;
1224 if (ACE_OS::sema_init (&cv
->sema_
, 0, type
, name
, arg
) == -1)
1226 else if (ACE_OS::thread_mutex_init (&cv
->waiters_lock_
) == -1)
1228 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1229 else if (ACE_OS::sema_init (&cv
->waiters_done_
, 0, type
) == -1)
1231 else if (ACE_OS::event_init (&cv
->waiters_done_
) == -1)
1232 # endif /* ACE_VXWORKS */
1236 ACE_UNUSED_ARG (cv
);
1237 ACE_UNUSED_ARG (type
);
1238 ACE_UNUSED_ARG (name
);
1239 ACE_UNUSED_ARG (arg
);
1240 ACE_NOTSUP_RETURN (-1);
1241 # endif /* ACE_HAS_THREADS */
1244 # if defined (ACE_HAS_WCHAR)
1246 ACE_OS::cond_init (ACE_cond_t
*cv
, short type
, const wchar_t *name
, void *arg
)
1248 ACE_OS_TRACE ("ACE_OS::cond_init");
1249 # if defined (ACE_HAS_THREADS)
1251 cv
->was_broadcast_
= 0;
1254 if (ACE_OS::sema_init (&cv
->sema_
, 0, type
, name
, arg
) == -1)
1256 else if (ACE_OS::thread_mutex_init (&cv
->waiters_lock_
) == -1)
1258 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1259 else if (ACE_OS::sema_init (&cv
->waiters_done_
, 0, type
) == -1)
1261 else if (ACE_OS::event_init (&cv
->waiters_done_
) == -1)
1262 # endif /* ACE_VXWORKS */
1266 ACE_UNUSED_ARG (cv
);
1267 ACE_UNUSED_ARG (type
);
1268 ACE_UNUSED_ARG (name
);
1269 ACE_UNUSED_ARG (arg
);
1270 ACE_NOTSUP_RETURN (-1);
1271 # endif /* ACE_HAS_THREADS */
1273 # endif /* ACE_HAS_WCHAR */
1276 ACE_OS::cond_signal (ACE_cond_t
*cv
)
1278 ACE_OS_TRACE ("ACE_OS::cond_signal");
1279 # if defined (ACE_HAS_THREADS)
1280 // If there aren't any waiters, then this is a no-op. Note that
1281 // this function *must* be called with the <external_mutex> held
1282 // since other wise there is a race condition that can lead to the
1283 // lost wakeup bug... This is needed to ensure that the <waiters_>
1284 // value is not in an inconsistent internal state while being
1285 // updated by another thread.
1286 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1288 bool const have_waiters
= cv
->waiters_
> 0;
1289 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1293 return ACE_OS::sema_post (&cv
->sema_
);
1297 ACE_UNUSED_ARG (cv
);
1298 ACE_NOTSUP_RETURN (-1);
1299 # endif /* ACE_HAS_THREADS */
1303 ACE_OS::cond_wait (ACE_cond_t
*cv
,
1304 ACE_mutex_t
*external_mutex
)
1306 ACE_OS_TRACE ("ACE_OS::cond_wait");
1307 # if defined (ACE_HAS_THREADS)
1308 // Prevent race conditions on the <waiters_> count.
1309 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1314 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1319 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1320 if (external_mutex
->type_
== USYNC_PROCESS
)
1322 // This call will automatically release the mutex and wait on the semaphore.
1323 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex
->proc_mutex_
,
1324 cv
->sema_
, INFINITE
, FALSE
),
1331 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1333 // We keep the lock held just long enough to increment the count of
1334 // waiters by one. Note that we can't keep it held across the call
1335 // to ACE_OS::sema_wait() since that will deadlock other calls to
1336 // ACE_OS::cond_signal().
1337 if (ACE_OS::mutex_unlock (external_mutex
) != 0)
1340 // Wait to be awakened by a ACE_OS::cond_signal() or
1341 // ACE_OS::cond_broadcast().
1342 result
= ACE_OS::sema_wait (&cv
->sema_
);
1345 // Reacquire lock to avoid race conditions on the <waiters_> count.
1346 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1349 // We're ready to return, so there's one less waiter.
1352 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1354 // Release the lock so that other collaborating threads can make
1356 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1360 // Bad things happened, so let's just return below.
1362 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1363 else if (external_mutex
->type_
== USYNC_PROCESS
)
1367 // This call atomically signals the <waiters_done_> event and
1368 // waits until it can acquire the mutex. This is important to
1369 // prevent unfairness.
1370 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv
->waiters_done_
,
1371 external_mutex
->proc_mutex_
,
1376 // We must always regain the <external_mutex>, even when
1377 // errors occur because that's the guarantee that we give to
1379 if (ACE_OS::mutex_lock (external_mutex
) != 0)
1385 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1386 // If we're the last waiter thread during this particular broadcast
1387 // then let all the other threads proceed.
1388 else if (last_waiter
)
1389 # if defined (ACE_VXWORKS) || defined (ACE_MQX)
1390 ACE_OS::sema_post (&cv
->waiters_done_
);
1392 ACE_OS::event_signal (&cv
->waiters_done_
);
1393 # endif /* ACE_VXWORKS */
1395 // We must always regain the <external_mutex>, even when errors
1396 // occur because that's the guarantee that we give to our callers.
1397 ACE_OS::mutex_lock (external_mutex
);
1401 ACE_UNUSED_ARG (cv
);
1402 ACE_UNUSED_ARG (external_mutex
);
1403 ACE_NOTSUP_RETURN (-1);
1404 # endif /* ACE_HAS_THREADS */
1408 ACE_OS::cond_timedwait (ACE_cond_t
*cv
,
1409 ACE_mutex_t
*external_mutex
,
1410 ACE_Time_Value
*timeout
)
1412 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1413 # if defined (ACE_HAS_THREADS)
1414 // Handle the easy case first.
1416 return ACE_OS::cond_wait (cv
, external_mutex
);
1417 # if defined (ACE_HAS_WTHREADS) || defined (ACE_VXWORKS) || defined (ACE_MQX)
1419 // Prevent race conditions on the <waiters_> count.
1420 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1425 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1429 ACE_Errno_Guard
error (errno
, 0);
1430 int msec_timeout
= 0;
1432 if (timeout
!= 0 && *timeout
!= ACE_Time_Value::zero
)
1434 // Note that we must convert between absolute time (which is
1435 // passed as a parameter) and relative time (which is what
1436 // WaitForSingleObjects() expects).
1437 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
1439 // Watchout for situations where a context switch has caused the
1440 // current time to be > the timeout.
1441 if (relative_time
> ACE_Time_Value::zero
)
1442 msec_timeout
= relative_time
.msec ();
1445 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1446 if (external_mutex
->type_
== USYNC_PROCESS
)
1447 // This call will automatically release the mutex and wait on the
1449 result
= ::SignalObjectAndWait (external_mutex
->proc_mutex_
,
1454 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1456 // We keep the lock held just long enough to increment the count
1457 // of waiters by one. Note that we can't keep it held across
1458 // the call to WaitForSingleObject since that will deadlock
1459 // other calls to ACE_OS::cond_signal().
1460 if (ACE_OS::mutex_unlock (external_mutex
) != 0)
1463 // Wait to be awakened by a ACE_OS::signal() or
1464 // ACE_OS::broadcast().
1465 # if defined (ACE_WIN32)
1466 result
= ::WaitForSingleObject (cv
->sema_
, msec_timeout
);
1467 # elif defined (ACE_VXWORKS)
1468 // Inline the call to ACE_OS::sema_wait () because it takes an
1469 // ACE_Time_Value argument. Avoid the cost of that conversion . . .
1470 _Vx_freq_t
const ticks_per_sec
= ::sysClkRateGet ();
1471 int const ticks
= msec_timeout
* ticks_per_sec
/ ACE_ONE_SECOND_IN_MSECS
;
1472 result
= ::semTake (cv
->sema_
.sema_
, ticks
);
1474 result
= ACE_OS::sema_wait (&cv
->sema_
, timeout
);
1475 # endif /* ACE_WIN32 || VXWORKS */
1478 // Reacquire lock to avoid race conditions.
1479 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1484 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1486 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1489 # if defined (ACE_WIN32)
1490 if (result
!= (int)WAIT_OBJECT_0
)
1498 error
= ::GetLastError ();
1503 # elif defined (ACE_VXWORKS)
1504 if (result
== ERROR
)
1508 case S_objLib_OBJ_TIMEOUT
:
1511 case S_objLib_OBJ_UNAVAILABLE
:
1512 if (msec_timeout
== 0)
1521 # endif /* ACE_WIN32 || VXWORKS */
1522 # if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
1523 if (external_mutex
->type_
== USYNC_PROCESS
)
1526 // This call atomically signals the <waiters_done_> event and
1527 // waits until it can acquire the mutex. This is important to
1528 // prevent unfairness.
1529 ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv
->waiters_done_
,
1530 external_mutex
->proc_mutex_
,
1536 // We must always regain the <external_Mutex>, even when
1537 // errors occur because that's the guarantee that we give to
1539 if (ACE_OS::mutex_lock (external_mutex
) != 0)
1546 # endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
1547 // Note that this *must* be an "if" statement rather than an "else
1548 // if" statement since the caller may have timed out and hence the
1549 // result would have been -1 above.
1552 // Release the signaler/broadcaster if we're the last waiter.
1553 # if defined (ACE_WIN32)
1554 if (ACE_OS::event_signal (&cv
->waiters_done_
) != 0)
1556 if (ACE_OS::sema_post (&cv
->waiters_done_
) != 0)
1557 # endif /* ACE_WIN32 */
1561 // We must always regain the <external_mutex>, even when errors
1562 // occur because that's the guarantee that we give to our callers.
1563 if (ACE_OS::mutex_lock (external_mutex
) != 0)
1567 # endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS */
1569 ACE_UNUSED_ARG (cv
);
1570 ACE_UNUSED_ARG (external_mutex
);
1571 ACE_UNUSED_ARG (timeout
);
1572 ACE_NOTSUP_RETURN (-1);
1573 # endif /* ACE_HAS_THREADS */
1577 ACE_OS::cond_init (ACE_cond_t
*cv
, short type
, const char *name
, void *arg
)
1579 ACE_condattr_t attributes
;
1580 if (ACE_OS::condattr_init (attributes
, type
) == 0
1581 && ACE_OS::cond_init (cv
, attributes
, name
, arg
) == 0)
1583 (void) ACE_OS::condattr_destroy (attributes
);
1588 #endif /* ACE_LACKS_COND_T */
1590 #if defined (ACE_WIN32) && defined (ACE_HAS_WTHREADS)
1592 ACE_OS::cond_timedwait (ACE_cond_t
*cv
,
1593 ACE_thread_mutex_t
*external_mutex
,
1594 ACE_Time_Value
*timeout
)
1596 ACE_OS_TRACE ("ACE_OS::cond_timedwait");
1597 # if defined (ACE_HAS_THREADS)
1598 // Handle the easy case first.
1600 return ACE_OS::cond_wait (cv
, external_mutex
);
1602 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1603 int msec_timeout
= 0;
1606 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
1607 // Watchout for situations where a context switch has caused the
1608 // current time to be > the timeout.
1609 if (relative_time
> ACE_Time_Value::zero
)
1610 msec_timeout
= relative_time
.msec ();
1612 ACE_OSCALL (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv
, external_mutex
, msec_timeout
),
1617 // Prevent race conditions on the <waiters_> count.
1618 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1623 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1628 int msec_timeout
= 0;
1630 if (timeout
!= 0 && *timeout
!= ACE_Time_Value::zero
)
1632 // Note that we must convert between absolute time (which is
1633 // passed as a parameter) and relative time (which is what
1634 // WaitForSingleObjects() expects).
1635 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
1637 // Watchout for situations where a context switch has caused the
1638 // current time to be > the timeout.
1639 if (relative_time
> ACE_Time_Value::zero
)
1640 msec_timeout
= relative_time
.msec ();
1643 // We keep the lock held just long enough to increment the count of
1644 // waiters by one. Note that we can't keep it held across the call
1645 // to WaitForSingleObject since that will deadlock other calls to
1646 // ACE_OS::cond_signal().
1647 if (ACE_OS::thread_mutex_unlock (external_mutex
) != 0)
1650 // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
1651 result
= ::WaitForSingleObject (cv
->sema_
, msec_timeout
);
1653 // Reacquire lock to avoid race conditions.
1654 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1659 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1661 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1664 if (result
!= (int)WAIT_OBJECT_0
)
1672 error
= ::GetLastError ();
1680 // Release the signaler/broadcaster if we're the last waiter.
1681 if (ACE_OS::event_signal (&cv
->waiters_done_
) != 0)
1685 // We must always regain the <external_mutex>, even when errors
1686 // occur because that's the guarantee that we give to our callers.
1687 if (ACE_OS::thread_mutex_lock (external_mutex
) != 0)
1692 /* This assignment must only be done if error != 0,
1693 * since writing 0 to errno violates the POSIX specification.
1700 ACE_NOTSUP_RETURN (-1);
1701 # endif /* ACE_HAS_THREADS */
1705 ACE_OS::cond_wait (ACE_cond_t
*cv
,
1706 ACE_thread_mutex_t
*external_mutex
)
1708 ACE_OS_TRACE ("ACE_OS::cond_wait");
1709 # if defined (ACE_HAS_THREADS)
1710 # if defined (ACE_HAS_WTHREADS_CONDITION_VARIABLE)
1712 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::SleepConditionVariableCS (cv
, external_mutex
, INFINITE
), result
), int);
1714 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1718 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1724 // We keep the lock held just long enough to increment the count of
1725 // waiters by one. Note that we can't keep it held across the call
1726 // to ACE_OS::sema_wait() since that will deadlock other calls to
1727 // ACE_OS::cond_signal().
1728 if (ACE_OS::thread_mutex_unlock (external_mutex
) != 0)
1731 // Wait to be awakened by a ACE_OS::cond_signal() or
1732 // ACE_OS::cond_broadcast().
1733 result
= ::WaitForSingleObject (cv
->sema_
, INFINITE
);
1735 // Reacquire lock to avoid race conditions.
1736 if (ACE_OS::thread_mutex_lock (&cv
->waiters_lock_
) != 0)
1741 bool const last_waiter
= cv
->was_broadcast_
&& cv
->waiters_
== 0;
1743 if (ACE_OS::thread_mutex_unlock (&cv
->waiters_lock_
) != 0)
1746 if (result
!= (int)WAIT_OBJECT_0
)
1754 error
= ::GetLastError ();
1758 else if (last_waiter
)
1760 // Release the signaler/broadcaster if we're the last waiter.
1761 if (ACE_OS::event_signal (&cv
->waiters_done_
) != 0)
1765 // We must always regain the <external_mutex>, even when errors
1766 // occur because that's the guarantee that we give to our callers.
1767 if (ACE_OS::thread_mutex_lock (external_mutex
) != 0)
1770 // Reset errno in case mutex_lock() also fails...
1773 /* This assignment must only be done if error != 0,
1774 * since writing 0 to errno violates the POSIX specification.
1781 ACE_NOTSUP_RETURN (-1);
1782 # endif /* ACE_HAS_THREADS */
1784 # endif /* ACE_HAS_WTHREADS */
1786 /*****************************************************************************/
1788 /*****************************************************************************/
1790 /*****************************************************************************/
1792 /*****************************************************************************/
1795 ACE_OS::mutex_init (ACE_mutex_t
*m
,
1798 ACE_mutexattr_t
*attributes
,
1799 LPSECURITY_ATTRIBUTES sa
,
1802 // ACE_OS_TRACE ("ACE_OS::mutex_init");
1803 #if defined (ACE_HAS_THREADS)
1804 # if defined (ACE_HAS_PTHREADS)
1805 ACE_UNUSED_ARG (name
);
1806 ACE_UNUSED_ARG (sa
);
1808 # if defined (ACE_PTHREAD_MUTEXATTR_T_INITIALIZE)
1809 /* Tests show that VxWorks 6.x pthread lib does not only
1810 * require zeroing of mutex/condition objects to function correctly
1811 * but also of the attribute objects.
1813 pthread_mutexattr_t l_attributes
= {0};
1815 pthread_mutexattr_t l_attributes
;
1818 if (attributes
== 0)
1819 attributes
= &l_attributes
;
1821 int attr_init
= 0; // have we initialized the local attributes.
1823 // Only do these initializations if the <attributes> parameter
1824 // wasn't originally set.
1825 if (attributes
== &l_attributes
)
1827 if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes
), result
) == 0)
1830 attr_init
= 1; // we have initialized these attributes
1834 result
= -1; // ACE_ADAPT_RETVAL used it for intermediate status
1838 if (result
== 0 && lock_scope
!= 0)
1840 # if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED)
1841 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes
,
1844 # endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */
1847 if (result
== 0 && lock_type
!= 0)
1849 # if defined (ACE_HAS_RECURSIVE_MUTEXES) && !defined (ACE_LACKS_PTHREAD_MUTEXATTR_SETTYPE)
1850 (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes
,
1853 # endif /* ACE_HAS_RECURSIVE_MUTEXES */
1858 # if defined (ACE_PTHREAD_MUTEX_T_INITIALIZE)
1859 /* VxWorks 6.x API reference states:
1860 * If the memory for the mutex variable object has been allocated
1861 * dynamically, it is a good policy to always zero out the
1862 * block of memory so as to avoid spurious EBUSY return code
1863 * when calling this routine.
1864 * Tests shows this to be necessary.
1866 ACE_OS::memset (m
, 0, sizeof (*m
));
1868 if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m
, attributes
), result
) == 0)
1871 result
= -1; // ACE_ADAPT_RETVAL used it for intermediate status
1874 // Only do the deletions if the <attributes> parameter wasn't
1876 if (attributes
== &l_attributes
&& attr_init
)
1877 ::pthread_mutexattr_destroy (&l_attributes
);
1880 # elif defined (ACE_HAS_WTHREADS)
1881 m
->type_
= lock_scope
;
1883 SECURITY_ATTRIBUTES sa_buffer
;
1884 SECURITY_DESCRIPTOR sd_buffer
;
1889 ::CreateMutexA (ACE_OS::default_win32_security_attributes_r
1890 (sa
, &sa_buffer
, &sd_buffer
),
1893 if (m
->proc_mutex_
== 0)
1894 ACE_FAIL_RETURN (-1);
1897 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1898 ACE_OS::set_errno_to_last_error ();
1902 return ACE_OS::thread_mutex_init (&m
->thr_mutex_
,
1912 # elif defined (ACE_VXWORKS)
1913 ACE_UNUSED_ARG (name
);
1914 ACE_UNUSED_ARG (attributes
);
1915 ACE_UNUSED_ARG (sa
);
1916 ACE_UNUSED_ARG (lock_type
);
1918 return (*m
= ::semMCreate (lock_scope
)) == 0 ? -1 : 0;
1919 # endif /* ACE_HAS_PTHREADS */
1922 ACE_UNUSED_ARG (lock_scope
);
1923 ACE_UNUSED_ARG (name
);
1924 ACE_UNUSED_ARG (attributes
);
1925 ACE_UNUSED_ARG (sa
);
1926 ACE_UNUSED_ARG (lock_type
);
1927 ACE_NOTSUP_RETURN (-1);
1928 #endif /* ACE_HAS_THREADS */
1932 ACE_OS::mutex_destroy (ACE_mutex_t
*m
)
1934 ACE_OS_TRACE ("ACE_OS::mutex_destroy");
1935 #if defined (ACE_HAS_THREADS)
1936 # if defined (ACE_HAS_PTHREADS)
1937 # if defined (ACE_LACKS_PTHREAD_MUTEX_DESTROY)
1939 ACE_NOTSUP_RETURN (-1);
1942 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m
), result
), int);
1943 # endif /* ACE_LACKS_PTHREAD_MUTEX_DESTROY */
1944 # elif defined (ACE_HAS_WTHREADS)
1948 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m
->proc_mutex_
),
1952 return ACE_OS::thread_mutex_destroy (&m
->thr_mutex_
);
1958 # elif defined (ACE_VXWORKS)
1959 return ::semDelete (*m
) == OK
? 0 : -1;
1960 # endif /* Threads variety case */
1963 ACE_NOTSUP_RETURN (-1);
1964 #endif /* ACE_HAS_THREADS */
1967 #if defined (ACE_HAS_WCHAR)
1969 ACE_OS::mutex_init (ACE_mutex_t
*m
,
1971 const wchar_t *name
,
1972 ACE_mutexattr_t
*attributes
,
1973 LPSECURITY_ATTRIBUTES sa
,
1976 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
1977 m
->type_
= lock_scope
;
1978 SECURITY_ATTRIBUTES sa_buffer
;
1979 SECURITY_DESCRIPTOR sd_buffer
;
1984 ::CreateMutexW (ACE_OS::default_win32_security_attributes_r
1985 (sa
, &sa_buffer
, &sd_buffer
),
1988 if (m
->proc_mutex_
== 0)
1989 ACE_FAIL_RETURN (-1);
1992 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
1993 ACE_OS::set_errno_to_last_error ();
1997 return ACE_OS::thread_mutex_init (&m
->thr_mutex_
,
2005 #else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2006 return ACE_OS::mutex_init (m
,
2008 ACE_Wide_To_Ascii (name
).char_rep (),
2012 #endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */
2014 #endif /* ACE_HAS_WCHAR */
2017 ACE_OS::mutex_lock (ACE_mutex_t
*m
)
2019 // ACE_OS_TRACE ("ACE_OS::mutex_lock");
2020 #if defined (ACE_HAS_THREADS)
2021 # if defined (ACE_HAS_PTHREADS)
2022 // Note, don't use "::" here since the following call is often a macro.
2024 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m
), result
), int);
2025 # elif defined (ACE_HAS_WTHREADS)
2029 switch (::WaitForSingleObject (m
->proc_mutex_
, INFINITE
))
2032 // Timeout can't occur, so don't bother checking...
2035 case WAIT_ABANDONED
:
2036 // We will ignore abandonments in this method
2037 // Note that we still hold the lock
2040 // This is a hack, we need to find an appropriate mapping...
2041 ACE_OS::set_errno_to_last_error ();
2045 return ACE_OS::thread_mutex_lock (&m
->thr_mutex_
);
2051 # elif defined (ACE_VXWORKS)
2052 return ::semTake (*m
, WAIT_FOREVER
) == OK
? 0 : -1;
2053 # endif /* Threads variety case */
2056 ACE_NOTSUP_RETURN (-1);
2057 #endif /* ACE_HAS_THREADS */
2061 ACE_OS::mutex_lock (ACE_mutex_t
*m
,
2064 ACE_OS_TRACE ("ACE_OS::mutex_lock");
2065 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2070 switch (::WaitForSingleObject (m
->proc_mutex_
, INFINITE
))
2073 // Timeout can't occur, so don't bother checking...
2077 case WAIT_ABANDONED
:
2079 return 0; // something goofed, but we hold the lock ...
2081 // This is a hack, we need to find an appropriate mapping...
2082 ACE_OS::set_errno_to_last_error ();
2086 return ACE_OS::thread_mutex_lock (&m
->thr_mutex_
);
2094 ACE_UNUSED_ARG (abandoned
);
2095 ACE_NOTSUP_RETURN (-1);
2096 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2100 ACE_OS::mutex_lock (ACE_mutex_t
*m
,
2101 const ACE_Time_Value
&timeout
)
2103 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS)
2105 # if defined (ACE_HAS_PTHREADS)
2108 // "timeout" should be an absolute time.
2110 timespec_t ts
= timeout
; // Calls ACE_Time_Value::operator timespec_t().
2112 // Note that the mutex should not be a recursive one, i.e., it
2113 // should only be a standard mutex or an error checking mutex.
2115 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m
, &ts
), result
), int, result
);
2117 // We need to adjust this to make the errno values consistent.
2118 if (result
== -1 && errno
== ETIMEDOUT
)
2122 # elif defined (ACE_HAS_WTHREADS)
2123 // Note that we must convert between absolute time (which is passed
2124 // as a parameter) and relative time (which is what the system call
2126 ACE_Time_Value relative_time
= timeout
.to_relative_time ();
2131 switch (::WaitForSingleObject (m
->proc_mutex_
,
2132 relative_time
.msec ()))
2135 case WAIT_ABANDONED
:
2136 // We will ignore abandonments in this method
2137 // Note that we still hold the lock
2143 // This is a hack, we need to find an appropriate mapping...
2144 ACE_OS::set_errno_to_last_error ();
2148 ACE_NOTSUP_RETURN (-1);
2155 # elif defined (ACE_VXWORKS)
2157 // Note that we must convert between absolute time (which is passed
2158 // as a parameter) and relative time (which is what the system call
2160 ACE_Time_Value relative_time
= timeout
.to_relative_time ();
2162 _Vx_freq_t
const ticks_per_sec
= ::sysClkRateGet ();
2164 int ticks
= relative_time
.sec() * ticks_per_sec
+
2165 relative_time
.usec () * ticks_per_sec
/ ACE_ONE_SECOND_IN_USECS
;
2166 if (::semTake (*m
, ticks
) == ERROR
)
2168 if (errno
== S_objLib_OBJ_TIMEOUT
)
2169 // Convert the VxWorks errno to one that's common for to ACE
2172 else if (errno
== S_objLib_OBJ_UNAVAILABLE
)
2178 # endif /* ACE_HAS_PTHREADS */
2182 ACE_UNUSED_ARG (timeout
);
2183 ACE_NOTSUP_RETURN (-1);
2184 #endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */
2188 ACE_OS::mutex_trylock (ACE_mutex_t
*m
)
2190 ACE_OS_TRACE ("ACE_OS::mutex_trylock");
2191 #if defined (ACE_HAS_THREADS)
2192 # if defined (ACE_HAS_PTHREADS)
2193 // Note, don't use "::" here since the following call is often a macro.
2195 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m
), result
), int);
2196 # elif defined (ACE_HAS_WTHREADS)
2201 // Try for 0 milliseconds - i.e. nonblocking.
2202 switch (::WaitForSingleObject (m
->proc_mutex_
, 0))
2206 case WAIT_ABANDONED
:
2207 // We will ignore abandonments in this method. Note that
2208 // we still hold the lock.
2214 ACE_OS::set_errno_to_last_error ();
2219 return ACE_OS::thread_mutex_trylock (&m
->thr_mutex_
);
2225 # elif defined (ACE_VXWORKS)
2226 if (::semTake (*m
, NO_WAIT
) == ERROR
)
2227 if (errno
== S_objLib_OBJ_UNAVAILABLE
)
2229 // couldn't get the semaphore
2237 // got the semaphore
2239 # endif /* Threads variety case */
2242 ACE_NOTSUP_RETURN (-1);
2243 #endif /* ACE_HAS_THREADS */
2247 ACE_OS::mutex_trylock (ACE_mutex_t
*m
, int &abandoned
)
2249 #if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS)
2255 // Try for 0 milliseconds - i.e. nonblocking.
2256 switch (::WaitForSingleObject (m
->proc_mutex_
, 0))
2260 case WAIT_ABANDONED
:
2262 return 0; // something goofed, but we hold the lock ...
2267 ACE_OS::set_errno_to_last_error ();
2272 return ACE_OS::thread_mutex_trylock (&m
->thr_mutex_
);
2280 ACE_UNUSED_ARG (abandoned
);
2281 ACE_NOTSUP_RETURN (-1);
2282 #endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */
2286 ACE_OS::mutex_unlock (ACE_mutex_t
*m
)
2288 ACE_OS_TRACE ("ACE_OS::mutex_unlock");
2289 #if defined (ACE_HAS_THREADS)
2290 # if defined (ACE_HAS_PTHREADS)
2291 // Note, don't use "::" here since the following call is often a macro.
2293 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m
), result
), int);
2294 # elif defined (ACE_HAS_WTHREADS)
2298 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m
->proc_mutex_
),
2302 return ACE_OS::thread_mutex_unlock (&m
->thr_mutex_
);
2308 # elif defined (ACE_VXWORKS)
2309 return ::semGive (*m
) == OK
? 0 : -1;
2310 # endif /* Threads variety case */
2313 ACE_NOTSUP_RETURN (-1);
2314 #endif /* ACE_HAS_THREADS */
2318 ACE_OS::mutex_lock_cleanup (void *mutex
)
2320 ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
2321 #if defined (ACE_HAS_THREADS)
2322 # if defined (ACE_HAS_PTHREADS)
2323 ACE_mutex_t
*p_lock
= (ACE_mutex_t
*) mutex
;
2324 ACE_OS::mutex_unlock (p_lock
);
2326 ACE_UNUSED_ARG (mutex
);
2327 # endif /* ACE_HAS_PTHREADS */
2329 ACE_UNUSED_ARG (mutex
);
2330 #endif /* ACE_HAS_THREADS */
2333 /*****************************************************************************/
2335 /*****************************************************************************/
2337 /*****************************************************************************/
2339 /*****************************************************************************/
2343 int ACE_event_t::lock ()
2345 # if !ACE_EVENT_USE_MUTEX_PSHARED
2346 if (this->eventdata_
->type_
== USYNC_PROCESS
)
2347 return ACE_OS::sema_wait (&this->lock_
);
2349 return ACE_OS::mutex_lock (&this->eventdata_
->lock_
);
2352 int ACE_event_t::unlock ()
2354 # if !ACE_EVENT_USE_MUTEX_PSHARED
2355 if (this->eventdata_
->type_
== USYNC_PROCESS
)
2356 return ACE_OS::sema_post (&this->lock_
);
2358 return ACE_OS::mutex_unlock (&this->eventdata_
->lock_
);
2361 int ACE_event_t::wake_one ()
2363 # if !ACE_EVENT_USE_COND_PSHARED
2364 if (this->eventdata_
->type_
== USYNC_PROCESS
)
2366 if (ACE_OS::sema_post (&this->semaphore_
) != 0)
2371 if (ACE_OS::cond_signal (&this->eventdata_
->condition_
) != 0)
2376 #endif /* ACE_WIN32 */
2379 ACE_OS::event_destroy (ACE_event_t
*event
)
2381 #if defined (ACE_WIN32)
2382 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event
), ace_result_
), int, -1);
2383 #elif defined (ACE_HAS_THREADS)
2384 if (!event
->eventdata_
)
2390 // mutex_destroy()/cond_destroy() are called in a loop if the object
2391 // is BUSY. This avoids conditions where we fail to destroy these
2392 // objects because at time of destroy they were just being used in
2393 // another thread possibly causing deadlocks later on if they keep
2394 // being used after we're gone.
2396 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2401 # if ACE_EVENT_USE_MUTEX_PSHARED
2402 // First destroy the mutex so locking after this will return
2404 while ((r1
= ACE_OS::mutex_destroy (&event
->eventdata_
->lock_
)) == -1
2406 ACE_OS::thr_yield ();
2408 r1
= ACE_OS::sema_destroy (&event
->lock_
);
2411 # if ACE_EVENT_USE_COND_PSHARED
2412 // Now fix event to manual reset, raise signal and broadcast
2413 // until is's possible to destroy the condition.
2414 event
->eventdata_
->manual_reset_
= 1;
2415 while ((r2
= ACE_OS::cond_destroy (&event
->eventdata_
->condition_
))
2416 == -1 && errno
== EBUSY
)
2418 event
->eventdata_
->is_signaled_
= 1;
2419 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2421 ACE_OS::thr_yield ();
2424 r2
= ACE_OS::sema_destroy (&event
->semaphore_
);
2426 ACE_OS::munmap (event
->eventdata_
, sizeof (ACE_eventdata_t
));
2427 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (event
->name_
));
2428 # if defined (ACE_HAS_ALLOC_HOOKS)
2429 ACE_Allocator::instance ()->free (event
->name_
);
2431 ACE_OS::free (event
->name_
);
2432 # endif /* ACE_HAS_ALLOC_HOOKS */
2433 return r1
!= 0 || r2
!= 0 ? -1 : 0;
2435 else // !name_ (not owned by this process)
2437 ACE_OS::munmap (event
->eventdata_
, sizeof (ACE_eventdata_t
));
2439 # if !ACE_EVENT_USE_MUTEX_PSHARED
2440 ACE_OS::sema_destroy (&event
->lock_
);
2443 # if !ACE_EVENT_USE_COND_PSHARED
2444 return ACE_OS::sema_destroy (&event
->semaphore_
);
2448 else // USYNC_THREAD:
2451 // First destroy the mutex so locking after this will return errors.
2452 while ((r1
= ACE_OS::mutex_destroy (&event
->eventdata_
->lock_
)) == -1
2454 ACE_OS::thr_yield ();
2456 // Now fix event to manual reset, raise signal and broadcast until
2457 // it's possible to destroy the condition.
2458 event
->eventdata_
->manual_reset_
= 1;
2459 while ((r2
= ACE_OS::cond_destroy (&event
->eventdata_
->condition_
)) == -1
2462 event
->eventdata_
->is_signaled_
= 1;
2463 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2465 ACE_OS::thr_yield ();
2468 delete event
->eventdata_
;
2469 return r1
!= 0 || r2
!= 0 ? -1 : 0;
2474 ACE_UNUSED_ARG (event
);
2475 ACE_NOTSUP_RETURN (-1);
2476 #endif /* ACE_WIN32 */
2479 ACE_ALLOC_HOOK_DEFINE (ACE_eventdata_t
)
2483 int eventdata_init (ACE_eventdata_t
*evtdata
, int type
, int manual_reset
,
2484 int initial_state
, ACE_condattr_t
*attributes
,
2485 const char *name
, void *arg
, int init_condition
= 1,
2488 evtdata
->type_
= type
;
2489 evtdata
->manual_reset_
= manual_reset
;
2490 evtdata
->is_signaled_
= initial_state
;
2491 evtdata
->auto_event_signaled_
= false;
2492 evtdata
->waiting_threads_
= 0;
2493 evtdata
->signal_count_
= 0;
2497 const int result
= attributes
?
2498 ACE_OS::cond_init (&evtdata
->condition_
, *attributes
, name
, arg
) :
2499 ACE_OS::cond_init (&evtdata
->condition_
, (short) type
, name
, arg
);
2505 return init_mutex
? ACE_OS::mutex_init (&evtdata
->lock_
, type
, name
,
2506 (ACE_mutexattr_t
*) arg
) : 0;
2509 template <size_t N
, size_t M
>
2510 void format_name (char (&str
)[N
], const char *name
, const char (&suffix
)[M
])
2512 ACE_OS::strncpy (str
, name
, N
- M
);
2513 ACE_OS::strcat (str
, suffix
);
2516 #endif /* ACE_WIN32 */
2519 ACE_OS::event_init (ACE_event_t
*event
,
2521 ACE_condattr_t
*attributes
,
2526 LPSECURITY_ATTRIBUTES sa
)
2528 #if defined (ACE_WIN32)
2529 ACE_UNUSED_ARG (type
);
2530 ACE_UNUSED_ARG (attributes
);
2531 ACE_UNUSED_ARG (arg
);
2532 SECURITY_ATTRIBUTES sa_buffer
;
2533 SECURITY_DESCRIPTOR sd_buffer
;
2534 *event
= ::CreateEventA (ACE_OS::default_win32_security_attributes_r
2535 (sa
, &sa_buffer
, &sd_buffer
),
2540 ACE_FAIL_RETURN (-1);
2543 // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary.
2544 ACE_OS::set_errno_to_last_error ();
2547 #elif defined (ACE_HAS_THREADS)
2548 ACE_UNUSED_ARG (sa
);
2550 event
->eventdata_
= 0;
2552 if (type
== USYNC_PROCESS
)
2554 const char *name_p
= name
;
2556 // Let's see if the shared memory entity already exists.
2557 ACE_HANDLE fd
= ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p
),
2558 O_RDWR
| O_CREAT
| O_EXCL
,
2559 ACE_DEFAULT_FILE_PERMS
);
2560 if (fd
== ACE_INVALID_HANDLE
)
2562 if (errno
== EEXIST
)
2563 fd
= ACE_OS::shm_open (ACE_TEXT_CHAR_TO_TCHAR (name_p
),
2565 ACE_DEFAULT_FILE_PERMS
);
2566 if (fd
== ACE_INVALID_HANDLE
) // Still can't get it.
2571 // We own this shared memory object! Let's set its size.
2572 if (ACE_OS::ftruncate (fd
, sizeof (ACE_eventdata_t
)) == -1)
2580 void *const mapped
= ACE_OS::mmap (0, sizeof (ACE_eventdata_t
),
2581 PROT_RDWR
, MAP_SHARED
, fd
);
2582 ACE_eventdata_t
*evtdata
= reinterpret_cast<ACE_eventdata_t
*> (mapped
);
2584 if (evtdata
== MAP_FAILED
)
2587 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
2591 event
->eventdata_
= evtdata
;
2595 event
->name_
= ACE_OS::strdup (name_p
);
2596 if (event
->name_
== 0 ||
2597 eventdata_init (event
->eventdata_
, USYNC_PROCESS
, manual_reset
,
2598 initial_state
, attributes
, name
, arg
,
2599 ACE_EVENT_USE_COND_PSHARED
,
2600 ACE_EVENT_USE_MUTEX_PSHARED
) != 0)
2602 ACE_OS::munmap (evtdata
, sizeof (ACE_eventdata_t
));
2603 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
2609 # if !ACE_EVENT_USE_COND_PSHARED
2610 char sem_name
[128] = {};
2611 format_name (sem_name
, name
, "._ACE_EVTSEM_");
2612 result
= ACE_OS::sema_init (&event
->semaphore_
, 0, type
, attributes
,
2616 # if !ACE_EVENT_USE_MUTEX_PSHARED
2619 char lck_name
[128] = {};
2620 format_name (lck_name
, name
, "._ACE_EVTLCK_");
2621 result
= ACE_OS::sema_init (&event
->lock_
, owner
, type
, attributes
,
2626 # if !ACE_EVENT_USE_COND_PSHARED || !ACE_EVENT_USE_MUTEX_PSHARED
2627 if (result
!= 0 && owner
)
2628 ACE_OS::shm_unlink (ACE_TEXT_CHAR_TO_TCHAR (name_p
));
2635 ACE_NEW_RETURN (event
->eventdata_
, ACE_eventdata_t
, -1);
2636 return eventdata_init (event
->eventdata_
, USYNC_THREAD
, manual_reset
,
2637 initial_state
, attributes
, name
, arg
);
2640 ACE_UNUSED_ARG (event
);
2641 ACE_UNUSED_ARG (manual_reset
);
2642 ACE_UNUSED_ARG (initial_state
);
2643 ACE_UNUSED_ARG (type
);
2644 ACE_UNUSED_ARG (attributes
);
2645 ACE_UNUSED_ARG (name
);
2646 ACE_UNUSED_ARG (arg
);
2647 ACE_UNUSED_ARG (sa
);
2648 ACE_NOTSUP_RETURN (-1);
2649 #endif /* ACE_WIN32 */
2653 ACE_OS::event_pulse (ACE_event_t
*event
)
2655 #if defined (ACE_WIN32)
2656 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event
), ace_result_
), int, -1);
2657 #elif defined (ACE_HAS_THREADS)
2659 int result
= event
->lock ();
2663 if (event
->eventdata_
->waiting_threads_
> 0)
2665 if (event
->eventdata_
->manual_reset_
== 1)
2667 // Wakeup all waiters.
2668 # if !ACE_EVENT_USE_COND_PSHARED
2669 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2671 event
->eventdata_
->signal_count_
=
2672 event
->eventdata_
->waiting_threads_
;
2673 for (unsigned long i
= 0;
2674 i
< event
->eventdata_
->signal_count_
; ++i
)
2675 if (ACE_OS::sema_post (&event
->semaphore_
) != 0)
2677 event
->eventdata_
->signal_count_
= 0;
2683 while (event
->eventdata_
->signal_count_
!= 0 &&
2684 event
->eventdata_
->waiting_threads_
!= 0)
2685 ACE_OS::thr_yield ();
2689 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2695 event
->eventdata_
->signal_count_
=
2696 event
->eventdata_
->waiting_threads_
;
2698 else // Auto-reset event: wakeup one waiter.
2700 if (event
->wake_one () != 0)
2706 event
->eventdata_
->auto_event_signaled_
= true;
2710 event
->eventdata_
->is_signaled_
= 0;
2712 if (event
->unlock () != 0)
2720 ACE_UNUSED_ARG (event
);
2721 ACE_NOTSUP_RETURN (-1);
2722 #endif /* ACE_WIN32 */
2726 ACE_OS::event_reset (ACE_event_t
*event
)
2728 #if defined (ACE_WIN32)
2729 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event
), ace_result_
), int, -1);
2730 #elif defined (ACE_HAS_THREADS)
2731 if (event
->lock () != 0)
2734 event
->eventdata_
->is_signaled_
= 0;
2735 event
->eventdata_
->auto_event_signaled_
= false;
2737 return event
->unlock ();
2739 ACE_UNUSED_ARG (event
);
2740 ACE_NOTSUP_RETURN (-1);
2741 #endif /* ACE_WIN32 */
2745 ACE_OS::event_signal (ACE_event_t
*event
)
2747 #if defined (ACE_WIN32)
2748 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event
), ace_result_
), int, -1);
2749 #elif defined (ACE_HAS_THREADS)
2751 int result
= event
->lock ();
2756 if (event
->eventdata_
->manual_reset_
== 1)
2759 # if !ACE_EVENT_USE_COND_PSHARED
2760 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2762 if (ACE_OS::sema_post (&event
->semaphore_
) != 0)
2770 if (ACE_OS::cond_broadcast (&event
->eventdata_
->condition_
) != 0)
2777 event
->eventdata_
->is_signaled_
= 1;
2779 else // Auto-reset event
2781 if (event
->eventdata_
->waiting_threads_
== 0)
2782 event
->eventdata_
->is_signaled_
= 1;
2783 else if (event
->wake_one () != 0)
2789 event
->eventdata_
->auto_event_signaled_
= true;
2792 if (event
->unlock () != 0)
2800 ACE_UNUSED_ARG (event
);
2801 ACE_NOTSUP_RETURN (-1);
2802 #endif /* ACE_WIN32 */
2806 ACE_OS::event_timedwait (ACE_event_t
*event
,
2807 ACE_Time_Value
*timeout
,
2808 int use_absolute_time
)
2810 #if defined (ACE_WIN32)
2813 if (timeout
&& *timeout
== ACE_Time_Value::zero
)
2815 result
= ::WaitForSingleObject (*event
, 0);
2818 // Wait for upto <relative_time> number of milliseconds. Note
2819 // that we must convert between absolute time (which is passed
2820 // as a parameter) and relative time (which is what
2821 // WaitForSingleObjects() expects).
2822 // <timeout> parameter is given in absolute or relative value
2823 // depending on parameter <use_absolute_time>.
2824 int msec_timeout
= 0;
2827 msec_timeout
= INFINITE
;
2829 else if (use_absolute_time
)
2831 // Time is given in absolute time, we should use
2832 // gettimeofday() to calculate relative time
2833 ACE_Time_Value relative_time
= timeout
->to_relative_time ();
2835 // Watchout for situations where a context switch has caused
2836 // the current time to be > the timeout. Thanks to Norbert
2837 // Rapp <NRapp@nexus-informatics.de> for pointing this.
2838 if (relative_time
> ACE_Time_Value::zero
)
2839 msec_timeout
= relative_time
.msec ();
2842 // time is given in relative time, just convert it into
2843 // milliseconds and use it
2844 msec_timeout
= timeout
->msec ();
2845 result
= ::WaitForSingleObject (*event
, msec_timeout
);
2856 // This is a hack, we need to find an appropriate mapping...
2857 ACE_OS::set_errno_to_last_error ();
2860 #elif defined (ACE_HAS_THREADS)
2862 int result
= event
->lock ();
2867 if (event
->eventdata_
->is_signaled_
== 1)
2869 if (event
->eventdata_
->manual_reset_
== 0)
2871 // AUTO: reset state
2872 event
->eventdata_
->is_signaled_
= 0;
2873 event
->eventdata_
->auto_event_signaled_
= false;
2876 else // event is currently not signaled
2878 ++event
->eventdata_
->waiting_threads_
;
2880 ACE_Time_Value
*absolute_timeout
= timeout
, converted_time
;
2882 // cond_timedwait() expects absolute time, check <use_absolute_time> flag
2883 if (timeout
&& use_absolute_time
== 0)
2885 converted_time
= timeout
->to_absolute_time ();
2886 absolute_timeout
= &converted_time
;
2889 while (event
->eventdata_
->is_signaled_
== 0 &&
2890 !event
->eventdata_
->auto_event_signaled_
)
2891 # if !ACE_EVENT_USE_COND_PSHARED
2892 if (event
->eventdata_
->type_
== USYNC_PROCESS
)
2894 if (event
->unlock () != 0)
2896 --event
->eventdata_
->waiting_threads_
;
2900 if (ACE_OS::sema_wait (&event
->semaphore_
, absolute_timeout
) != 0)
2903 error
= (errno
== ETIMEDOUT
) // Semaphores use ETIMEDOUT (POSIX)
2907 bool signalled
= false;
2908 if (result
== 0 && event
->eventdata_
->signal_count_
> 0)
2910 --event
->eventdata_
->signal_count_
;
2914 if (event
->lock () != 0)
2916 --event
->eventdata_
->waiting_threads_
;
2923 if (event
->eventdata_
->manual_reset_
== 1 &&
2924 event
->eventdata_
->is_signaled_
== 1 &&
2925 ACE_OS::sema_post (&event
->semaphore_
) != 0)
2938 if (ACE_OS::cond_timedwait (&event
->eventdata_
->condition_
,
2939 &event
->eventdata_
->lock_
,
2940 absolute_timeout
) != 0)
2947 if (event
->eventdata_
->signal_count_
> 0)
2949 --event
->eventdata_
->signal_count_
;
2954 // Reset the auto_event_signaled_ to false now that we have woken up.
2955 if (event
->eventdata_
->auto_event_signaled_
)
2956 event
->eventdata_
->auto_event_signaled_
= false;
2958 --event
->eventdata_
->waiting_threads_
;
2961 if (event
->unlock () != 0)
2969 ACE_UNUSED_ARG (event
);
2970 ACE_UNUSED_ARG (timeout
);
2971 ACE_UNUSED_ARG (use_absolute_time
);
2972 ACE_NOTSUP_RETURN (-1);
2973 #endif /* ACE_WIN32 */
2976 /*****************************************************************************/
2978 /*****************************************************************************/
2981 ACE_OS::lwp_getparams (ACE_Sched_Params
&sched_params
)
2983 ACE_UNUSED_ARG (sched_params
);
2984 ACE_NOTSUP_RETURN (-1);
2988 ACE_OS::lwp_setparams (const ACE_Sched_Params
&sched_params
)
2990 ACE_UNUSED_ARG (sched_params
);
2991 ACE_NOTSUP_RETURN (-1);
2994 #if defined ACE_HAS_THREADS && defined ACE_LACKS_RWLOCK_T
2997 UniqueName (int type
, const void *addr
)
3000 if (type
== USYNC_THREAD
)
3002 this->named_
= false;
3005 this->named_
= true;
3007 ACE_UNUSED_ARG (type
);
3009 ACE_OS::unique_name (addr
, &this->buffer_
[0], ACE_UNIQUE_NAME_LEN
);
3012 operator const ACE_TCHAR
* () const
3020 return &this->buffer_
[0];
3023 ACE_TCHAR buffer_
[ACE_UNIQUE_NAME_LEN
];
3029 enum RWLockCleanup
{RWLC_CondAttr
, RWLC_Lock
, RWLC_CondReaders
, RWLC_CondWriters
};
3031 struct RWLockCleaner
{
3032 RWLockCleaner (ACE_condattr_t
&attr
, ACE_rwlock_t
*rw
)
3033 : state_ (RWLC_CondAttr
)
3040 ACE_Errno_Guard
error (errno
);
3041 switch (this->state_
)
3043 case RWLC_CondWriters
:
3044 ACE_OS::cond_destroy (&this->rw_
->waiting_writers_
);
3046 case RWLC_CondReaders
:
3047 ACE_OS::cond_destroy (&this->rw_
->waiting_readers_
);
3050 ACE_OS::mutex_destroy (&this->rw_
->lock_
);
3053 ACE_OS::condattr_destroy (this->attr_
);
3057 RWLockCleanup state_
;
3058 ACE_condattr_t
&attr_
;
3064 #if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T)
3066 ACE_OS::rwlock_init (ACE_rwlock_t
*rw
,
3071 // ACE_OS_TRACE ("ACE_OS::rwlock_init");
3072 # if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
3073 // NT, POSIX, and VxWorks don't support this natively.
3075 ACE_condattr_t attributes
;
3076 if (ACE_OS::condattr_init (attributes
, type
) != 0)
3079 RWLockCleaner
cleanup (attributes
, rw
);
3081 if (ACE_OS::mutex_init (&rw
->lock_
, type
, UniqueName (type
, &rw
->lock_
),
3082 (ACE_mutexattr_t
*) arg
) != 0)
3085 cleanup
.state_
= RWLC_Lock
;
3086 if (ACE_OS::cond_init (&rw
->waiting_readers_
, attributes
,
3087 UniqueName (type
, &rw
->waiting_readers_
), arg
) != 0)
3090 cleanup
.state_
= RWLC_CondReaders
;
3091 if (ACE_OS::cond_init (&rw
->waiting_writers_
, attributes
,
3092 UniqueName (type
, &rw
->waiting_writers_
), arg
) != 0)
3095 cleanup
.state_
= RWLC_CondWriters
;
3096 if (ACE_OS::cond_init (&rw
->waiting_important_writer_
, attributes
,
3097 UniqueName (type
, &rw
->waiting_important_writer_
),
3101 cleanup
.state_
= RWLC_CondAttr
;
3103 rw
->num_waiting_writers_
= 0;
3104 rw
->num_waiting_readers_
= 0;
3105 rw
->important_writer_
= false;
3108 ACE_UNUSED_ARG (rw
);
3109 ACE_UNUSED_ARG (type
);
3110 ACE_UNUSED_ARG (arg
);
3111 ACE_NOTSUP_RETURN (-1);
3112 # endif /* ACE_HAS_THREADS */
3114 #endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
3117 ACE_OS::sched_params (const ACE_Sched_Params
&sched_params
,
3120 ACE_OS_TRACE ("ACE_OS::sched_params");
3121 #if defined (ACE_HAS_PTHREADS) && \
3122 (!defined (ACE_LACKS_SETSCHED) || \
3123 defined (ACE_HAS_PTHREAD_SCHEDPARAM))
3124 if (sched_params
.quantum () != ACE_Time_Value::zero
)
3126 // quantums not supported
3131 // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
3132 // providing this code for 1003.1c PThreads. Please note that this
3133 // has only been tested for POSIX 1003.1c threads, and may cause
3134 // problems with other PThreads flavors!
3136 struct sched_param param
;
3137 param
.sched_priority
= sched_params
.priority ();
3139 if (sched_params
.scope () == ACE_SCOPE_PROCESS
)
3141 # if defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3142 ACE_UNUSED_ARG (id
);
3143 ACE_NOTSUP_RETURN (-1);
3144 # else /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3145 int result
= ::sched_setscheduler (id
== ACE_SELF
? 0 : id
,
3146 sched_params
.policy (),
3147 ¶m
) == -1 ? -1 : 0;
3149 # endif /* !ACE_HAS_PTHREAD_SCHEDPARAM */
3151 else if (sched_params
.scope () == ACE_SCOPE_THREAD
)
3153 ACE_thread_t thr_id
= ACE_OS::thr_self ();
3156 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id
,
3157 sched_params
.policy (),
3162 else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
3168 #elif defined (ACE_WIN32)
3169 if (sched_params
.scope () == ACE_SCOPE_THREAD
)
3171 // Setting the REALTIME_PRIORITY_CLASS on Windows is almost always
3172 // a VERY BAD THING. This include guard will allow people
3173 // to easily disable this feature in ACE.
3174 #if !defined (ACE_DISABLE_WIN32_INCREASE_PRIORITY)
3175 // Set the priority class of this process to the REALTIME process class
3176 // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL.
3177 if (!::SetPriorityClass (::GetCurrentProcess (),
3178 (sched_params
.policy () == ACE_SCHED_FIFO
||
3179 sched_params
.policy () == ACE_SCHED_RR
)
3180 ? REALTIME_PRIORITY_CLASS
3181 : NORMAL_PRIORITY_CLASS
))
3183 ACE_OS::set_errno_to_last_error ();
3186 #endif /* ACE_DISABLE_WIN32_INCREASE_PRIORITY */
3188 // Now that we have set the priority class of the process, set the
3189 // priority of the current thread to the desired value.
3190 return ACE_OS::thr_setprio (sched_params
.priority ());
3192 else if (sched_params
.scope () == ACE_SCOPE_PROCESS
)
3195 = ::OpenProcess (PROCESS_SET_INFORMATION
,
3197 id
== ACE_SELF
? ::GetCurrentProcessId() : id
);
3200 ACE_OS::set_errno_to_last_error();
3203 // There is no way for us to set the priority of the thread when we
3204 // are setting the priority of a different process. So just ignore
3205 // the priority argument when ACE_SCOPE_PROCESS is specified.
3206 // Setting the priority class will automatically increase the base
3207 // priority of all the threads within a process while maintaining the
3208 // relative priorities of the threads within it.
3209 if (!::SetPriorityClass (hProcess
,
3210 (sched_params
.policy () == ACE_SCHED_FIFO
||
3211 sched_params
.policy () == ACE_SCHED_RR
)
3212 ? REALTIME_PRIORITY_CLASS
3213 : NORMAL_PRIORITY_CLASS
))
3215 ACE_OS::set_errno_to_last_error ();
3216 ::CloseHandle (hProcess
);
3219 ::CloseHandle (hProcess
);
3227 #elif defined (ACE_VXWORKS)
3228 ACE_UNUSED_ARG (id
);
3230 // There is only one class of priorities on VxWorks, and no time
3231 // quanta. So, just set the current thread's priority.
3233 if (sched_params
.policy () != ACE_SCHED_FIFO
3234 || sched_params
.scope () != ACE_SCOPE_PROCESS
3235 || sched_params
.quantum () != ACE_Time_Value::zero
)
3241 // Set the thread priority on the current thread.
3242 return ACE_OS::thr_setprio (sched_params
.priority ());
3244 ACE_UNUSED_ARG (sched_params
);
3245 ACE_UNUSED_ARG (id
);
3246 ACE_NOTSUP_RETURN (-1);
3247 #endif /* ACE_HAS_PTHREADS */
3251 ACE_OS::scheduling_class (const char */
*class_name*/
, ACE_id_t
&/*id*/)
3253 ACE_NOTSUP_RETURN (-1);
3257 ACE_OS::set_scheduling_params (const ACE_Sched_Params
&/*sched_params*/, ACE_id_t
/*id*/)
3259 ACE_NOTSUP_RETURN (-1);
3263 ACE_OS::thr_create (ACE_THR_FUNC func
,
3266 ACE_thread_t
*thr_id
,
3267 ACE_hthread_t
*thr_handle
,
3271 ACE_Base_Thread_Adapter
*thread_adapter
,
3272 const char** thr_name
)
3274 ACE_OS_TRACE ("ACE_OS::thr_create");
3276 if (ACE_BIT_DISABLED (flags
, THR_DETACHED
) &&
3277 ACE_BIT_DISABLED (flags
, THR_JOINABLE
))
3278 ACE_SET_BITS (flags
, THR_JOINABLE
);
3280 #if defined (ACE_NO_THREAD_ADAPTER)
3281 # define ACE_THREAD_FUNCTION func
3282 # define ACE_THREAD_ARGUMENT args
3283 #else /* ! defined (ACE_NO_THREAD_ADAPTER) */
3284 # define ACE_THREAD_FUNCTION thread_args->entry_point ()
3285 # define ACE_THREAD_ARGUMENT thread_args
3286 #endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
3288 ACE_Base_Thread_Adapter
*thread_args
= 0;
3289 if (thread_adapter
== 0)
3290 #if defined (ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS)
3291 ACE_NEW_RETURN (thread_args
,
3292 ACE_OS_Thread_Adapter (func
, args
,
3293 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
,
3294 ACE_OS_Object_Manager::seh_except_selector(),
3295 ACE_OS_Object_Manager::seh_except_handler(),
3299 ACE_NEW_RETURN (thread_args
,
3300 ACE_OS_Thread_Adapter (func
, args
,
3301 (ACE_THR_C_FUNC
) ACE_THREAD_ADAPTER_NAME
,
3305 #endif /* ACE_HAS_WIN32_STRUCTURED_EXCEPTIONS */
3307 thread_args
= thread_adapter
;
3309 std::unique_ptr
<ACE_Base_Thread_Adapter
> auto_thread_args
;
3311 if (thread_adapter
== 0)
3312 auto_thread_args
.reset (thread_args
);
3314 #if defined (ACE_HAS_THREADS)
3316 // *** Set Stack Size
3317 # if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
3318 if (stacksize
< ACE_NEEDS_HUGE_THREAD_STACKSIZE
)
3319 stacksize
= ACE_NEEDS_HUGE_THREAD_STACKSIZE
;
3320 # endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
3322 ACE_thread_t tmp_thr
;
3326 ACE_hthread_t tmp_handle
;
3327 if (thr_handle
== 0)
3328 thr_handle
= &tmp_handle
;
3330 # if defined (ACE_HAS_PTHREADS)
3332 # if defined (ACE_PTHREAD_ATTR_T_INITIALIZE)
3333 /* Tests show that VxWorks 6.x pthread lib does not only
3334 * require zeroing of mutex/condition objects to function correctly
3335 * but also of the attribute objects.
3337 pthread_attr_t attr
= {0};
3339 pthread_attr_t attr
;
3341 if (ACE_ADAPT_RETVAL(::pthread_attr_init(&attr
), result
) != 0)
3346 size_t size
= stacksize
;
3348 # if defined (PTHREAD_STACK_MIN)
3349 if (size
< static_cast <size_t> (PTHREAD_STACK_MIN
))
3350 size
= PTHREAD_STACK_MIN
;
3351 # endif /* PTHREAD_STACK_MIN */
3353 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE)
3354 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3357 result
= ACE_ADAPT_RETVAL (pthread_attr_setstack (&attr
, stack
, size
), result
);
3359 result
= ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr
, size
), result
);
3362 if (ACE_ADAPT_RETVAL (pthread_attr_setstacksize (&attr
, size
), result
) == -1)
3363 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3365 ::pthread_attr_destroy (&attr
);
3369 ACE_UNUSED_ARG (size
);
3370 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKSIZE */
3373 // *** Set Stack Address
3374 # if defined (ACE_LACKS_PTHREAD_ATTR_SETSTACK)
3375 # if !defined (ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR)
3378 if (ACE_ADAPT_RETVAL(::pthread_attr_setstackaddr (&attr
, stack
), result
) != 0)
3380 ::pthread_attr_destroy (&attr
);
3385 ACE_UNUSED_ARG (stack
);
3386 # endif /* !ACE_LACKS_PTHREAD_ATTR_SETSTACKADDR */
3387 # endif /* ACE_LACKS_PTHREAD_ATTR_SETSTACK */
3389 // *** Deal with various attributes
3392 // *** Set Detach state
3393 # if !defined (ACE_LACKS_SETDETACH)
3394 if (ACE_BIT_ENABLED (flags
, THR_DETACHED
)
3395 || ACE_BIT_ENABLED (flags
, THR_JOINABLE
))
3397 int dstate
= PTHREAD_CREATE_JOINABLE
;
3399 if (ACE_BIT_ENABLED (flags
, THR_DETACHED
))
3400 dstate
= PTHREAD_CREATE_DETACHED
;
3402 if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr
, dstate
),
3405 ::pthread_attr_destroy (&attr
);
3410 // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
3411 // call ::pthread_detach () below. If THR_DETACHED is not
3412 // enabled, we call ::pthread_detach () in the Thread_Manager,
3413 // after joining with the thread.
3414 # endif /* ACE_LACKS_SETDETACH */
3417 # if !defined (ACE_LACKS_SETSCHED) || defined (ACE_HAS_PTHREAD_SCHEDPARAM)
3418 // If we wish to set the priority explicitly, we have to enable
3419 // explicit scheduling, and a policy, too.
3420 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
3422 ACE_SET_BITS (flags
, THR_EXPLICIT_SCHED
);
3423 if (ACE_BIT_DISABLED (flags
, THR_SCHED_FIFO
)
3424 && ACE_BIT_DISABLED (flags
, THR_SCHED_RR
)
3425 && ACE_BIT_DISABLED (flags
, THR_SCHED_DEFAULT
))
3426 ACE_SET_BITS (flags
, THR_SCHED_DEFAULT
);
3429 if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
)
3430 || ACE_BIT_ENABLED (flags
, THR_SCHED_RR
)
3431 || ACE_BIT_ENABLED (flags
, THR_SCHED_DEFAULT
))
3435 # if defined (ACE_HAS_ONLY_SCHED_OTHER)
3436 // SunOS, thru version 5.6, only supports SCHED_OTHER.
3437 spolicy
= SCHED_OTHER
;
3439 // Make sure to enable explicit scheduling, in case we didn't
3440 // enable it above (for non-default priority).
3441 ACE_SET_BITS (flags
, THR_EXPLICIT_SCHED
);
3443 if (ACE_BIT_ENABLED (flags
, THR_SCHED_DEFAULT
))
3444 spolicy
= SCHED_OTHER
;
3445 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
))
3446 spolicy
= SCHED_FIFO
;
3447 # if defined (SCHED_IO)
3448 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_IO
))
3451 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_IO
))
3456 # endif /* SCHED_IO */
3460 # endif /* ACE_HAS_ONLY_SCHED_OTHER */
3462 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr
, spolicy
),
3466 ::pthread_attr_destroy (&attr
);
3471 // *** Set Priority (use reasonable default priorities)
3472 # if defined(ACE_HAS_PTHREADS)
3473 // If we wish to explicitly set a scheduling policy, we also
3474 // have to specify a priority. We choose a "middle" priority as
3475 // default. Maybe this is also necessary on other POSIX'ish
3477 if ((ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
)
3478 || ACE_BIT_ENABLED (flags
, THR_SCHED_RR
)
3479 || ACE_BIT_ENABLED (flags
, THR_SCHED_DEFAULT
))
3480 && priority
== ACE_DEFAULT_THREAD_PRIORITY
)
3482 if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
))
3483 priority
= ACE_THR_PRI_FIFO_DEF
;
3484 else if (ACE_BIT_ENABLED (flags
, THR_SCHED_RR
))
3485 priority
= ACE_THR_PRI_RR_DEF
;
3486 else // THR_SCHED_DEFAULT
3487 priority
= ACE_THR_PRI_OTHER_DEF
;
3489 # endif /* ACE_HAS_PTHREADS */
3490 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
3492 struct sched_param sparam
;
3493 ACE_OS::memset ((void *) &sparam
, 0, sizeof sparam
);
3495 # if defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS)
3496 /* For MIT pthreads... */
3497 sparam
.prio
= ACE_MIN (priority
, PTHREAD_MAX_PRIORITY
);
3498 # elif defined(ACE_HAS_PTHREADS)
3499 // The following code forces priority into range.
3500 if (ACE_BIT_ENABLED (flags
, THR_SCHED_FIFO
))
3501 sparam
.sched_priority
=
3502 ACE_MIN (ACE_THR_PRI_FIFO_MAX
,
3503 ACE_MAX (ACE_THR_PRI_FIFO_MIN
, priority
));
3504 else if (ACE_BIT_ENABLED(flags
, THR_SCHED_RR
))
3505 sparam
.sched_priority
=
3506 ACE_MIN (ACE_THR_PRI_RR_MAX
,
3507 ACE_MAX (ACE_THR_PRI_RR_MIN
, priority
));
3508 else // Default policy, whether set or not
3509 sparam
.sched_priority
=
3510 ACE_MIN (ACE_THR_PRI_OTHER_MAX
,
3511 ACE_MAX (ACE_THR_PRI_OTHER_MIN
, priority
));
3512 # elif defined (PRIORITY_MAX)
3513 sparam
.sched_priority
= ACE_MIN (priority
,
3514 (long) PRIORITY_MAX
);
3516 sparam
.sched_priority
= priority
;
3517 # endif /* PTHREAD_MAX_PRIORITY */
3520 (void) ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr
, &sparam
),
3524 ::pthread_attr_destroy (&attr
);
3530 # if !defined (ACE_LACKS_SETINHERITSCHED)
3531 // *** Set scheduling explicit or inherited
3532 if (ACE_BIT_ENABLED (flags
, THR_INHERIT_SCHED
)
3533 || ACE_BIT_ENABLED (flags
, THR_EXPLICIT_SCHED
))
3535 int sched
= PTHREAD_EXPLICIT_SCHED
;
3536 if (ACE_BIT_ENABLED (flags
, THR_INHERIT_SCHED
))
3537 sched
= PTHREAD_INHERIT_SCHED
;
3538 if (ACE_ADAPT_RETVAL(::pthread_attr_setinheritsched (&attr
, sched
), result
) != 0)
3540 ::pthread_attr_destroy (&attr
);
3544 # endif /* ACE_LACKS_SETINHERITSCHED */
3545 # else /* ACE_LACKS_SETSCHED */
3546 ACE_UNUSED_ARG (priority
);
3547 # endif /* ACE_LACKS_SETSCHED */
3549 // *** Set pthread name
3550 # if defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3551 if (thr_name
&& *thr_name
)
3553 if (ACE_ADAPT_RETVAL(::pthread_attr_setname (&attr
, const_cast<char*>(*thr_name
)), result
) != 0)
3555 ::pthread_attr_destroy (&attr
);
3559 # endif /* ACE_HAS_PTHREAD_ATTR_SETNAME */
3562 # if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
3563 if (ACE_BIT_ENABLED (flags
, THR_SCOPE_SYSTEM
)
3564 || ACE_BIT_ENABLED (flags
, THR_SCOPE_PROCESS
))
3566 # if defined (ACE_LACKS_PTHREAD_SCOPE_PROCESS)
3567 int scope
= PTHREAD_SCOPE_SYSTEM
;
3568 # else /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3569 int scope
= PTHREAD_SCOPE_PROCESS
;
3570 # endif /* ACE_LACKS_PTHREAD_SCOPE_PROCESS */
3571 if (ACE_BIT_ENABLED (flags
, THR_SCOPE_SYSTEM
))
3572 scope
= PTHREAD_SCOPE_SYSTEM
;
3574 if (ACE_ADAPT_RETVAL(::pthread_attr_setscope (&attr
, scope
), result
) != 0)
3576 ::pthread_attr_destroy (&attr
);
3580 # endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
3582 # ifdef ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP
3583 if (ACE_BIT_ENABLED (flags
, THR_SUSPENDED
))
3585 if (ACE_ADAPT_RETVAL(::pthread_attr_setcreatesuspend_np(&attr
), result
) != 0)
3587 ::pthread_attr_destroy (&attr
);
3591 # endif /* !ACE_HAS_PTHREAD_ATTR_SETCREATESUSPEND_NP */
3593 if (ACE_BIT_ENABLED (flags
, THR_NEW_LWP
))
3595 // Increment the number of LWPs by one to emulate the
3597 int lwps
= ACE_OS::thr_getconcurrency ();
3600 if (errno
== ENOTSUP
)
3601 // Suppress the ENOTSUP because it's harmless.
3604 // This should never happen on SunOS:
3605 // ::thr_getconcurrency () should always succeed.
3608 else if (ACE_OS::thr_setconcurrency (lwps
+ 1) == -1)
3610 if (errno
== ENOTSUP
)
3612 // Unlikely: ::thr_getconcurrency () is supported
3613 // but ::thr_setconcurrency () is not?
3621 ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id
,
3623 thread_args
->entry_point (),
3627 ::pthread_attr_destroy (&attr
);
3629 // This is a SunOS or POSIX implementation of pthreads, where we
3630 // assume that ACE_thread_t and ACE_hthread_t are the same. If this
3631 // *isn't* correct on some platform, please let us know.
3633 *thr_handle
= *thr_id
;
3635 auto_thread_args
.release ();
3637 // *** Set pthread name (second try)
3638 # if !defined (ACE_HAS_PTHREAD_ATTR_SETNAME)
3639 # if defined (ACE_HAS_PTHREAD_SETNAME_NP)
3640 if (thr_name
&& *thr_name
)
3642 ACE_OSCALL (ACE_ADAPT_RETVAL(::pthread_setname_np (*thr_id
, *thr_name
),
3648 ACE_UNUSED_ARG (thr_name
);
3649 # endif /* ACE_HAS_PTHREAD_SETNAME_NP */
3650 # endif /* !ACE_HAS_PTHREAD_ATTR_SETNAME */
3653 # elif defined (ACE_HAS_WTHREADS)
3654 ACE_UNUSED_ARG (thr_name
);
3655 ACE_UNUSED_ARG (stack
);
3656 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
3657 if (ACE_BIT_ENABLED (flags
, THR_USE_AFX
))
3659 CWinThread
*cwin_thread
=
3660 ::AfxBeginThread ((AFX_THREADPROC
) thread_args
->entry_point (),
3664 flags
| THR_SUSPENDED
);
3665 // Have to duplicate the handle because
3666 // CWinThread::~CWinThread() closes the original handle.
3667 (void) ::DuplicateHandle (::GetCurrentProcess (),
3668 cwin_thread
->m_hThread
,
3669 ::GetCurrentProcess (),
3673 DUPLICATE_SAME_ACCESS
);
3674 *thr_id
= cwin_thread
->m_nThreadID
;
3676 if (ACE_BIT_ENABLED (flags
, THR_SUSPENDED
) == 0)
3677 cwin_thread
->ResumeThread ();
3678 // cwin_thread will be deleted in AfxThreadExit()
3679 // Warning: If AfxThreadExit() is called from within the
3680 // thread, ACE_TSS_Cleanup->thread_exit() never gets called !
3683 # endif /* ACE_HAS_MFC */
3685 int const start_suspended
= ACE_BIT_ENABLED (flags
, THR_SUSPENDED
);
3687 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
)
3688 // If we need to set the priority, then we need to start the
3689 // thread in a suspended mode.
3690 ACE_SET_BITS (flags
, THR_SUSPENDED
);
3692 *thr_handle
= (void *) ACE_BEGINTHREADEX (0,
3693 static_cast <u_int
> (stacksize
),
3694 thread_args
->entry_point (),
3699 if (priority
!= ACE_DEFAULT_THREAD_PRIORITY
&& *thr_handle
!= 0)
3701 // Set the priority of the new thread and then let it
3702 // continue, but only if the user didn't start it suspended
3703 // in the first place!
3704 if (ACE_OS::thr_setprio (*thr_handle
, priority
) != 0)
3709 if (start_suspended
== 0)
3711 ACE_OS::thr_continue (*thr_handle
);
3716 // Close down the handle if no one wants to use it.
3717 if (thr_handle
== &tmp_handle
&& tmp_handle
!= 0)
3718 ::CloseHandle (tmp_handle
);
3720 if (*thr_handle
!= 0)
3722 auto_thread_args
.release ();
3726 ACE_FAIL_RETURN (-1);
3729 # elif defined (ACE_VXWORKS)
3730 // The hard-coded values below are what ::sp () would use. (::sp ()
3731 // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
3732 // 20,000.) stacksize should be an even integer. If a stack is not
3733 // specified, ::taskSpawn () is used so that we can set the
3734 // priority, flags, and stacksize. If a stack is specified,
3735 // ::taskInit ()/::taskActivate() are used.
3737 // If called with thr_create() defaults, use same default values as ::sp ():
3738 if (priority
== ACE_DEFAULT_THREAD_PRIORITY
) priority
= 100;
3739 // Assumes that there is a floating point coprocessor. As noted
3740 // above, ::sp () hardcodes this, so we should be safe with it.
3741 if (flags
== 0) flags
= VX_FP_TASK
;
3742 if (stacksize
== 0) stacksize
= 20000;
3745 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
3749 ACE_UNUSED_ARG (stack
);
3751 // The call below to ::taskSpawn () causes VxWorks to assign a
3752 // unique task name of the form: "t" + an integer, because the
3753 // first argument is 0.
3754 tid
= ::taskSpawn (thr_name
&& *thr_name
? const_cast <char*> (*thr_name
) : 0,
3758 thread_args
->entry_point (),
3759 (ACE_VX_USR_ARG_T
) thread_args
,
3760 0, 0, 0, 0, 0, 0, 0, 0, 0);
3761 # if 0 /* Don't support setting of stack, because it doesn't seem to work. */
3765 // If a task name (thr_id) was not supplied, then the task will
3766 // not have a unique name. That's VxWorks' behavior.
3768 // Carve out a TCB at the beginning of the stack space. The TCB
3769 // occupies 400 bytes with VxWorks 5.3.1/I386.
3770 WIND_TCB
*tcb
= (WIND_TCB
*) stack
;
3772 // The TID is defined to be the address of the TCB.
3773 int status
= ::taskInit (tcb
,
3774 thr_name
&& *thr_name
? const_cast <char*>(*thr_name
) : 0,
3777 (char *) stack
+ sizeof (WIND_TCB
),
3778 (int) (stacksize
- sizeof (WIND_TCB
)),
3779 thread_args
->entry_point (),
3781 0, 0, 0, 0, 0, 0, 0, 0, 0);
3785 // The task was successfully initialized, now activate it.
3786 status
= ::taskActivate ((ACE_hthread_t
) tcb
);
3789 tid
= status
== OK
? (ACE_thread_t
) tcb
: ERROR
;
3793 if (tid
== ACE_VX_TASK_ID_ERROR
)
3803 if (thr_name
&& !(*thr_name
))
3804 *thr_name
= ::taskName (tid
);
3806 auto_thread_args
.release ();
3810 # endif /* ACE_HAS_PTHREADS */
3812 ACE_UNUSED_ARG (func
);
3813 ACE_UNUSED_ARG (args
);
3814 ACE_UNUSED_ARG (flags
);
3815 ACE_UNUSED_ARG (thr_id
);
3816 ACE_UNUSED_ARG (thr_handle
);
3817 ACE_UNUSED_ARG (priority
);
3818 ACE_UNUSED_ARG (stack
);
3819 ACE_UNUSED_ARG (stacksize
);
3820 ACE_UNUSED_ARG (thr_name
);
3821 ACE_NOTSUP_RETURN (-1);
3822 #endif /* ACE_HAS_THREADS */
3826 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status
)
3828 ACE_OS_TRACE ("ACE_OS::thr_exit");
3829 #if defined (ACE_HAS_THREADS)
3830 # if defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_PTHREAD_EXIT)
3831 ::pthread_exit (status
);
3832 # elif defined (ACE_HAS_WTHREADS)
3833 // Can't call it here because on NT, the thread is exited
3834 // directly by ACE_Thread_Adapter::invoke ().
3835 // ACE_TSS_Cleanup::instance ()->thread_exit (status);
3837 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
3839 // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
3840 // But without #including ace/Thread_Manager.h, we don't know that.
3841 ACE_OS_Thread_Descriptor
*td
=
3842 ACE_Base_Thread_Adapter::thr_desc_log_msg ();
3844 using_afx
= ACE_BIT_ENABLED (td
->flags (), THR_USE_AFX
);
3845 # endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
3847 // Call TSS destructors.
3848 ACE_OS::cleanup_tss (0 /* not main thread */);
3851 // Allow CWinThread-destructor to be invoked from AfxEndThread.
3852 // _endthreadex will be called from AfxEndThread so don't exit the
3853 // thread now if we are running an MFC thread.
3854 # if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
3855 if (using_afx
!= -1)
3858 ::AfxEndThread (status
);
3860 ACE_ENDTHREADEX (status
);
3864 // Not spawned by ACE_Thread_Manager, use the old buggy
3865 // version. You should seriously consider using
3866 // ACE_Thread_Manager to spawn threads. The following code is
3867 // know to cause some problem.
3868 CWinThread
*pThread
= ::AfxGetThread ();
3869 if (!pThread
|| pThread
->m_nThreadID
!= ACE_OS::thr_self ())
3870 ACE_ENDTHREADEX (status
);
3872 ::AfxEndThread (status
);
3875 ACE_ENDTHREADEX (status
);
3876 # endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
3878 # elif defined (ACE_HAS_VXTHREADS)
3879 ACE_UNUSED_ARG (status
);
3880 ::taskDelete (ACE_OS::thr_self ());
3882 ACE_UNUSED_ARG (status
);
3883 # endif /* ACE_HAS_PTHREADS */
3885 ACE_UNUSED_ARG (status
);
3886 #endif /* ACE_HAS_THREADS */
3889 #if defined (ACE_HAS_VXTHREADS)
3890 // Leave this in the global scope to allow
3891 // users to adjust the delay value.
3892 int ACE_THR_JOIN_DELAY
= 5;
3895 ACE_OS::thr_join (ACE_hthread_t thr_handle
,
3896 ACE_THR_FUNC_RETURN
*status
)
3898 // We can't get the status of the thread
3904 // This method can not support joining all threads
3905 if (ACE_OS::thr_cmp (thr_handle
, ACE_OS::NULL_hthread
))
3907 ACE_NOTSUP_RETURN (-1);
3911 ACE_thread_t current
= ACE_OS::thr_self ();
3913 // Make sure we are not joining ourself
3914 if (ACE_OS::thr_cmp (thr_handle
, current
))
3920 // Whether the task exists or not
3921 // we will return a successful value
3924 // Verify that the task id still exists
3925 while (taskIdVerify (thr_handle
) == OK
)
3927 // Wait a bit to see if the task is still active.
3928 ACE_OS::sleep (ACE_THR_JOIN_DELAY
);
3932 // Adapt the return value into errno and return value.
3933 // The ACE_ADAPT_RETVAL macro doesn't exactly do what
3934 // we need to do here, so we do it manually.
3945 ACE_OS::thr_join (ACE_thread_t waiter_id
,
3946 ACE_thread_t
*thr_id
,
3947 ACE_THR_FUNC_RETURN
*status
)
3950 return ACE_OS::thr_join (waiter_id
, status
);
3952 #endif /* ACE_HAS_VXTHREADS */
3955 ACE_OS::thr_key_detach (ACE_thread_key_t key
)
3957 #if defined (ACE_HAS_WTHREADS) || defined (ACE_HAS_TSS_EMULATION)
3958 TSS_Cleanup_Instance cleanup
;
3959 if (cleanup
.valid ())
3961 return cleanup
->thread_detach_key (key
);
3968 ACE_UNUSED_ARG (key
);
3969 ACE_NOTSUP_RETURN (-1);
3970 #endif /* ACE_HAS_WTHREADS || ACE_HAS_TSS_EMULATION */
3974 ACE_OS::thr_get_affinity (ACE_hthread_t thr_id
,
3975 size_t cpu_set_size
,
3976 cpu_set_t
* cpu_mask
)
3978 #if defined (ACE_HAS_PTHREAD_GETAFFINITY_NP)
3979 // Handle of the thread, which is NPTL thread-id, normally a big number
3980 if (::pthread_getaffinity_np (thr_id
, cpu_set_size
, cpu_mask
) != 0)
3985 #elif defined (ACE_HAS_2_PARAM_SCHED_GETAFFINITY)
3986 // The process-id is expected as <thr_id>, which can be a thread-id of
3987 // linux-thread, thus making binding to cpu of that particular thread only.
3988 // If you are using this flag for NPTL-threads, however, please pass as a
3989 // thr_id process id obtained by ACE_OS::getpid ()
3990 ACE_UNUSED_ARG (cpu_set_size
);
3991 if (::sched_getaffinity(thr_id
, cpu_mask
) == -1)
3996 #elif defined (ACE_HAS_SCHED_GETAFFINITY)
3997 // The process-id is expected as <thr_id>, which can be a thread-id of
3998 // linux-thread, thus making binding to cpu of that particular thread only.
3999 // If you are using this flag for NPTL-threads, however, please pass as a
4000 // thr_id process id obtained by ACE_OS::getpid ()
4001 if (::sched_getaffinity(thr_id
, cpu_set_size
, cpu_mask
) == -1)
4006 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4007 ACE_UNUSED_ARG (cpu_set_size
);
4009 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id
, *cpu_mask
), result
) == -1)
4015 ACE_UNUSED_ARG (thr_id
);
4016 ACE_UNUSED_ARG (cpu_set_size
);
4017 ACE_UNUSED_ARG (cpu_mask
);
4018 ACE_NOTSUP_RETURN (-1);
4023 ACE_OS::thr_set_affinity (ACE_hthread_t thr_id
,
4024 size_t cpu_set_size
,
4025 const cpu_set_t
* cpu_mask
)
4027 #if defined (ACE_HAS_PTHREAD_SETAFFINITY_NP)
4028 if (::pthread_setaffinity_np (thr_id
, cpu_set_size
, cpu_mask
) != 0)
4033 #elif defined (ACE_HAS_2_PARAM_SCHED_SETAFFINITY)
4034 // The process-id is expected as <thr_id>, which can be a thread-id of
4035 // linux-thread, thus making binding to cpu of that particular thread only.
4036 // If you are using this flag for NPTL-threads, however, please pass as a
4037 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4039 ACE_UNUSED_ARG (cpu_set_size
);
4040 if (::sched_setaffinity (thr_id
, cpu_mask
) == -1)
4045 #elif defined (ACE_HAS_SCHED_SETAFFINITY)
4046 // The process-id is expected as <thr_id>, which can be a thread-id of
4047 // linux-thread, thus making binding to cpu of that particular thread only.
4048 // If you are using this flag for NPTL-threads, however, please pass as a
4049 // thr_id process id obtained by ACE_OS::getpid (), but whole process will bind your CPUs
4051 if (::sched_setaffinity (thr_id
, cpu_set_size
, cpu_mask
) == -1)
4056 #elif defined (ACE_HAS_TASKCPUAFFINITYSET)
4057 ACE_UNUSED_ARG (cpu_set_size
);
4059 if (ACE_ADAPT_RETVAL (::taskCpuAffinitySet (thr_id
, *cpu_mask
), result
) == -1)
4065 ACE_UNUSED_ARG (thr_id
);
4066 ACE_UNUSED_ARG (cpu_set_size
);
4067 ACE_UNUSED_ARG (cpu_mask
);
4068 ACE_NOTSUP_RETURN (-1);
4073 ACE_OS::thr_key_used (ACE_thread_key_t key
)
4075 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION)
4076 TSS_Cleanup_Instance cleanup
;
4077 if (cleanup
.valid ())
4079 cleanup
->thread_use_key (key
);
4084 ACE_UNUSED_ARG (key
);
4085 ACE_NOTSUP_RETURN (-1);
4086 #endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
4089 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4091 ACE_OS::thr_keycreate_native (ACE_OS_thread_key_t
*key
,
4092 # if defined (ACE_HAS_THR_C_DEST)
4096 # endif /* ACE_HAS_THR_C_DEST */
4099 // can't trace here. Trace uses TSS
4100 // ACE_OS_TRACE ("ACE_OS::thr_keycreate_native");
4101 # if defined (ACE_HAS_THREADS)
4102 # if defined (ACE_HAS_PTHREADS)
4104 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key
, dest
),
4107 # elif defined (ACE_HAS_WTHREADS)
4108 ACE_UNUSED_ARG (dest
);
4109 *key
= ::TlsAlloc ();
4111 if (*key
== ACE_SYSCALL_FAILED
)
4112 ACE_FAIL_RETURN (-1);
4114 # endif /* ACE_HAS_PTHREADS */
4116 ACE_UNUSED_ARG (key
);
4117 ACE_UNUSED_ARG (dest
);
4118 ACE_NOTSUP_RETURN (-1);
4119 # endif /* ACE_HAS_THREADS */
4121 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4124 ACE_OS::thr_keycreate (ACE_thread_key_t
*key
,
4125 # if defined (ACE_HAS_THR_C_DEST)
4126 ACE_THR_C_DEST dest
)
4129 # endif /* ACE_HAS_THR_C_DEST */
4131 // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
4132 #if defined (ACE_HAS_THREADS)
4133 # if defined (ACE_HAS_TSS_EMULATION)
4134 if (ACE_TSS_Emulation::next_key (*key
) == 0)
4136 ACE_TSS_Emulation::tss_destructor (*key
, dest
);
4138 // Extract out the thread-specific table instance and stash away
4139 // the key and destructor so that we can free it up later on...
4140 TSS_Cleanup_Instance
cleanup (TSS_Cleanup_Instance::CREATE
);
4141 if (cleanup
.valid ())
4143 return cleanup
->insert (*key
, dest
);
4152 # elif defined (ACE_HAS_WTHREADS)
4153 if (ACE_OS::thr_keycreate_native (key
, dest
) == 0)
4155 // Extract out the thread-specific table instance and stash away
4156 // the key and destructor so that we can free it up later on...
4157 TSS_Cleanup_Instance
cleanup (TSS_Cleanup_Instance::CREATE
);
4158 if (cleanup
.valid ())
4160 return cleanup
->insert (*key
, dest
);
4170 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4171 return ACE_OS::thr_keycreate_native (key
, dest
);
4173 ACE_UNUSED_ARG (key
);
4174 ACE_UNUSED_ARG (dest
);
4175 ACE_NOTSUP_RETURN (-1);
4176 # endif /* ACE_HAS_TSS_EMULATION */
4177 # else /* ACE_HAS_THREADS */
4178 ACE_UNUSED_ARG (key
);
4179 ACE_UNUSED_ARG (dest
);
4180 ACE_NOTSUP_RETURN (-1);
4181 # endif /* ACE_HAS_THREADS */
4184 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4186 ACE_OS::thr_keyfree_native (ACE_OS_thread_key_t key
)
4188 ACE_OS_TRACE ("ACE_OS::thr_keyfree_native");
4189 # if defined (ACE_HAS_THREADS)
4190 # if defined (ACE_HAS_BROKEN_THREAD_KEYFREE) || defined (ACE_HAS_THR_KEYDELETE)
4191 // For some systems, e.g. LynxOS, we need to ensure that
4192 // any registered thread destructor action for this slot
4193 // is now disabled. Otherwise in the event of a dynamic library
4194 // unload of libACE, by a program not linked with libACE,
4195 // ACE_TSS_cleanup will be invoked again at the thread exit
4196 // after libACE has been actually been unmapped from memory.
4197 (void) ACE_OS::thr_setspecific_native (key
, 0);
4198 # endif /* ACE_HAS_BROKEN_THREAD_KEYFREE */
4199 # if defined (ACE_HAS_PTHREADS)
4200 # if defined (ACE_LACKS_PTHREAD_KEY_DELETE)
4201 ACE_UNUSED_ARG (key
);
4202 ACE_NOTSUP_RETURN (-1);
4204 return ::pthread_key_delete (key
);
4205 # endif /* ACE_LACKS_PTHREAD_KEY_DELETE */
4206 # elif defined (ACE_HAS_THR_KEYDELETE)
4207 return ::thr_keydelete (key
);
4208 # elif defined (ACE_HAS_WTHREADS)
4209 ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key
), ace_result_
), int, -1);
4211 ACE_UNUSED_ARG (key
);
4212 ACE_NOTSUP_RETURN (-1);
4213 # endif /* ACE_HAS_PTHREADS */
4215 ACE_UNUSED_ARG (key
);
4216 ACE_NOTSUP_RETURN (-1);
4217 # endif /* ACE_HAS_THREADS */
4219 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4222 ACE_OS::thr_keyfree (ACE_thread_key_t key
)
4224 ACE_OS_TRACE ("ACE_OS::thr_keyfree");
4225 # if defined (ACE_HAS_THREADS)
4226 # if defined (ACE_HAS_TSS_EMULATION)
4227 // Release the key in the TSS_Emulation administration
4228 ACE_TSS_Emulation::release_key (key
);
4229 TSS_Cleanup_Instance cleanup
;
4230 if (cleanup
.valid ())
4232 return cleanup
->free_key (key
);
4235 # elif defined (ACE_HAS_WTHREADS)
4236 // Extract out the thread-specific table instance and free up
4237 // the key and destructor.
4238 TSS_Cleanup_Instance cleanup
;
4239 if (cleanup
.valid ())
4241 return cleanup
->free_key (key
);
4244 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4245 return ACE_OS::thr_keyfree_native (key
);
4247 ACE_UNUSED_ARG (key
);
4248 ACE_NOTSUP_RETURN (-1);
4249 # endif /* ACE_HAS_TSS_EMULATION */
4250 # else /* ACE_HAS_THREADS */
4251 ACE_UNUSED_ARG (key
);
4252 ACE_NOTSUP_RETURN (-1);
4254 # endif /* ACE_HAS_THREADS */
4258 ACE_OS::thr_setprio (const ACE_Sched_Priority prio
)
4260 // Set the thread priority on the current thread.
4261 ACE_hthread_t my_thread_id
;
4262 ACE_OS::thr_self (my_thread_id
);
4264 return ACE_OS::thr_setprio (my_thread_id
, prio
);
4267 # if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4269 ACE_OS::thr_setspecific_native (ACE_OS_thread_key_t key
, void *data
)
4271 // ACE_OS_TRACE ("ACE_OS::thr_setspecific_native");
4272 # if defined (ACE_HAS_THREADS)
4273 # if defined (ACE_HAS_PTHREADS)
4275 ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_setspecific (key
, data
),
4278 # elif defined (ACE_HAS_WTHREADS)
4279 ::TlsSetValue (key
, data
);
4281 # else /* ACE_HAS_PTHREADS */
4282 ACE_UNUSED_ARG (key
);
4283 ACE_UNUSED_ARG (data
);
4284 ACE_NOTSUP_RETURN (-1);
4285 # endif /* ACE_HAS_PTHREADS */
4287 ACE_UNUSED_ARG (key
);
4288 ACE_UNUSED_ARG (data
);
4289 ACE_NOTSUP_RETURN (-1);
4290 # endif /* ACE_HAS_THREADS */
4292 # endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
4295 ACE_OS::thr_setspecific (ACE_thread_key_t key
, void *data
)
4297 // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
4298 #if defined (ACE_HAS_THREADS)
4299 # if defined (ACE_HAS_TSS_EMULATION)
4300 if (ACE_TSS_Emulation::is_key (key
) == 0)
4308 ACE_TSS_Emulation::ts_object (key
) = data
;
4309 TSS_Cleanup_Instance cleanup
;
4310 if (cleanup
.valid ())
4312 cleanup
->thread_use_key (key
);
4313 // for TSS_Cleanup purposes treat stetting data to zero
4314 // like detaching. This is a consequence of POSIX allowing
4315 // deletion of a "used" key.
4318 cleanup
->thread_detach_key (key
);
4327 # elif defined (ACE_HAS_WTHREADS)
4328 if (ACE_OS::thr_setspecific_native (key
, data
) == 0)
4330 TSS_Cleanup_Instance cleanup
;
4331 if (cleanup
.valid ())
4333 cleanup
->thread_use_key (key
);
4334 // for TSS_Cleanup purposes treat stetting data to zero
4335 // like detaching. This is a consequence of POSIX allowing
4336 // deletion of a "used" key.
4339 cleanup
->thread_detach_key (key
);
4346 # elif defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
4347 return ACE_OS::thr_setspecific_native (key
, data
);
4348 # else /* ACE_HAS_TSS_EMULATION */
4349 ACE_UNUSED_ARG (key
);
4350 ACE_UNUSED_ARG (data
);
4351 ACE_NOTSUP_RETURN (-1);
4352 # endif /* ACE_HAS_TSS_EMULATION */
4353 # else /* ACE_HAS_THREADS */
4354 ACE_UNUSED_ARG (key
);
4355 ACE_UNUSED_ARG (data
);
4356 ACE_NOTSUP_RETURN (-1);
4357 # endif /* ACE_HAS_THREADS */
4361 ACE_OS::unique_name (const void *object
,
4365 // The process ID will provide uniqueness between processes on the
4366 // same machine. The "this" pointer of the <object> will provide
4367 // uniqueness between other "live" objects in the same process. The
4368 // uniqueness of this name is therefore only valid for the life of
4370 ACE_OS::snprintf (name
, length
, "%p%d", object
,
4371 static_cast<int> (ACE_OS::getpid ()));
4374 #if defined (ACE_USES_WCHAR)
4376 ACE_OS::unique_name (const void *object
,
4380 // The process ID will provide uniqueness between processes on the
4381 // same machine. The "this" pointer of the <object> will provide
4382 // uniqueness between other "live" objects in the same process. The
4383 // uniqueness of this name is therefore only valid for the life of
4385 ACE_OS::snprintf (name
, length
, ACE_TEXT ("%p%d"), object
,
4386 static_cast<int> (ACE_OS::getpid ()));
4390 ACE_END_VERSIONED_NAMESPACE_DECL
4392 #if defined (ACE_VXWORKS) && !defined (__RTP__)
4393 # include /**/ <usrLib.h> /* for ::sp() */
4394 # include /**/ <sysLib.h> /* for ::sysClkRateGet() */
4395 # include "ace/Service_Config.h"
4397 #if !defined (ACE_LACKS_VA_FUNCTIONS)
4399 // This global function can be used from the VxWorks shell to pass
4400 // arguments to a C main () function.
4402 // usage: -> spa main, "arg1", "arg2"
4404 // All arguments must be quoted, even numbers.
4406 spa (FUNCPTR entry
, ...)
4408 // The called entrypoint can get the function name plus the normal 10
4409 // optional arguments.
4410 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 1 + 10;
4411 static char *argv
[ACE_MAX_ARGS
] = { 0 };
4413 ACE_VX_USR_ARG_T argc
;
4415 // Hardcode a program name because the real one isn't available
4416 // through the VxWorks shell.
4417 argv
[0] = const_cast<char*> ("ace_main");
4419 // Peel off arguments to spa () and put into argv. va_arg () isn't
4420 // necessarily supposed to return 0 when done, though since the
4421 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4422 // the unused ones. This function could be used to increase that
4423 // limit, but then it couldn't depend on the trailing 0. So, the
4424 // number of arguments would have to be passed.
4425 va_start (pvar
, entry
);
4427 for (argc
= 1; argc
< ACE_MAX_ARGS
; ++argc
)
4429 argv
[argc
] = va_arg (pvar
, char *);
4431 if (argv
[argc
] == 0)
4435 if (argc
>= ACE_MAX_ARGS
&& argv
[ACE_MAX_ARGS
- 1] != 0)
4437 // Try to read another arg, and warn user if the limit was exceeded.
4439 // Note that the VxWorks shell arguments change from int to long when
4440 // using a 64bit compiler. Cast the argument up so that the format
4441 // specifier remains correct for either build type.
4442 if (va_arg (pvar
, char *) != 0)
4443 ACE_OS::fprintf (stderr
, "spa(): number of arguments limited to %ld\n",
4444 (long)ACE_MAX_ARGS
);
4448 // fill unused argv slots with 0 to get rid of leftovers
4449 // from previous invocations
4450 for (ACE_VX_USR_ARG_T i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
4454 // The hard-coded options are what ::sp () uses, except for the
4455 // larger stack size (instead of ::sp ()'s 20000).
4456 ACE_VX_TASK_ID
const ret
= ::taskSpawn (argv
[0], // task name
4457 100, // task priority
4458 VX_FP_TASK
, // task options
4459 ACE_NEEDS_HUGE_THREAD_STACKSIZE
, // stack size
4460 entry
, // entry point
4461 argc
, // first argument to main ()
4462 (ACE_VX_USR_ARG_T
) argv
, // second argument to main ()
4463 0, 0, 0, 0, 0, 0, 0, 0);
4466 // ::taskSpawn () returns TASK_ID_ERROR on
4468 return ret
== ACE_VX_TASK_ID_ERROR
? -1 : 0;
4470 #endif /* !ACE_LACKS_VA_FUNCTIONS */
4472 // A helper function for the extended spa functions
4474 add_to_argv (ACE_VX_USR_ARG_T
& argc
, char** argv
, int max_args
, char* string
)
4477 size_t previous
= 0;
4478 size_t length
= ACE_OS::strlen (string
);
4482 // We use <= to make sure that we get the last argument
4483 for (size_t i
= 0; i
<= length
; i
++)
4485 // Is it a double quote that hasn't been escaped?
4486 if (string
[i
] == '\"' && (i
== 0 || string
[i
- 1] != '\\'))
4491 // We have just entered a double quoted string, so
4492 // save the starting position of the contents.
4497 // We have just left a double quoted string, so
4498 // zero out the ending double quote.
4502 else if (string
[i
] == '\\') // Escape the next character
4504 // The next character is automatically skipped because
4505 // of the memmove().
4506 ACE_OS::memmove (string
+ i
, string
+ i
+ 1, length
);
4509 else if (!indouble
&&
4510 (ACE_OS::ace_isspace (string
[i
]) || string
[i
] == '\0'))
4513 if (argc
< max_args
)
4515 argv
[argc
] = string
+ previous
;
4520 ACE_OS::fprintf (stderr
, "spae(): number of arguments "
4521 "limited to %d\n", max_args
);
4524 // Skip over whitespace in between arguments
4525 for(++i
; i
< length
&& ACE_OS::ace_isspace (string
[i
]); ++i
)
4529 // Save the starting point for the next time around
4532 // Make sure we don't skip over a character due
4533 // to the above loop to skip over whitespace
4540 // This global function can be used from the VxWorks shell to pass
4541 // arguments to a C main () function.
4543 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
4545 // All arguments must be within double quotes, even numbers.
4547 spae (FUNCPTR entry
, ...)
4549 static int const WINDSH_ARGS
= 10;
4550 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 128;
4551 static char* argv
[ACE_MAX_ARGS
] = { const_cast<char*> ("ace_main"), 0 };
4553 ACE_VX_USR_ARG_T argc
= 1;
4555 // Peel off arguments to spa () and put into argv. va_arg () isn't
4556 // necessarily supposed to return 0 when done, though since the
4557 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4559 va_start (pvar
, entry
);
4562 for (char* str
= va_arg (pvar
, char*);
4563 str
!= 0 && i
< WINDSH_ARGS
; str
= va_arg (pvar
, char*), ++i
)
4565 add_to_argv(argc
, argv
, ACE_MAX_ARGS
, str
);
4568 // fill unused argv slots with 0 to get rid of leftovers
4569 // from previous invocations
4570 for (i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
4573 // The hard-coded options are what ::sp () uses, except for the
4574 // larger stack size (instead of ::sp ()'s 20000).
4575 ACE_VX_TASK_ID
const ret
= ::taskSpawn (argv
[0], // task name
4576 100, // task priority
4577 VX_FP_TASK
, // task options
4578 ACE_NEEDS_HUGE_THREAD_STACKSIZE
, // stack size
4579 entry
, // entry point
4580 argc
, // first argument to main ()
4581 (ACE_VX_USR_ARG_T
) argv
, // second argument to main ()
4582 0, 0, 0, 0, 0, 0, 0, 0);
4585 // ::taskSpawn () returns the taskID on success: return 0 instead if
4587 return ret
== ACE_VX_TASK_ID_ERROR
? -1 : 0;
4590 // This global function can be used from the VxWorks shell to pass
4591 // arguments to a C main () function. The function will be run
4592 // within the shells task.
4594 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
4596 // All arguments must be within double quotes, even numbers.
4597 // Unlike the spae function, this fuction executes the supplied
4598 // routine in the foreground, rather than spawning it in a separate
4601 spaef (FUNCPTR entry
, ...)
4603 static int const WINDSH_ARGS
= 10;
4604 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 128;
4605 static char* argv
[ACE_MAX_ARGS
] = { const_cast<char*> ("ace_main"), 0 };
4607 ACE_VX_USR_ARG_T argc
= 1;
4609 // Peel off arguments to spa () and put into argv. va_arg () isn't
4610 // necessarily supposed to return 0 when done, though since the
4611 // VxWorks shell uses a fixed number (10) of arguments, it might 0
4613 va_start (pvar
, entry
);
4616 for (char* str
= va_arg (pvar
, char*);
4617 str
!= 0 && i
< WINDSH_ARGS
; str
= va_arg (pvar
, char*), ++i
)
4619 add_to_argv(argc
, argv
, ACE_MAX_ARGS
, str
);
4622 // fill unused argv slots with 0 to get rid of leftovers
4623 // from previous invocations
4624 for (i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
4627 int const ret
= entry (argc
, argv
);
4631 // Return the return value of the invoked ace_main routine.
4635 // This global function can be used from the VxWorks shell to pass
4636 // arguments to and run a main () function (i.e. ace_main).
4638 // usage: -> vx_execae ace_main, "arg1 arg2 \"arg3 with spaces\"", [prio, [opt, [stacksz]]]
4640 // All arguments must be within double quotes, even numbers.
4641 // This routine spawns the main () function in a separate task and waits till the
4642 // task has finished.
4643 static int _vx_call_rc
= 0;
4646 _vx_call_entry(FUNCPTR entry
, int argc
, char* argv
[])
4648 ACE_Service_Config::current (ACE_Service_Config::global());
4649 _vx_call_rc
= entry (argc
, argv
);
4654 vx_execae (FUNCPTR entry
, char* arg
, int prio
, int opt
, size_t stacksz
, ...)
4656 static ACE_VX_USR_ARG_T
const ACE_MAX_ARGS
= 128;
4657 static char* argv
[ACE_MAX_ARGS
] = { const_cast<char*> ("ace_main"), 0 };
4658 ACE_VX_USR_ARG_T argc
= 1;
4660 // Peel off arguments to run_main () and put into argv.
4663 add_to_argv(argc
, argv
, ACE_MAX_ARGS
, arg
);
4666 // fill unused argv slots with 0 to get rid of leftovers
4667 // from previous invocations
4668 for (ACE_VX_USR_ARG_T i
= argc
; i
< ACE_MAX_ARGS
; ++i
)
4671 // The hard-coded options are what ::sp () uses, except for the
4672 // larger stack size (instead of ::sp ()'s 20000).
4673 ACE_VX_TASK_ID
const ret
= ::taskSpawn (argv
[0], // task name
4674 prio
==0 ? 100 : prio
, // task priority
4675 opt
==0 ? VX_FP_TASK
: opt
, // task options
4676 stacksz
==0 ? ACE_NEEDS_HUGE_THREAD_STACKSIZE
: stacksz
, // stack size
4677 (FUNCPTR
)_vx_call_entry
, // entrypoint caller
4678 (ACE_VX_USR_ARG_T
)entry
, // entry point
4679 argc
, // first argument to main ()
4680 (ACE_VX_USR_ARG_T
) argv
, // second argument to main ()
4681 0, 0, 0, 0, 0, 0, 0);
4683 if (ret
== ACE_VX_TASK_ID_ERROR
)
4686 while( ::taskIdVerify (ret
) != ERROR
)
4687 ::taskDelay (3 * ::sysClkRateGet ());
4689 // ::taskSpawn () returns TASK_ID_ERROR on failure: return _vx_call_rc instead if
4691 return ret
== ACE_VX_TASK_ID_ERROR
? 255 : _vx_call_rc
;
4694 #if defined(ACE_AS_STATIC_LIBS) && defined (ACE_VXWORKS_DEBUGGING_HELPER)
4695 /** Wind River workbench allows the user to spawn a kernel task as a
4696 "Debug Configuration". Use this function as the entrypoint so that
4697 the arguments are translated into the form that ace_main() requires.
4699 int ace_wb_exec (int arg0
, int arg1
, int arg2
, int arg3
, int arg4
,
4700 int arg5
, int arg6
, int arg7
, int arg8
, int arg9
)
4702 return spaef ((FUNCPTR
) ace_main
, arg0
, arg1
, arg2
, arg3
, arg4
,
4703 arg5
, arg6
, arg7
, arg8
, arg9
);
4705 #endif /* ACE_AS_STATIC_LIBS && ... */
4707 #endif /* ACE_VXWORKS && !__RTP__ */