diff options
author | Johnny Willemsen <jwillemsen@remedy.nl> | 2005-06-22 12:45:09 +0000 |
---|---|---|
committer | Johnny Willemsen <jwillemsen@remedy.nl> | 2005-06-22 12:45:09 +0000 |
commit | 1cc414706f2d174fa970cd298883db7e992e5e51 (patch) | |
tree | 7bed30dd9a623509f2ccf80de7699179ce165d6e | |
parent | 6b59a245758402722aef446c8d54d0a3840fa632 (diff) | |
download | ATCD-1cc414706f2d174fa970cd298883db7e992e5e51.tar.gz |
ChangeLogTag: Wed Jun 22 12:24:12 UTC 2005 Martin Corino <mcorino@remedy.nl>
-rw-r--r-- | ChangeLog | 33 | ||||
-rw-r--r-- | ace/OS_NS_Thread.cpp | 1316 | ||||
-rw-r--r-- | ace/OS_NS_Thread.h | 117 | ||||
-rw-r--r-- | ace/OS_NS_Thread.inl | 1351 | ||||
-rw-r--r-- | ace/config-linux-common.h | 12 | ||||
-rw-r--r-- | ace/config-lite.h | 6 | ||||
-rw-r--r-- | ace/config-posix.h | 5 | ||||
-rw-r--r-- | ace/os_include/os_pthread.h | 2 |
8 files changed, 1633 insertions, 1209 deletions
diff --git a/ChangeLog b/ChangeLog index a2814946f96..21bae97aaf8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +Wed Jun 22 12:24:12 UTC 2005 Martin Corino <mcorino@remedy.nl> + + * ace/config-posix.h: + Added test to set new macro ACE_HAS_POSIX_SEM_TIMEOUT when supported. + + * ace/config-linux-common.h: + Added include for config-posix.h to test for more supported POSIX + functionality. + Added special test for Linux kernels < 2.6 because these falsely + report certain POSIX support while not having that in reality + (f.i. ACE_HAS_POSIX_SEM with ACE_HAS_POSIX_SEM_TIMEOUT). + + * ace/config-lite.h: + Added test to undef (new) macro ACE_USES_FIFO_SEM (see below) when + other macro settings invalidate this one. + + * ace/os_include/os_pthread.h: + Extended test to prevent definition of ACE_sema_t when ACE_USES_FIFO_SEM + is defined. + + * ace/OS_NS_Thread{.h .inl .cpp}: + Added new implementation of ACE_OS::sema_XXX methods based on FIFOs + (derived from W. Richard Stevens, UNIX Network Programming V2) + active when !ACE_HAS_POSIX_SEM && ACE_USES_FIFO_SEM. + Offshoot of customer request for process shareable solution for Linux + 2.4.xx kernels. + + Outlined most ACE_OS::mutex_XXX and ACE_OS::event_XXX methods resulting + in a) ~7 Kb footprint reduction (Linux 2.6) and b) lessened dependency + complexities allowing later introduction of another Event platform + emulation. + + Wed Jun 22 08:51:12 UTC 2005 Johnny Willemsen <jwillemsen@remedy.nl> * include/makeinclude/build_core_exe.bor: 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 diff --git a/ace/OS_NS_Thread.h b/ace/OS_NS_Thread.h index 5d7b9c5ce9f..9fb32b2b88a 100644 --- a/ace/OS_NS_Thread.h +++ b/ace/OS_NS_Thread.h @@ -115,6 +115,18 @@ typedef DWORD ACE_OS_thread_key_t; # endif /* ! ACE_HAS_TSS_EMULATION */ # endif /* ACE_WIN32 */ +# if !defined (ACE_HAS_POSIX_SEM) && defined (ACE_USES_FIFO_SEM) + +extern "C" { + typedef struct + { + ACE_TCHAR* name_; + ACE_HANDLE fd_[2]; + } ACE_sema_t; +}; + +#endif /* !ACE_HAS_POSIX_SEM && ACE_USES_FIFO_SEM */ + # if defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) @@ -153,7 +165,7 @@ typedef mutex_t ACE_mutex_t; # if !defined (ACE_LACKS_RWLOCK_T) typedef rwlock_t ACE_rwlock_t; # endif /* !ACE_LACKS_RWLOCK_T */ -# if !defined (ACE_HAS_POSIX_SEM) +# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_USES_FIFO_SEM) typedef sema_t ACE_sema_t; # endif /* !ACE_HAS_POSIX_SEM */ @@ -696,7 +708,7 @@ typedef int ACE_mutex_t; typedef int ACE_thread_mutex_t; typedef int ACE_recursive_thread_mutex_t; typedef int ACE_recursive_mutex_state; -# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_PSOS) +# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_PSOS) && !defined (ACE_USES_FIFO_SEM) typedef int ACE_sema_t; # endif /* !ACE_HAS_POSIX_SEM && !ACE_PSOS */ typedef int ACE_rwlock_t; @@ -1263,10 +1275,10 @@ namespace ACE_OS { //@{ @name A set of wrappers for auto-reset and manual events. - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_destroy (ACE_event_t *event); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_init (ACE_event_t *event, int manual_reset = 0, int initial_state = 0, @@ -1286,21 +1298,21 @@ namespace ACE_OS { LPSECURITY_ATTRIBUTES sa = 0); # endif /* ACE_HAS_WCHAR */ - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_pulse (ACE_event_t *event); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_reset (ACE_event_t *event); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_signal (ACE_event_t *event); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_timedwait (ACE_event_t *event, ACE_Time_Value *timeout, int use_absolute_time = 1); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int event_wait (ACE_event_t *event); //@} @@ -1314,10 +1326,10 @@ namespace ACE_OS { //@{ @name A set of wrappers for mutex locks. - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_destroy (ACE_mutex_t *m); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_init (ACE_mutex_t *m, int lock_scope = ACE_DEFAULT_SYNCH_TYPE, const char *name = 0, @@ -1326,7 +1338,7 @@ namespace ACE_OS { int lock_type = 0); #if defined (ACE_HAS_WCHAR) - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_init (ACE_mutex_t *m, int lock_scope, const wchar_t *name, @@ -1337,12 +1349,12 @@ namespace ACE_OS { /// Win32 note: Abandoned mutexes are not treated differently. 0 is /// returned since the calling thread does get the ownership. - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_lock (ACE_mutex_t *m); /// This method is only implemented for Win32. For abandoned /// mutexes, <abandoned> is set to 1 and 0 is returned. - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_lock (ACE_mutex_t *m, int &abandoned); @@ -1355,7 +1367,7 @@ namespace ACE_OS { * 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_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_lock (ACE_mutex_t *m, const ACE_Time_Value &timeout); @@ -1378,16 +1390,16 @@ namespace ACE_OS { /// Win32 note: Abandoned mutexes are not treated differently. 0 is /// returned since the calling thread does get the ownership. - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_trylock (ACE_mutex_t *m); /// This method is only implemented for Win32. For abandoned /// mutexes, <abandoned> is set to 1 and 0 is returned. - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_trylock (ACE_mutex_t *m, int &abandoned); - ACE_NAMESPACE_INLINE_FUNCTION + extern ACE_Export int mutex_unlock (ACE_mutex_t *m); //@} @@ -1815,6 +1827,48 @@ namespace ACE_OS { } /* namespace ACE_OS */ #if !defined (ACE_WIN32) + +extern "C" +{ + typedef struct + { + /// Object type. + int type_; + + /// Protect critical section. + ACE_mutex_t lock_; + + /// Keeps track of waiters. +/* +#if (defined (ACE_USES_FIFO_SEM) || (defined (ACE_HAS_POSIX_SEM) && !defined (ACE_LACKS_NAMED_POSIX_SEM))) && \ + defined (ACE_HAS_PTHREADS) && (!defined (_POSIX_THREAD_PROCESS_SHARED) || defined (ACE_LACKS_CONDATTR_PSHARED)) + ACE_sema_t semaphore_; +#else +*/ + ACE_cond_t condition_; +//#endif + + /// Specifies if this is an auto- or manual-reset event. + int manual_reset_; + + /// "True" if signaled. + int is_signaled_; + + /// Special bool for auto_events alone + /** + * The semantics of auto events forces us to introduce this extra + * variable to ensure that the thread is not woken up + * spuriously. Please see event_wait and event_timedwait () to see + * how this is used for auto_events. Theoretically this is a hack + * that needs revisiting after x.4 + */ + bool auto_event_signaled_; + + /// Number of waiting threads. + unsigned long waiting_threads_; + } ACE_eventdata_t; +}; + /** * @class ACE_event_t * @@ -1831,31 +1885,14 @@ class ACE_Export ACE_event_t friend int ACE_OS::event_reset(ACE_event_t*); protected: - /// Protect critical section. - ACE_mutex_t lock_; - - /// Keeps track of waiters. - ACE_cond_t condition_; - - /// Specifies if this is an auto- or manual-reset event. - int manual_reset_; + /// Event name if process shared. + ACE_TCHAR* name_; - /// "True" if signaled. - int is_signaled_; + /// Event data + ACE_eventdata_t* eventdata_; - /// Special bool for auto_events alone - /** - * The semantics of auto events forces us to introduce this extra - * variable to ensure that the thread is not woken up - * spuriously. Please see event_wait and event_timedwait () to see - * how this is used for auto_events. Theoretically this is a hack - * that needs revisiting after x.4 - */ - bool auto_event_signaled_; - - /// Number of waiting threads. - unsigned long waiting_threads_; }; + #endif /* ACE_WIN32 */ #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) diff --git a/ace/OS_NS_Thread.inl b/ace/OS_NS_Thread.inl index ac084d571e2..04227059446 100644 --- a/ace/OS_NS_Thread.inl +++ b/ace/OS_NS_Thread.inl @@ -12,6 +12,12 @@ #include "ace/OS_NS_stdio.h" #include "ace/OS_NS_errno.h" +#if defined (ACE_USES_FIFO_SEM) +# include "ace/OS_NS_sys_stat.h" +# include "ace/OS_NS_sys_select.h" +# include "ace/Handle_Set.h" +# endif /* ACE_USES_FIFO_SEM */ + #if defined (ACE_HAS_PRIOCNTL) # include /**/ <sys/priocntl.h> #endif /* ACE_HAS_PRIOCNTL */ @@ -523,300 +529,10 @@ ACE_OS::cond_timedwait (ACE_cond_t *cv, #endif /* !ACE_LACKS_COND_T */ ACE_INLINE 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) - int r1 = ACE_OS::mutex_destroy (&event->lock_); - int r2 = ACE_OS::cond_destroy (&event->condition_); - return r1 != 0 || r2 != 0 ? -1 : 0; -#else - ACE_UNUSED_ARG (event); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_WIN32 */ -} - -ACE_INLINE 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 */ -} - -ACE_INLINE 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) +ACE_OS::mutex_lock (ACE_mutex_t *m, + const ACE_Time_Value *timeout) { -#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->manual_reset_ = manual_reset; - event->is_signaled_ = initial_state; - event->auto_event_signaled_ = false; - event->waiting_threads_ = 0; - - int result = ACE_OS::cond_init (&event->condition_, - static_cast<short> (type), - name, - arg); - if (result == 0) - result = ACE_OS::mutex_init (&event->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 */ + return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout); } #if defined (ACE_HAS_WCHAR) @@ -835,10 +551,10 @@ ACE_OS::event_init (ACE_event_t *event, SECURITY_ATTRIBUTES sa_buffer; SECURITY_DESCRIPTOR sd_buffer; *event = ::CreateEventW (ACE_OS::default_win32_security_attributes_r - (sa, &sa_buffer, &sd_buffer), - manual_reset, - initial_state, - name); + (sa, &sa_buffer, &sd_buffer), + manual_reset, + initial_state, + name); if (*event == 0) ACE_FAIL_RETURN (-1); @@ -856,817 +572,6 @@ ACE_OS::event_init (ACE_event_t *event, #endif /* ACE_HAS_WCHAR */ ACE_INLINE 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->lock_) == 0) - { - // Manual-reset event. - if (event->manual_reset_ == 1) - { - // Wakeup all waiters. - if (ACE_OS::cond_broadcast (&event->condition_) != 0) - { - result = -1; - error = errno; - } - } - // Auto-reset event: wakeup one waiter. - else if (ACE_OS::cond_signal (&event->condition_) != 0) - { - result = -1; - error = errno; - } - - // Reset event. - event->is_signaled_ = 0; - - // Now we can let go of the lock. - ACE_OS::mutex_unlock (&event->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 */ -} - -ACE_INLINE 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->lock_) == 0) - { - // Reset event. - event->is_signaled_ = 0; - event->auto_event_signaled_ = false; - - // Now we can let go of the lock. - ACE_OS::mutex_unlock (&event->lock_); - } - else - result = -1; - return result; -#else - ACE_UNUSED_ARG (event); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_WIN32 */ -} - -ACE_INLINE 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->lock_) == 0) - { - // Manual-reset event. - if (event->manual_reset_ == 1) - { - // wakeup all - if (ACE_OS::cond_broadcast (&event->condition_) != 0) - { - result = -1; - error = errno; - } - - // signal event - event->is_signaled_ = 1; - } - // Auto-reset event - else - { - if (event->waiting_threads_ == 0) - // No waiters: signal event. - event->is_signaled_ = 1; - // Waiters: wakeup one waiter. - else if (ACE_OS::cond_signal (&event->condition_) != 0) - { - result = -1; - error = errno; - } - - event->auto_event_signaled_ = true; - } - - // Now we can let go of the lock. - ACE_OS::mutex_unlock (&event->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 */ -} - -ACE_INLINE 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->lock_) == 0) - { - if (event->is_signaled_ == 1) - // event is currently signaled - { - if (event->manual_reset_ == 0) - { - // AUTO: reset state - event->is_signaled_ = 0; - event->auto_event_signaled_ = false; - } - } - else - // event is currently not signaled - { - event->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->is_signaled_ == 0 && - event->auto_event_signaled_ == false) - { - if (ACE_OS::cond_timedwait (&event->condition_, - &event->lock_, - &absolute_timeout) != 0) - { - result = -1; - error = errno; - break; - } - } - - // Reset the auto_event_signaled_ to false now that we have - // woken up. - if (event->auto_event_signaled_ == true) - event->auto_event_signaled_ = false; - - event->waiting_threads_--; - } - - // Now we can let go of the lock. - ACE_OS::mutex_unlock (&event->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 */ -} - -ACE_INLINE 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->lock_) == 0) - { - if (event->is_signaled_ == 1) - // Event is currently signaled. - { - if (event->manual_reset_ == 0) - // AUTO: reset state - event->is_signaled_ = 0; - } - else // event is currently not signaled - { - event->waiting_threads_++; - - while (event->is_signaled_ == 0 && - event->auto_event_signaled_ == false) - { - if (ACE_OS::cond_wait (&event->condition_, - &event->lock_) != 0) - { - result = -1; - error = errno; - // Something went wrong... - break; - } - } - - // Reset it since we have woken up. - if (event->auto_event_signaled_ == true) - event->auto_event_signaled_ = false; - - event->waiting_threads_--; - } - - // Now we can let go of the lock. - ACE_OS::mutex_unlock (&event->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 */ -} - -ACE_INLINE 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) -ACE_INLINE 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 */ - -ACE_INLINE 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 */ -} - -ACE_INLINE 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 */ -} - -ACE_INLINE 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 */ -} - -ACE_INLINE int -ACE_OS::mutex_lock (ACE_mutex_t *m, - const ACE_Time_Value *timeout) -{ - return timeout == 0 ? ACE_OS::mutex_lock (m) : ACE_OS::mutex_lock (m, *timeout); -} - -ACE_INLINE 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 */ -} - -ACE_INLINE 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 */ -} - -ACE_INLINE 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 */ -} - -ACE_INLINE int ACE_OS::priority_control (ACE_idtype_t idtype, ACE_id_t identifier, int cmd, void *arg) { ACE_OS_TRACE ("ACE_OS::priority_control"); @@ -1899,29 +804,29 @@ ACE_OS::recursive_mutex_lock (ACE_recursive_thread_mutex_t *m) if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1) result = -1; else - { + { // If there's no contention, just grab the lock immediately // (since this is the common case we'll optimize for it). - if (m->nesting_level_ == 0) - m->owner_id_ = t_id; + if (m->nesting_level_ == 0) + m->owner_id_ = t_id; // If we already own the lock, then increment the nesting level // and return. - else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0) - { + else if (ACE_OS::thr_equal (t_id, m->owner_id_) == 0) + { // Wait until the nesting level has dropped to zero, at // which point we can acquire the lock. - while (m->nesting_level_ > 0) - ACE_OS::cond_wait (&m->lock_available_, - &m->nesting_mutex_); + while (m->nesting_level_ > 0) + ACE_OS::cond_wait (&m->lock_available_, + &m->nesting_mutex_); // At this point the nesting_mutex_ is held... - m->owner_id_ = t_id; - } + m->owner_id_ = t_id; + } // At this point, we can safely increment the nesting_level_ no // matter how we got here! - m->nesting_level_++; - } + m->nesting_level_++; + } { // Save/restore errno. @@ -1950,23 +855,23 @@ ACE_OS::recursive_mutex_trylock (ACE_recursive_thread_mutex_t *m) if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1) result = -1; else - { + { // If there's no contention, just grab the lock immediately. - if (m->nesting_level_ == 0) - { - m->owner_id_ = t_id; - m->nesting_level_ = 1; - } + if (m->nesting_level_ == 0) + { + m->owner_id_ = t_id; + m->nesting_level_ = 1; + } // If we already own the lock, then increment the nesting level // and proceed. - else if (ACE_OS::thr_equal (t_id, m->owner_id_)) - m->nesting_level_++; - else - { - errno = EBUSY; - result = -1; - } + else if (ACE_OS::thr_equal (t_id, m->owner_id_)) + m->nesting_level_++; + else + { + errno = EBUSY; + result = -1; } + } { // Save/restore errno. @@ -1997,36 +902,36 @@ ACE_OS::recursive_mutex_unlock (ACE_recursive_thread_mutex_t *m) if (ACE_OS::thread_mutex_lock (&m->nesting_mutex_) == -1) result = -1; else - { + { # if !defined (ACE_NDEBUG) if (m->nesting_level_ == 0 || ACE_OS::thr_equal (t_id, m->owner_id_) == 0) - { - errno = EINVAL; - result = -1; - } +{ + errno = EINVAL; + result = -1; +} else # endif /* ACE_NDEBUG */ - { - m->nesting_level_--; - if (m->nesting_level_ == 0) - { +{ + m->nesting_level_--; + if (m->nesting_level_ == 0) + { // This may not be strictly necessary, but it does put // the mutex into a known state... - m->owner_id_ = ACE_OS::NULL_thread; + m->owner_id_ = ACE_OS::NULL_thread; // Inform a waiter that the lock is free. - if (ACE_OS::cond_signal (&m->lock_available_) == -1) - result = -1; - } - } - } + if (ACE_OS::cond_signal (&m->lock_available_) == -1) + result = -1; + } +} + } - { +{ // Save/restore errno. - ACE_Errno_Guard error (errno); - ACE_OS::thread_mutex_unlock (&m->nesting_mutex_); - } + ACE_Errno_Guard error (errno); + ACE_OS::thread_mutex_unlock (&m->nesting_mutex_); +} return result; # endif /* ACE_HAS_RECURSIVE_MUTEXES */ #else @@ -2460,6 +1365,17 @@ ACE_OS::sema_destroy (ACE_sema_t *s) s->sema_ = 0; return result; } +# elif defined (ACE_USES_FIFO_SEM) + int r0 = 0; + if (s->name_) + { + r0 = ACE_OS::unlink (s->name_); /* if we created FIFO */ + ACE_OS::free (s->name_); + s->name_ = 0; + } + int r1 = ACE_OS::close (s->fd_[0]); /* ignore error */ + int r2 = ACE_OS::close (s->fd_[1]); /* ignore error */ + return r0 != 0 || r1 != 0 || r2 != 0 ? -1 : 0; # elif defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) int result; @@ -2612,6 +1528,66 @@ ACE_OS::sema_init (ACE_sema_t *s, type != USYNC_THREAD, count), int, -1); } + +#elif defined (ACE_USES_FIFO_SEM) + int flags = 0; + mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP; + + if (type == USYNC_THREAD) + { + // Create systemwide unique name for semaphore + ACE_TCHAR uname[ACE_UNIQUE_NAME_LEN]; + ACE_OS::unique_name ((const void *) s, + uname, + ACE_UNIQUE_NAME_LEN); + name = &uname[0]; + } + + s->name_ = 0; + s->fd_[0] = s->fd_[1] = ACE_INVALID_HANDLE; + + if (ACE_OS::mkfifo (name, mode) < 0) + { + if (errno != EEXIST) /* already exists OK else ERR */ + return -1; + // check if this is a real FIFO, not just some other existing file + ACE_stat fs; + if (ACE_OS::stat (name, &fs)) + return -1; + if (!S_ISFIFO(fs.st_mode)) + { + // existing file is not a FIFO + errno = EEXIST; + return -1; + } + } + else + { + s->name_ = ACE_OS::strdup (name); + } + + + if ((s->fd_[0] = ACE_OS::open (name, O_RDONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE + || (s->fd_[1] = ACE_OS::open (name, O_WRONLY | O_NONBLOCK)) == ACE_INVALID_HANDLE) + return(-1); + + /* turn off nonblocking for fd_[0] */ + if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0) + return(-1); + + flags &= ~O_NONBLOCK; + if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0) + return(-1); + + if (s->name_ && count) + { + char c = 1; + for(u_int i=0; i<count ;++i) + if (ACE_OS::write (s->fd_[1], &c, sizeof(char)) != 1) + return(-1); + } + + return(0); #elif defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) ACE_UNUSED_ARG (name); @@ -2802,6 +1778,12 @@ ACE_OS::sema_post (ACE_sema_t *s) ACE_OS_TRACE ("ACE_OS::sema_post"); # if defined (ACE_HAS_POSIX_SEM) ACE_OSCALL_RETURN (::sem_post (s->sema_), int, -1); +# elif defined (ACE_USES_FIFO_SEM) + char c = 1; + + if (ACE_OS::write (s->fd_[1], &c, sizeof(char)) == 1) + return(0); + return(-1); # elif defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) int result; @@ -2888,6 +1870,27 @@ ACE_OS::sema_trywait (ACE_sema_t *s) # if defined (ACE_HAS_POSIX_SEM) // POSIX semaphores set errno to EAGAIN if trywait fails ACE_OSCALL_RETURN (::sem_trywait (s->sema_), int, -1); +# elif defined (ACE_USES_FIFO_SEM) + char c; + int rc, flags; + + /* turn on nonblocking for s->fd_[0] */ + if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) < 0) + return(-1); + flags |= O_NONBLOCK; + if (ACE_OS::fcntl (s->fd_[0], F_SETFL, flags) < 0) + return(-1); + + rc = ACE_OS::read (s->fd_[0], &c, sizeof(char)); + + /* turn off nonblocking for fd_[0] */ + if ((flags = ACE_OS::fcntl (s->fd_[0], F_GETFL, 0)) >= 0) + { + flags &= ~O_NONBLOCK; + ACE_OS::fcntl (s->fd_[0], F_SETFL, flags); + } + + return rc == 1 ? 0 : (-1); # elif defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) // STHREADS semaphores set errno to EBUSY if trywait fails. @@ -3000,6 +2003,11 @@ ACE_OS::sema_wait (ACE_sema_t *s) ACE_OS_TRACE ("ACE_OS::sema_wait"); # if defined (ACE_HAS_POSIX_SEM) ACE_OSCALL_RETURN (::sem_wait (s->sema_), int, -1); +# elif defined (ACE_USES_FIFO_SEM) + char c; + if (ACE_OS::read (s->fd_[0], &c, sizeof(char)) == 1) + return(0); + return(-1); # elif defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) int result; @@ -3108,9 +2116,48 @@ ACE_OS::sema_wait (ACE_sema_t *s, ACE_Time_Value &tv) { ACE_OS_TRACE ("ACE_OS::sema_wait"); # if defined (ACE_HAS_POSIX_SEM) +# if defined (ACE_HAS_POSIX_SEM_TIMEOUT) + timespec_t ts; + ts = tv; // Calls ACE_Time_Value::operator timespec_t(). + ACE_OSCALL_RETURN (::sem_timedwait (s->sema_, &ts), int, -1); +# else ACE_UNUSED_ARG (s); ACE_UNUSED_ARG (tv); ACE_NOTSUP_RETURN (-1); +# endif /* !ACE_HAS_POSIX_SEM_TIMEOUT */ +# elif defined (ACE_USES_FIFO_SEM) + int rc; + ACE_Time_Value now = ACE_OS::gettimeofday (); + + while (tv > now) + { + ACE_Time_Value timeout = tv; + timeout -= now; + + ACE_Handle_Set fds_; + + fds_.set_bit (s->fd_[0]); + if ((rc = ACE_OS::select (ACE_Handle_Set::MAXSIZE, fds_, 0, 0, timeout)) != 1) + { + if (rc == 0) + // make sure errno is set right (select() sets ETIME) + errno = ETIMEDOUT; + return (-1); + } + + // try to read the signal *but* do *not* block + if (ACE_OS::sema_trywait(s) == 0) + return (0); + + // we were woken for input but someone beat us to it + // so we wait again if there is still time + now = ACE_OS::gettimeofday (); + } + + // make sure errno is set right + errno = ETIMEDOUT; + + return(-1); # elif defined (ACE_HAS_THREADS) # if defined (ACE_HAS_STHREADS) ACE_UNUSED_ARG (s); diff --git a/ace/config-linux-common.h b/ace/config-linux-common.h index d771c1a4086..0a7bc58ae01 100644 --- a/ace/config-linux-common.h +++ b/ace/config-linux-common.h @@ -36,6 +36,18 @@ # endif /* !ACE_HAS_CLOCK_GETTIME */ #endif /* _POSIX_C_SOURCE >= 199309L */ +#include "ace/config-posix.h" + +#if defined (ACE_HAS_POSIX_SEM) +# include <linux/version.h> +# if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) + // Linux versions < 2.6 may define all the right POSIX macros + // but they lack the actual runtime support for this stuff +# undef ACE_HAS_POSIX_SEM +# define ACE_USES_FIFO_SEM +# endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)) */ +#endif /* ACE_HAS_POSIX_SEM */ + // First the machine specific part #if defined (__powerpc__) diff --git a/ace/config-lite.h b/ace/config-lite.h index 861f177e9bb..48e89e4142a 100644 --- a/ace/config-lite.h +++ b/ace/config-lite.h @@ -136,6 +136,12 @@ # endif # endif /* ACE_HAS_DYNAMIC_LINKING */ +# if defined (ACE_USES_FIFO_SEM) +# if defined (ACE_HAS_POSIX_SEM) || defined (ACE_LACKS_MKFIFO) || defined (ACE_LACKS_FCNTL) +# undef ACE_USES_FIFO_SEM +# endif +# endif /* ACE_USES_FIFO_SEM */ + // ========================================================================= // RCSID Macros // ========================================================================= diff --git a/ace/config-posix.h b/ace/config-posix.h index a103215dcb6..809072dc850 100644 --- a/ace/config-posix.h +++ b/ace/config-posix.h @@ -26,6 +26,11 @@ # if !defined(ACE_HAS_POSIX_SEM) # define ACE_HAS_POSIX_SEM # endif /* ACE_HAS_POSIX_SEM */ +# if defined(ACE_HAS_POSIX_SEM) +# if !defined (ACE_HAS_POSIX_SEM_TIMEOUT) && (defined (_POSIX_TIMEOUTS) || ((_POSIX_C_SOURCE - 0) >= 200112L) || (_XOPEN_SOURCE >= 600)) +# define ACE_HAS_POSIX_SEM_TIMEOUT +# endif /* ACE_HAS_POSIX_SEM_TIMEOUT && (_POSIX_TIMEOUTS || ((_POSIX_C_SOURCE - 0) >= 200112L) || (_XOPEN_SOURCE >= 600)) */ +# endif /* ACE_HAS_POSIX_SEM */ #endif /* ACE_HAS_POSIX_SEM */ #if defined(_POSIX_MESSAGE_PASSING) && (_POSIX_MESSAGE_PASSING-0 != -1 ) diff --git a/ace/os_include/os_pthread.h b/ace/os_include/os_pthread.h index 6eccef3a418..a457271c9eb 100644 --- a/ace/os_include/os_pthread.h +++ b/ace/os_include/os_pthread.h @@ -372,7 +372,7 @@ extern "C" pthread_t pthread_self (void); # define THR_SCHED_IO 0x01000000 # if !defined (ACE_HAS_STHREADS) -# if !defined (ACE_HAS_POSIX_SEM) +# if !defined (ACE_HAS_POSIX_SEM) && !defined (ACE_USES_FIFO_SEM) // This needs to be moved out of here. #include "ace/ACE_export.h" |