diff options
Diffstat (limited to 'ace/OS_NS_Thread.cpp')
-rw-r--r-- | ace/OS_NS_Thread.cpp | 1316 |
1 files changed, 1300 insertions, 16 deletions
diff --git a/ace/OS_NS_Thread.cpp b/ace/OS_NS_Thread.cpp index 914fc7c7698..aec59096073 100644 --- a/ace/OS_NS_Thread.cpp +++ b/ace/OS_NS_Thread.cpp @@ -1259,6 +1259,10 @@ ACE_OS::cleanup_tss (const u_int main_thread) } } +/*****************************************************************************/ +// CONDITIONS BEGIN +/*****************************************************************************/ + #if defined (ACE_LACKS_COND_T) && ! defined (ACE_PSOS_DIAB_MIPS) // NOTE: The ACE_OS::cond_* functions for some non-Unix platforms are // defined here either because they're too big to be inlined, or @@ -1895,6 +1899,1302 @@ ACE_OS::cond_wait (ACE_cond_t *cv, # endif /* ACE_HAS_WTHREADS */ #endif /* ACE_LACKS_COND_T */ +/*****************************************************************************/ +// CONDITIONS END +/*****************************************************************************/ + +/*****************************************************************************/ +// MUTEXES BEGIN +/*****************************************************************************/ + +int +ACE_OS::mutex_init (ACE_mutex_t *m, + int lock_scope, + const char *name, + ACE_mutexattr_t *attributes, + LPSECURITY_ATTRIBUTES sa, + int lock_type) +{ + // ACE_OS_TRACE ("ACE_OS::mutex_init"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (sa); + + pthread_mutexattr_t l_attributes; + if (attributes == 0) + attributes = &l_attributes; + int result = 0; + int attr_init = 0; // have we initialized the local attributes. + + // Only do these initializations if the <attributes> parameter + // wasn't originally set. + if (attributes == &l_attributes) + { +# if defined (ACE_HAS_PTHREADS_DRAFT4) + if (::pthread_mutexattr_create (attributes) == 0) +# elif defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD) + if (ACE_ADAPT_RETVAL (::pthread_mutexattr_init (attributes), result) == 0) +# else /* draft 6 */ + if (::pthread_mutexattr_init (attributes) == 0) +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +{ + result = 0; + attr_init = 1; // we have initialized these attributes +} + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status + } + + if (result == 0 && lock_scope != 0) +{ +# if defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD) +# if defined (_POSIX_THREAD_PROCESS_SHARED) && !defined (ACE_LACKS_MUTEXATTR_PSHARED) + (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_setpshared (attributes, + lock_scope), + result); +# endif /* _POSIX_THREAD_PROCESS_SHARED && !ACE_LACKS_MUTEXATTR_PSHARED */ +# else /* Pthreads draft 6 */ +# if !defined (ACE_LACKS_MUTEXATTR_PSHARED) + if (::pthread_mutexattr_setpshared (attributes, lock_scope) != 0) + result = -1; +# endif /* ACE_LACKS_MUTEXATTR_PSHARED */ +# endif /* ACE_HAS_PTHREADS_DRAFT7 || ACE_HAS_PTHREADS_STD */ +} + + if (result == 0 && lock_type != 0) +{ +# if defined (ACE_HAS_PTHREADS_DRAFT4) +# if defined (ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP) + if (::pthread_mutexattr_setkind_np (attributes, lock_type) != 0) + result = -1; +# endif /* ACE_HAS_PTHREAD_MUTEXATTR_SETKIND_NP */ +# elif defined (ACE_HAS_RECURSIVE_MUTEXES) + (void) ACE_ADAPT_RETVAL (::pthread_mutexattr_settype (attributes, + lock_type), + result); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ +} + + if (result == 0) +{ +# if defined (ACE_HAS_PTHREADS_DRAFT4) + if (::pthread_mutex_init (m, *attributes) == 0) +# elif defined (ACE_HAS_PTHREADS_DRAFT7) || defined (ACE_HAS_PTHREADS_STD) + if (ACE_ADAPT_RETVAL (::pthread_mutex_init (m, attributes), result) == 0) +# else + if (::pthread_mutex_init (m, attributes) == 0) +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + result = 0; + else + result = -1; // ACE_ADAPT_RETVAL used it for intermediate status +} + + // Only do the deletions if the <attributes> parameter wasn't + // originally set. + if (attributes == &l_attributes && attr_init) +# if defined (ACE_HAS_PTHREADS_DRAFT4) + ::pthread_mutexattr_delete (&l_attributes); +# else + ::pthread_mutexattr_destroy (&l_attributes); +# endif /* ACE_HAS_PTHREADS_DRAFT4 */ + + return result; +# elif defined (ACE_HAS_STHREADS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (sa); + ACE_UNUSED_ARG (lock_type); + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_init (m, + lock_scope, + attributes), + result), + int, -1); +# elif defined (ACE_HAS_WTHREADS) + m->type_ = lock_scope; + + SECURITY_ATTRIBUTES sa_buffer; + SECURITY_DESCRIPTOR sd_buffer; + switch (lock_scope) +{ + case USYNC_PROCESS: +# if defined (ACE_HAS_WINCE) + // @@todo (brunsch) This idea should be moved into ACE_OS_Win32. + m->proc_mutex_ = + ::CreateMutexW (ACE_OS::default_win32_security_attributes_r + (sa, &sa_buffer, &sd_buffer), + FALSE, + ACE_Ascii_To_Wide (name).wchar_rep ()); +# else /* ACE_HAS_WINCE */ + m->proc_mutex_ = + ::CreateMutexA (ACE_OS::default_win32_security_attributes_r + (sa, &sa_buffer, &sd_buffer), + FALSE, + name); +# endif /* ACE_HAS_WINCE */ + if (m->proc_mutex_ == 0) + ACE_FAIL_RETURN (-1); + else + { + // Make sure to set errno to ERROR_ALREADY_EXISTS if necessary. + ACE_OS::set_errno_to_last_error (); + return 0; + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_init (&m->thr_mutex_, + lock_type, + name, + attributes); + default: + errno = EINVAL; + return -1; +} + /* NOTREACHED */ + +# elif defined (ACE_PSOS) + ACE_UNUSED_ARG (lock_scope); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); + ACE_UNUSED_ARG (lock_type); +# if defined (ACE_PSOS_HAS_MUTEX) + + u_long flags = MU_LOCAL; + u_long ceiling = 0; + +# if defined (ACE_HAS_RECURSIVE_MUTEXES) + flags |= MU_RECURSIVE; +# else /* ! ACE_HAS_RECURSIVE_MUTEXES */ + flags |= MU_NONRECURSIVE; +# endif /* ACE_HAS_RECURSIVE_MUTEXES */ + +# if defined (ACE_PSOS_HAS_PRIO_MUTEX) + + flags |= MU_PRIOR; + +# if defined (ACE_PSOS_HAS_PRIO_INHERIT_MUTEX) + flags |= MU_PRIO_INHERIT; +# elif defined (ACE_PSOS_HAS_PRIO_PROTECT_MUTEX) + ceiling = PSOS_TASK_MAX_PRIORITY; + flags |= MU_PRIO_PROTECT; +# else + flags |= MU_PRIO_NONE; +# endif /* ACE_PSOS_HAS_PRIO_INHERIT_MUTEX */ + +# else /* ! ACE_PSOS_HAS_PRIO_MUTEX */ + + flags |= MU_FIFO | MU_PRIO_NONE; + +# endif + + // Fake a pSOS name - it can be any 4-byte value, not necessarily needing + // to be ASCII. So use the mutex pointer passed in. That should identify + // each one uniquely. + union { ACE_mutex_t *p; char n[4]; } m_name; + m_name.p = m; + + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_create (m_name.n, + flags, + ceiling, + m), + result), + int, -1); + +# else /* ! ACE_PSOS_HAS_MUTEX */ + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_create ((char *) name, + 1, + SM_LOCAL | SM_PRIOR, + m), + result), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); + ACE_UNUSED_ARG (lock_type); + + return (*m = ::semMCreate (lock_scope)) == 0 ? -1 : 0; +# endif /* ACE_HAS_PTHREADS */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (lock_scope); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (attributes); + ACE_UNUSED_ARG (sa); + ACE_UNUSED_ARG (lock_type); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::mutex_destroy (ACE_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::mutex_destroy"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + ACE_OSCALL_RETURN (::pthread_mutex_destroy (m), int, -1); +# else + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_mutex_destroy (m), + result), int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6*/ +# elif defined (ACE_HAS_STHREADS) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_destroy (m), result), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) +{ + case USYNC_PROCESS: + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (m->proc_mutex_), + ace_result_), + int, -1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_destroy (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; +} + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_delete (*m), result), + int, -1); +# else /* ! ACE_PSOS_HAS_MUTEX */ + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_delete (*m), result), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + return ::semDelete (*m) == OK ? 0 : -1; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +#if defined (ACE_HAS_WCHAR) +int +ACE_OS::mutex_init (ACE_mutex_t *m, + int lock_scope, + const wchar_t *name, + ACE_mutexattr_t *attributes, + LPSECURITY_ATTRIBUTES sa, + int lock_type) +{ +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS) + m->type_ = lock_scope; + SECURITY_ATTRIBUTES sa_buffer; + SECURITY_DESCRIPTOR sd_buffer; + switch (lock_scope) + { + case USYNC_PROCESS: + m->proc_mutex_ = + ::CreateMutexW (ACE_OS::default_win32_security_attributes_r + (sa, &sa_buffer, &sd_buffer), + FALSE, + name); + if (m->proc_mutex_ == 0) + ACE_FAIL_RETURN (-1); + else + return 0; + case USYNC_THREAD: + return ACE_OS::thread_mutex_init (&m->thr_mutex_, + lock_type, + name, + attributes); + } + + errno = EINVAL; + return -1; +#else /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */ + return ACE_OS::mutex_init (m, + lock_scope, + ACE_Wide_To_Ascii (name).char_rep (), + attributes, + sa, + lock_type); +#endif /* ACE_HAS_THREADS && ACE_HAS_WTHREADS */ +} +#endif /* ACE_HAS_WCHAR */ + +int +ACE_OS::mutex_lock (ACE_mutex_t *m) +{ + // ACE_OS_TRACE ("ACE_OS::mutex_lock"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + ACE_OSCALL_RETURN (pthread_mutex_lock (m), int, -1); +# else + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_lock (m), result), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_lock (m), result), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) +{ + case USYNC_PROCESS: + switch (::WaitForSingleObject (m->proc_mutex_, INFINITE)) + { + // + // Timeout can't occur, so don't bother checking... + // + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + // We will ignore abandonments in this method + // Note that we still hold the lock + return 0; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_lock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; +} + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_lock (*m, MU_WAIT, 0), + result), + int, -1); +# else /* ACE_PSOS_HAS_MUTEX */ + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_p (*m, SM_WAIT, 0), + result), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + return ::semTake (*m, WAIT_FOREVER) == OK ? 0 : -1; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::mutex_lock (ACE_mutex_t *m, + int &abandoned) +{ + ACE_OS_TRACE ("ACE_OS::mutex_lock"); +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS) + abandoned = 0; + switch (m->type_) + { + case USYNC_PROCESS: + switch (::WaitForSingleObject (m->proc_mutex_, INFINITE)) + { + // + // Timeout can't occur, so don't bother checking... + // + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + abandoned = 1; + return 0; // something goofed, but we hold the lock ... + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_lock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (abandoned); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */ +} + +int +ACE_OS::mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value &timeout) +{ +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_MUTEX_TIMEOUTS) + +# if defined (ACE_HAS_PTHREADS) + int result; + + // "timeout" should be an absolute time. + + timespec_t ts = timeout; // Calls ACE_Time_Value::operator timespec_t(). + + // Note that the mutex should not be a recursive one, i.e., it + // should only be a standard mutex or an error checking mutex. + + ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_mutex_timedlock (m, &ts), result), int, -1, result); + + // We need to adjust this to make the errno values consistent. + if (result == -1 && errno == ETIMEDOUT) + errno = ETIME; + return result; + +# elif defined (ACE_HAS_WTHREADS) + // Note that we must convert between absolute time (which is passed + // as a parameter) and relative time (which is what the system call + // expects). + ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ()); + + switch (m->type_) + { + case USYNC_PROCESS: + switch (::WaitForSingleObject (m->proc_mutex_, + relative_time.msec ())) + { + case WAIT_OBJECT_0: + case WAIT_ABANDONED: + // We will ignore abandonments in this method + // Note that we still hold the lock + return 0; + case WAIT_TIMEOUT: + errno = ETIME; + return -1; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } + case USYNC_THREAD: + ACE_NOTSUP_RETURN (-1); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ + +# elif defined (ACE_PSOS) + + // Note that we must convert between absolute time (which is + // passed as a parameter) and relative time (which is what + // the system call expects). + ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ()); + + u_long ticks = relative_time.sec() * KC_TICKS2SEC + + relative_time.usec () * KC_TICKS2SEC / + ACE_ONE_SECOND_IN_USECS; + if (ticks == 0) + ACE_OSCALL_RETURN (::sm_p (*m, SM_NOWAIT, 0), int, -1); // no timeout + else + ACE_OSCALL_RETURN (::sm_p (*m, SM_WAIT, ticks), int, -1); + +# elif defined (VXWORKS) + + // Note that we must convert between absolute time (which is passed + // as a parameter) and relative time (which is what the system call + // expects). + ACE_Time_Value relative_time (timeout - ACE_OS::gettimeofday ()); + + int ticks_per_sec = ::sysClkRateGet (); + + int ticks = relative_time.sec() * ticks_per_sec + + relative_time.usec () * ticks_per_sec / ACE_ONE_SECOND_IN_USECS; + if (::semTake (*m, ticks) == ERROR) + { + if (errno == S_objLib_OBJ_TIMEOUT) + // Convert the VxWorks errno to one that's common for to ACE + // platforms. + errno = ETIME; + else if (errno == S_objLib_OBJ_UNAVAILABLE) + errno = EBUSY; + return -1; + } + else + return 0; +# endif /* ACE_HAS_PTHREADS */ + +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (timeout); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS && ACE_HAS_MUTEX_TIMEOUTS */ +} + +int +ACE_OS::mutex_trylock (ACE_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::mutex_trylock"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + int status = pthread_mutex_trylock (m); + if (status == 1) + status = 0; + else if (status == 0) { + status = -1; + errno = EBUSY; + } + return status; +# else + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_trylock (m), result), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_trylock (m), result), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) +{ + case USYNC_PROCESS: + { + // Try for 0 milliseconds - i.e. nonblocking. + switch (::WaitForSingleObject (m->proc_mutex_, 0)) + { + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + // We will ignore abandonments in this method. Note that + // we still hold the lock. + return 0; + case WAIT_TIMEOUT: + errno = EBUSY; + return -1; + default: + ACE_OS::set_errno_to_last_error (); + return -1; + } + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_trylock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; +} + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_lock (*m, MU_NOWAIT, 0), + result), + int, -1); +# else /* ! ACE_PSOS_HAS_MUTEX */ + switch (::sm_p (*m, SM_NOWAIT, 0)) +{ + case 0: + return 0; + case ERR_NOSEM: + errno = EBUSY; + // intentional fall through + default: + return -1; +} +# endif /* ACE_PSOS_HAS_MUTEX */ + +# elif defined (VXWORKS) + if (::semTake (*m, NO_WAIT) == ERROR) + if (errno == S_objLib_OBJ_UNAVAILABLE) +{ + // couldn't get the semaphore + errno = EBUSY; + return -1; +} + else + // error + return -1; + else + // got the semaphore + return 0; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +int +ACE_OS::mutex_trylock (ACE_mutex_t *m, int &abandoned) +{ +#if defined (ACE_HAS_THREADS) && defined (ACE_HAS_WTHREADS) + abandoned = 0; + switch (m->type_) + { + case USYNC_PROCESS: + { + // Try for 0 milliseconds - i.e. nonblocking. + switch (::WaitForSingleObject (m->proc_mutex_, 0)) + { + case WAIT_OBJECT_0: + return 0; + case WAIT_ABANDONED: + abandoned = 1; + return 0; // something goofed, but we hold the lock ... + case WAIT_TIMEOUT: + errno = EBUSY; + return -1; + default: + ACE_OS::set_errno_to_last_error (); + return -1; + } + } + case USYNC_THREAD: + return ACE_OS::thread_mutex_trylock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; + } + /* NOTREACHED */ +#else + ACE_UNUSED_ARG (m); + ACE_UNUSED_ARG (abandoned); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS and ACE_HAS_WTHREADS */ +} + +int +ACE_OS::mutex_unlock (ACE_mutex_t *m) +{ + ACE_OS_TRACE ("ACE_OS::mutex_unlock"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + // Note, don't use "::" here since the following call is often a macro. +# if (defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)) + ACE_OSCALL_RETURN (pthread_mutex_unlock (m), int, -1); +# else + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (pthread_mutex_unlock (m), result), + int, -1); +# endif /* ACE_HAS_PTHREADS_DRAFT4 || ACE_HAS_PTHREADS_DRAFT6 */ +# elif defined (ACE_HAS_STHREADS) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mutex_unlock (m), result), int, -1); +# elif defined (ACE_HAS_WTHREADS) + switch (m->type_) +{ + case USYNC_PROCESS: + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ReleaseMutex (m->proc_mutex_), + ace_result_), + int, -1); + case USYNC_THREAD: + return ACE_OS::thread_mutex_unlock (&m->thr_mutex_); + default: + errno = EINVAL; + return -1; +} + /* NOTREACHED */ +# elif defined (ACE_PSOS) +# if defined (ACE_PSOS_HAS_MUTEX) + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::mu_unlock (*m), result), + int, -1); +# else /* ! ACE_PSOS_HAS_MUTEX */ + int result; + ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sm_v (*m), result), + int, -1); +# endif /* ACE_PSOS_HAS_MUTEX */ +# elif defined (VXWORKS) + return ::semGive (*m) == OK ? 0 : -1; +# endif /* Threads variety case */ +#else + ACE_UNUSED_ARG (m); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_HAS_THREADS */ +} + +void +ACE_OS::mutex_lock_cleanup (void *mutex) +{ + ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup"); +#if defined (ACE_HAS_THREADS) +# if defined (ACE_HAS_PTHREADS) + ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex; + ACE_OS::mutex_unlock (p_lock); +# else + ACE_UNUSED_ARG (mutex); +# endif /* ACE_HAS_PTHREADS */ +#else + ACE_UNUSED_ARG (mutex); +#endif /* ACE_HAS_THREADS */ +} + +/*****************************************************************************/ +// MUTEXES END +/*****************************************************************************/ + +/*****************************************************************************/ +// EVENTS BEGIN +/*****************************************************************************/ + +int +ACE_OS::event_destroy (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::CloseHandle (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + if (event->eventdata_) +{ + // mutex_destroy()/cond_destroy() are called in a loop if the object + // is BUSY. This avoids conditions where we fail to destroy these + // objects because at time of destroy they were just being used in + // another thread possibly causing deadlocks later on if they keep + // being used after we're gone. + + if (event->eventdata_->type_ == USYNC_PROCESS) + { + if (event->name_) + { + // Only destroy the event data if we're the ones who initialized + // it. + + int r1, r2; + // first destroy the mutex so locking after this will return errors + while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1 + && errno == EBUSY) + { + ACE_OS::thr_yield (); + } + // now fix event to manual reset, raise signal and broadcast until is's + // possible to destroy the condition + event->eventdata_->manual_reset_ = 1; + while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1 + && errno == EBUSY) + { + event->eventdata_->is_signaled_ = 1; + ACE_OS::cond_broadcast (&event->eventdata_->condition_); + ACE_OS::thr_yield (); + } + ACE_OS::munmap (event->eventdata_, + sizeof (ACE_eventdata_t)); + ACE_OS::unlink (event->name_); + ACE_OS::free ( + static_cast<void *> (const_cast<ACE_TCHAR *> (event->name_))); + return r1 != 0 || r2 != 0 ? -1 : 0; + } + else + { + ACE_OS::munmap (event->eventdata_, + sizeof (ACE_eventdata_t)); + return 0; + } + } + else + { + int r1, r2; + // first destroy the mutex so locking after this will return errors + while ((r1 = ACE_OS::mutex_destroy (&event->eventdata_->lock_)) == -1 + && errno == EBUSY) + { + ACE_OS::thr_yield (); + } + // now fix event to manual reset, raise signal and broadcast until is's + // possible to destroy the condition + event->eventdata_->manual_reset_ = 1; + while ((r2 = ACE_OS::cond_destroy (&event->eventdata_->condition_)) == -1 + && errno == EBUSY) + { + event->eventdata_->is_signaled_ = 1; + ACE_OS::cond_broadcast (&event->eventdata_->condition_); + ACE_OS::thr_yield (); + } + delete event->eventdata_; + return r1 != 0 || r2 != 0 ? -1 : 0; + } +} + + return 0; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::event_init (ACE_event_t *event, + int manual_reset, + int initial_state, + int type, + const char *name, + void *arg, + LPSECURITY_ATTRIBUTES sa) +{ +#if defined (ACE_WIN32) + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (arg); + SECURITY_ATTRIBUTES sa_buffer; + SECURITY_DESCRIPTOR sd_buffer; +# if defined (ACE_HAS_WINCE) + // @@todo (brunsch) This idea should be moved into ACE_OS_Win32. + *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r + (sa, &sa_buffer, &sd_buffer), + manual_reset, + initial_state, + ACE_Ascii_To_Wide (name).wchar_rep ()); +# else /* ACE_HAS_WINCE */ + *event = ::CreateEventA (ACE_OS::default_win32_security_attributes_r + (sa, &sa_buffer, &sd_buffer), + manual_reset, + initial_state, + name); +# endif /* ACE_HAS_WINCE */ + if (*event == 0) + ACE_FAIL_RETURN (-1); + else + return 0; +#elif defined (ACE_HAS_THREADS) + ACE_UNUSED_ARG (sa); + event->eventdata_ = 0; + ACE_eventdata_t* evtdata; + + if (type == USYNC_PROCESS) + { + int owner = 0; + // Let's see if the shared memory entity already exists. + ACE_HANDLE fd = ACE_OS::shm_open (name, + O_RDWR | O_CREAT | O_EXCL, + ACE_DEFAULT_FILE_PERMS); + if (fd == ACE_INVALID_HANDLE) + { + if (errno == EEXIST) + fd = ACE_OS::shm_open (name, + O_RDWR | O_CREAT, + ACE_DEFAULT_FILE_PERMS); + else + return(-1); + } + else + { + // We own this shared memory object! Let's set its size. + if (ACE_OS::ftruncate (fd, + sizeof (ACE_eventdata_t)) == -1) + { + ACE_OS::close (fd); + return(-1); + } + owner = 1; + } + + evtdata = + (ACE_eventdata_t *) ACE_OS::mmap (0, + sizeof (ACE_eventdata_t), + PROT_RDWR, + MAP_SHARED, + fd, + 0); + ACE_OS::close (fd); + if (evtdata == MAP_FAILED) + { + if (owner) + ACE_OS::unlink (name); + return(-1); + } + + if (owner) + { + event->name_ = ACE_OS::strdup (name); + if (event->name_ == 0) + { + ACE_OS::unlink (name); + return(-1); + } + event->eventdata_ = evtdata; + event->eventdata_->type_ = type; + event->eventdata_->manual_reset_ = manual_reset; + event->eventdata_->is_signaled_ = initial_state; + event->eventdata_->auto_event_signaled_ = false; + event->eventdata_->waiting_threads_ = 0; + + int result = ACE_OS::cond_init (&event->eventdata_->condition_, + static_cast<short> (type), + name, + arg); + if (result == 0) + result = ACE_OS::mutex_init (&event->eventdata_->lock_, + type, + name, + (ACE_mutexattr_t *) arg); + + return result; + } + else + { + event->name_ = 0; + event->eventdata_ = evtdata; + } + + return(0); + } + else + { + ACE_NEW_RETURN (evtdata, + ACE_eventdata_t, + -1); + event->name_ = 0; + event->eventdata_ = evtdata; + event->eventdata_->type_ = type; + event->eventdata_->manual_reset_ = manual_reset; + event->eventdata_->is_signaled_ = initial_state; + event->eventdata_->auto_event_signaled_ = false; + event->eventdata_->waiting_threads_ = 0; + + int result = ACE_OS::cond_init (&event->eventdata_->condition_, + static_cast<short> (type), + name, + arg); + if (result == 0) + result = ACE_OS::mutex_init (&event->eventdata_->lock_, + type, + name, + (ACE_mutexattr_t *) arg); + + return result; + } +#else + ACE_UNUSED_ARG (event); + ACE_UNUSED_ARG (manual_reset); + ACE_UNUSED_ARG (initial_state); + ACE_UNUSED_ARG (type); + ACE_UNUSED_ARG (name); + ACE_UNUSED_ARG (arg); + ACE_UNUSED_ARG (sa); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::event_pulse (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::PulseEvent (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0) + { + // Manual-reset event. + if (event->eventdata_->manual_reset_ == 1) + { + // Wakeup all waiters. + if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0) + { + result = -1; + error = errno; + } + } + // Auto-reset event: wakeup one waiter. + else if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0) + { + result = -1; + error = errno; + } + + // Reset event. + event->eventdata_->is_signaled_ = 0; + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->eventdata_->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::event_reset (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::ResetEvent (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + + // Grab the lock first. + if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0) + { + // Reset event. + event->eventdata_->is_signaled_ = 0; + event->eventdata_->auto_event_signaled_ = false; + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->eventdata_->lock_); + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::event_signal (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::SetEvent (*event), ace_result_), int, -1); +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0) + { + // Manual-reset event. + if (event->eventdata_->manual_reset_ == 1) + { + // wakeup all + if (ACE_OS::cond_broadcast (&event->eventdata_->condition_) != 0) + { + result = -1; + error = errno; + } + + // signal event + event->eventdata_->is_signaled_ = 1; + } + // Auto-reset event + else + { + if (event->eventdata_->waiting_threads_ == 0) + // No waiters: signal event. + event->eventdata_->is_signaled_ = 1; + // Waiters: wakeup one waiter. + else if (ACE_OS::cond_signal (&event->eventdata_->condition_) != 0) + { + result = -1; + error = errno; + } + + event->eventdata_->auto_event_signaled_ = true; + } + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->eventdata_->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::event_timedwait (ACE_event_t *event, + ACE_Time_Value *timeout, + int use_absolute_time) +{ +#if defined (ACE_WIN32) + DWORD result; + + if (timeout == 0) + // Wait forever + result = ::WaitForSingleObject (*event, INFINITE); + else if (timeout->sec () == 0 && timeout->usec () == 0) + // Do a "poll". + result = ::WaitForSingleObject (*event, 0); + else + { + // Wait for upto <relative_time> number of milliseconds. Note + // that we must convert between absolute time (which is passed + // as a parameter) and relative time (which is what + // WaitForSingleObjects() expects). + // <timeout> parameter is given in absolute or relative value + // depending on parameter <use_absolute_time>. + int msec_timeout; + if (use_absolute_time) + { + // Time is given in absolute time, we should use + // gettimeofday() to calculate relative time + ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ()); + + // Watchout for situations where a context switch has caused + // the current time to be > the timeout. Thanks to Norbert + // Rapp <NRapp@nexus-informatics.de> for pointing this. + if (relative_time < ACE_Time_Value::zero) + msec_timeout = 0; + else + msec_timeout = relative_time.msec (); + } + else + // time is given in relative time, just convert it into + // milliseconds and use it + msec_timeout = timeout->msec (); + result = ::WaitForSingleObject (*event, msec_timeout); + } + + switch (result) + { + case WAIT_OBJECT_0: + return 0; + case WAIT_TIMEOUT: + errno = ETIME; + return -1; + default: + // This is a hack, we need to find an appropriate mapping... + ACE_OS::set_errno_to_last_error (); + return -1; + } +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0) + { + if (event->eventdata_->is_signaled_ == 1) + // event is currently signaled + { + if (event->eventdata_->manual_reset_ == 0) + { + // AUTO: reset state + event->eventdata_->is_signaled_ = 0; + event->eventdata_->auto_event_signaled_ = false; + } + } + else + // event is currently not signaled + { + event->eventdata_->waiting_threads_++; + + ACE_Time_Value absolute_timeout = *timeout; + + // cond_timewait() expects absolute time, check + // <use_absolute_time> flag. + if (use_absolute_time == 0) + absolute_timeout += ACE_OS::gettimeofday (); + + while (event->eventdata_->is_signaled_ == 0 && + event->eventdata_->auto_event_signaled_ == false) + { + if (ACE_OS::cond_timedwait (&event->eventdata_->condition_, + &event->eventdata_->lock_, + &absolute_timeout) != 0) + { + result = -1; + error = errno; + break; + } + } + + // Reset the auto_event_signaled_ to false now that we have + // woken up. + if (event->eventdata_->auto_event_signaled_ == true) + event->eventdata_->auto_event_signaled_ = false; + + event->eventdata_->waiting_threads_--; + } + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->eventdata_->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; + } + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_UNUSED_ARG (timeout); + ACE_UNUSED_ARG (use_absolute_time); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +int +ACE_OS::event_wait (ACE_event_t *event) +{ +#if defined (ACE_WIN32) + switch (::WaitForSingleObject (*event, INFINITE)) +{ + case WAIT_OBJECT_0: + return 0; + default: + ACE_OS::set_errno_to_last_error (); + return -1; +} +#elif defined (ACE_HAS_THREADS) + int result = 0; + int error = 0; + + // grab the lock first + if (ACE_OS::mutex_lock (&event->eventdata_->lock_) == 0) +{ + if (event->eventdata_->is_signaled_ == 1) + // Event is currently signaled. + { + if (event->eventdata_->manual_reset_ == 0) + // AUTO: reset state + event->eventdata_->is_signaled_ = 0; + } + else // event is currently not signaled + { + event->eventdata_->waiting_threads_++; + + while (event->eventdata_->is_signaled_ == 0 && + event->eventdata_->auto_event_signaled_ == false) + { + if (ACE_OS::cond_wait (&event->eventdata_->condition_, + &event->eventdata_->lock_) != 0) + { + result = -1; + error = errno; + // Something went wrong... + break; + } + } + + // Reset it since we have woken up. + if (event->eventdata_->auto_event_signaled_ == true) + event->eventdata_->auto_event_signaled_ = false; + + event->eventdata_->waiting_threads_--; + } + + // Now we can let go of the lock. + ACE_OS::mutex_unlock (&event->eventdata_->lock_); + + if (result == -1) + // Reset errno in case mutex_unlock() also fails... + errno = error; +} + else + result = -1; + return result; +#else + ACE_UNUSED_ARG (event); + ACE_NOTSUP_RETURN (-1); +#endif /* ACE_WIN32 */ +} + +/*****************************************************************************/ +// EVENTS END +/*****************************************************************************/ + int ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params) { @@ -1966,22 +3266,6 @@ ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params) #endif /* ! ACE_HAS_STHREADS && ! sun */ } -void -ACE_OS::mutex_lock_cleanup (void *mutex) -{ - ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup"); -#if defined (ACE_HAS_THREADS) -# if defined (ACE_HAS_PTHREADS) - ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex; - ACE_OS::mutex_unlock (p_lock); -# else - ACE_UNUSED_ARG (mutex); -# endif /* ACE_HAS_PTHREADS */ -#else - ACE_UNUSED_ARG (mutex); -#endif /* ACE_HAS_THREADS */ -} - #if !defined (ACE_HAS_THREADS) || (defined (ACE_LACKS_RWLOCK_T) && \ !defined (ACE_HAS_PTHREADS_UNIX98_EXT)) int |