diff options
Diffstat (limited to 'ace/OS.cpp')
-rw-r--r-- | ace/OS.cpp | 2330 |
1 files changed, 0 insertions, 2330 deletions
diff --git a/ace/OS.cpp b/ace/OS.cpp deleted file mode 100644 index 08eaded2edc..00000000000 --- a/ace/OS.cpp +++ /dev/null @@ -1,2330 +0,0 @@ -// $Id$ - -// OS.cpp -#define ACE_BUILD_DLL -#include "ace/OS.h" -#include "ace/Sched_Params.h" - -#if defined (ACE_WIN32) -#include "ace/ARGV.h" -#endif /* ACE_WIN32 */ - -// Perhaps we should *always* include ace/OS.i in order to make sure -// we can always link against the OS symbols? -#if !defined (ACE_HAS_INLINED_OSCALLS) -#include "ace/OS.i" -#endif /* ACE_HAS_INLINED_OS_CALLS */ - -// Static constant representing `zero-time'. -const ACE_Time_Value ACE_Time_Value::zero; - -ACE_ALLOC_HOOK_DEFINE(ACE_Time_Value) - -// Initializes the ACE_Time_Value object from a timeval. - -#if defined(ACE_WIN32) -// Initializes the ACE_Time_Value object from a Win32 FILETIME - -ACE_Time_Value::ACE_Time_Value (const FILETIME &file_time) -{ - // ACE_TRACE ("ACE_Time_Value::ACE_Time_Value"); - this->set (file_time); -} - -void ACE_Time_Value::set (const FILETIME &file_time) -{ - // Initializes the ACE_Time_Value object from a Win32 FILETIME - ACE_QWORD _100ns = ACE_MAKE_QWORD (file_time.dwLowDateTime, - file_time.dwHighDateTime); - // Convert 100ns units to seconds; - this->tv_.tv_sec = long (_100ns / (10000 * 1000)); - // Convert remainder to microseconds; - this->tv_.tv_usec = long ((_100ns - (this->tv_.tv_sec * (10000 * 1000))) / 10); -} - -// Returns the value of the object as a Win32 FILETIME. - -ACE_Time_Value::operator FILETIME () const -{ - // ACE_TRACE ("ACE_Time_Value::operator FILETIME"); - ACE_QWORD _100ns = ((ACE_QWORD) this->tv_.tv_sec * (1000 * 1000) + this->tv_.tv_usec) * 10; - FILETIME file_time; - file_time.dwLowDateTime = ACE_LOW_DWORD (_100ns); - file_time.dwHighDateTime = ACE_HIGH_DWORD (_100ns); - return file_time; -} - -#endif - -void -ACE_Time_Value::dump (void) const -{ - // ACE_TRACE ("ACE_Time_Value::dump"); -#if 0 - if (tv.usec () < 0 || tv.sec () < 0) - stream << "-"; - - stream << dec << abs (int (tv.sec ())) << "." -// << setw (6) << setfill ('0') - << dec << abs (int (tv.usec ())); -// I assume - inline int abs(int d) { return (d>0)?d:-d; } - is defined somewhere */ -#endif /* 0 */ -} - -void -ACE_Time_Value::normalize (void) -{ - // ACE_TRACE ("ACE_Time_Value::normalize"); - // New code from Hans Rohnert... - - if (this->tv_.tv_usec >= ONE_SECOND) - { - do - { - this->tv_.tv_sec++; - this->tv_.tv_usec -= ONE_SECOND; - } - while (this->tv_.tv_usec >= ONE_SECOND); - } - else if (this->tv_.tv_usec <= -ONE_SECOND) - { - do - { - this->tv_.tv_sec--; - this->tv_.tv_usec += ONE_SECOND; - } - while (this->tv_.tv_usec <= -ONE_SECOND); - } - - if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0) - { - this->tv_.tv_sec--; - this->tv_.tv_usec += ONE_SECOND; - } - else if (this->tv_.tv_sec < 0 && this->tv_.tv_usec > 0) - { - this->tv_.tv_sec++; - this->tv_.tv_usec -= ONE_SECOND; - } -} - -int -ACE_Countdown_Time::start (void) -{ - this->start_time_ = ACE_OS::gettimeofday (); - this->stopped_ = 0; - return 0; -} - -int -ACE_Countdown_Time::update (void) -{ - return (this->stop () == 0) && this->start (); -} - -int -ACE_Countdown_Time::stop (void) -{ - if (this->max_wait_time_ != 0 && this->stopped_ == 0) - { - ACE_Time_Value elapsed_time = - ACE_OS::gettimeofday () - this->start_time_; - - if (*this->max_wait_time_ > elapsed_time) - *this->max_wait_time_ -= elapsed_time; - else - { - // Used all of timeout. - *this->max_wait_time_ = ACE_Time_Value::zero; - errno = ETIME; - } - this->stopped_ = 1; - } - return 0; -} - -ACE_Countdown_Time::ACE_Countdown_Time (ACE_Time_Value *max_wait_time) - : max_wait_time_ (max_wait_time), - stopped_ (0) -{ - if (max_wait_time != 0) - this->start (); -} - -ACE_Countdown_Time::~ACE_Countdown_Time (void) -{ - this->stop (); -} - -#if defined (ACE_HAS_PENTIUM) && defined (__GNUC__) -ACE_hrtime_t -ACE_OS::gethrtime (void) -{ - // ACE_TRACE ("ACE_OS::gethrtime"); - - // See comments for ACE_WIN32 version of ACE_OS::gethrtime () in OS.i. - // - // This function can't be inline because it depends on the location - // of the following variables on the stack. - unsigned long least, most; - - asm ("rdtsc"); - asm ("movl %eax, -4(%ebp)"); // least - asm ("movl %edx, -8(%ebp)"); // most - - return (unsigned long long) most << 32 | least; -} -#endif /* ACE_HAS_PENTIUM && __GNUC__ */ - -#if defined (ACE_HAS_POWERPC) && defined (ghs) -void -ACE_OS::readPPCTimeBase (u_long &most, u_long &least) -{ - // ACE_TRACE ("ACE_OS::readPPCTimeBase"); - - // This function can't be inline because it depends on the arguments - // being in particular registers (r3 and r4), in conformance with the - // EABI standard. It would be nice if we knew how to put the variable - // names directly into the assembler instructions . . . - asm("aclock:"); - asm("mftb r5,TBU"); - asm("mftb r6,TBL"); - asm("mftb r7,TBU"); - asm("cmpw r5,r7"); - asm("bne aclock"); - - asm("stw r5, 0(r3)"); - asm("stw r6, 0(r4)"); -} -#endif /* ACE_HAS_POWERPC && ghs */ - -#if defined (ACE_WIN32) || defined (VXWORKS) -// Don't inline on those platforms because this function contains -// string literals, and some compilers, e.g., g++, don't handle those -// efficiently in unused inline functions. -int -ACE_OS::uname (struct utsname *name) -{ - // ACE_TRACE ("ACE_OS::uname"); -#if defined (ACE_WIN32) - size_t maxnamelen = sizeof name->nodename; - ::strcpy (name->sysname, "Win32"); - // Any ideas what these should be? - ::strcpy (name->release, "???"); - ::strcpy (name->version, "???"); - ::strcpy (name->machine, "???"); - - return ACE_OS::hostname (name->nodename, maxnamelen); -#elif defined (VXWORKS) - size_t maxnamelen = sizeof name->nodename; - ::strcpy (name->sysname, "VxWorks"); - ::strcpy (name->release, "???"); - ::strcpy (name->version, "???"); - ::strcpy (name->machine, "???"); - - return ACE_OS::hostname (name->nodename, maxnamelen); -#endif /* ACE_WIN32 */ -} -#endif /* ACE_WIN32 || VXWORKS */ - - -#if defined(ACE_MT_SAFE) && defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) - -int ACE_OS::netdb_mutex_inited_ = 0; - -ACE_mutex_t ACE_OS::netdb_mutex_; - -int -ACE_OS::netdb_acquire (void) -{ - if (ACE_OS::netdb_mutex_inited_ == 0) - { - if (ACE_OS::thread_mutex_init (&ACE_OS::netdb_mutex_) != 0) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", - "ACE_OS::netdb_acquire[init]"), -1); - ACE_OS::netdb_mutex_inited_ = 1; - } - - if (ACE_OS::thread_mutex_lock (&ACE_OS::netdb_mutex_) != 0) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", - "ACE_OS::netdb_acquire[lock]"), -1); - return 0; -} - -int -ACE_OS::netdb_release (void) -{ - if (ACE_OS::netdb_mutex_inited_ == 0) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", - "ACE_OS::netdb_release[inited]"), -1); - - if (ACE_OS::thread_mutex_unlock (&ACE_OS::netdb_mutex_) != 0) - ACE_ERROR_RETURN ((LM_ERROR, "%p\n", - "ACE_OS::netdb_release[unlock]"), -1); - return 0; -} -#endif /* defined(ACE_MT_SAFE) && defined(ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */ - -struct hostent * -ACE_OS::gethostbyname (const char *name) -{ - // ACE_TRACE ("ACE_OS::gethostbyname"); -#if defined (VXWORKS) - // not thread safe! - static hostent ret; - static int first_addr = ::hostGetByName ((char *) name); - static char *hostaddr[2]; - - if (first_addr == -1) - return 0; - - hostaddr[0] = (char *) &first_addr; - hostaddr[1] = 0; - - // might not be official: just echo input arg. - ret.h_name = (char *) name; - ret.h_addrtype = AF_INET; - ret.h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN; - ret.h_addr_list = hostaddr; - - return &ret; -#elif defined (ACE_HAS_NONCONST_GETBY) - ACE_SOCKCALL_RETURN (::gethostbyname ((char *) name), struct hostent *, 0); -#else - ACE_SOCKCALL_RETURN (::gethostbyname (name), struct hostent *, 0); -#endif /* ACE_HAS_NONCONST_GETBY */ -} - -#if defined (VXWORKS) -// not inline because it has the static char array -char * -ACE_OS::inet_ntoa (const struct in_addr addr) -{ - // ACE_TRACE ("ACE_OS::inet_ntoa"); - - // the following storage is not thread-specific! - static char buf[32]; - // assumes that addr is already in network byte order - ACE_OS::sprintf (buf, "%d.%d.%d.%d", addr.s_addr / (256*256*256) & 255, - addr.s_addr / (256*256) & 255, - addr.s_addr / 256 & 255, - addr.s_addr & 255); - return buf; -} -#endif /* VXWORKS */ - -void -ACE_OS::ace_flock_t::dump (void) const -{ -// ACE_TRACE ("ACE_OS::ace_flock_t::dump"); - - ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, "handle_ = %u", this->handle_)); -#if defined (ACE_WIN32) - ACE_DEBUG ((LM_DEBUG, "\nInternal = %d", this->overlapped_.Internal)); - ACE_DEBUG ((LM_DEBUG, "\nInternalHigh = %d", this->overlapped_.InternalHigh)); - ACE_DEBUG ((LM_DEBUG, "\nOffsetHigh = %d", this->overlapped_.OffsetHigh)); - ACE_DEBUG ((LM_DEBUG, "\nhEvent = %d", this->overlapped_.hEvent)); -#elif !defined (CHORUS) - ACE_DEBUG ((LM_DEBUG, "\nl_whence = %d", this->lock_.l_whence)); - ACE_DEBUG ((LM_DEBUG, "\nl_start = %d", this->lock_.l_start)); - ACE_DEBUG ((LM_DEBUG, "\nl_len = %d", this->lock_.l_len)); - ACE_DEBUG ((LM_DEBUG, "\nl_type = %d", this->lock_.l_type)); -#endif /* ACE_WIN32 */ - ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -} - -void -ACE_OS::mutex_lock_cleanup (void *mutex) -{ -// ACE_TRACE ("ACE_OS::mutex_lock_cleanup"); -#if defined (ACE_HAS_THREADS) -#if defined (ACE_HAS_DCETHREADS) || 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_DCETHREADS */ -#else - ACE_UNUSED_ARG (mutex); -#endif /* ACE_HAS_THREADS */ -} - -// The following *printf functions aren't inline because -// they use varargs. -int -ACE_OS::fprintf (FILE *fp, const char *format, ...) -{ - // ACE_TRACE ("ACE_OS::fprintf"); - int result = 0; - va_list ap; - va_start (ap, format); - ACE_OSCALL (::vfprintf (fp, format, ap), int, -1, result); - va_end (ap); - return result; -} - -int -ACE_OS::printf (const char *format, ...) -{ - // ACE_TRACE ("ACE_OS::printf"); - int result; - va_list ap; - va_start (ap, format); - ACE_OSCALL (::vprintf (format, ap), int, -1, result); - va_end (ap); - return result; -} - -int -ACE_OS::sprintf (char *buf, const char *format, ...) -{ - // ACE_TRACE ("ACE_OS::sprintf"); - int result; - va_list ap; - va_start (ap, format); - ACE_OSCALL (ACE_SPRINTF_ADAPTER (::vsprintf (buf, format, ap)), int, -1, result); - va_end (ap); - return result; -} - -#if defined (ACE_HAS_UNICODE) -#if defined (ACE_WIN32) -int -ACE_OS::sprintf (wchar_t *buf, const wchar_t *format, ...) -{ - // ACE_TRACE ("ACE_OS::sprintf"); - int result; - va_list ap; - va_start (ap, format); - ACE_OSCALL (::vswprintf (buf, format, ap), int, -1, result); - va_end (ap); - return result; -} -#endif /* ACE_WIN32 */ -#endif /* ACE_HAS_UNICODE */ - -int -ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...) -{ - // ACE_TRACE ("ACE_OS::execl"); -#if defined (ACE_WIN32) || defined (VXWORKS) - ACE_NOTSUP_RETURN (-1); -#else - ACE_NOTSUP_RETURN (-1); - // Need to write this code. - // ACE_OSCALL_RETURN (::execv (path, argv), int, -1); -#endif /* ACE_WIN32 */ -} - -int -ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...) -{ - // ACE_TRACE ("ACE_OS::execle"); -#if defined (ACE_WIN32) || defined (VXWORKS) - ACE_NOTSUP_RETURN (-1); -#else - ACE_NOTSUP_RETURN (-1); - // Need to write this code. - // ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1); -#endif /* ACE_WIN32 */ -} - -int -ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...) -{ - // ACE_TRACE ("ACE_OS::execlp"); -#if defined (ACE_WIN32) || defined (VXWORKS) - ACE_NOTSUP_RETURN (-1); -#else - ACE_NOTSUP_RETURN (-1); - // Need to write this code. - // ACE_OSCALL_RETURN (::execvp (file, argv), int, -1); -#endif /* ACE_WIN32 */ -} - -#if defined (ACE_HAS_STHREADS) -#include /**/ <sys/rtpriocntl.h> -#include /**/ <sys/tspriocntl.h> -#endif /* ACE_HAS_STHREADS */ - -int -ACE_OS::thr_setprio (const ACE_Sched_Priority prio) -{ - // Set the thread priority on the current thread. - ACE_hthread_t my_thread_id; - ACE_OS::thr_self (my_thread_id); - return ACE_OS::thr_setprio (my_thread_id, prio); -} - -int -ACE_OS::sched_params (const ACE_Sched_Params &sched_params) -{ - // ACE_TRACE ("ACE_OS::sched_params"); -#if defined (ACE_HAS_STHREADS) - // Set priority class, priority, and quantum of this LWP or process as - // specified in sched_params. - - // Get the priority class ID and attributes. - pcinfo_t pcinfo; - ACE_OS::strcpy (pcinfo.pc_clname, - sched_params.policy() == ACE_SCHED_OTHER ? "TS" : "RT"); - // The following is just to avoid Purify warnings about unitialized - // memory reads. - ACE_OS::memset (pcinfo.pc_clinfo, 0, PC_CLINFOSZ); - - if (::priocntl (P_ALL /* ignored */, - P_MYID /* ignored */, - PC_GETCID, - (char *) &pcinfo) == -1) - { - return -1; - } - - // OK, now we've got the class ID in pcinfo.pc_cid. In addition, - // the maximum configured real-time priority is in ((rtinfo_t *) - // pcinfo.pc_clinfo)->rt_maxpri. - - pcparms_t pcparms; - pcparms.pc_cid = pcinfo.pc_cid; - - if (sched_params.policy () == ACE_SCHED_OTHER && - sched_params.quantum () == ACE_Time_Value::zero) - // Solaris doesn't support non-zero quantums in time-sharing class: use - // real-time class instead. - { - tsparms_t tsparms; - // Don't change ts_uprilim (user priority limit) - tsparms.ts_uprilim = TS_NOCHANGE; - tsparms.ts_upri = sched_params.priority (); - - // Package up the TS class ID and parameters for the ::priocntl () - // call. - ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms); - } - else if (sched_params.policy () == ACE_SCHED_FIFO || - (sched_params.policy () == ACE_SCHED_RR && - sched_params.quantum () != ACE_Time_Value::zero)) - // must have non-zero quantum for RR, to make it meaningful - // A zero quantum with FIFO has special significance: it actually - // means infinite time quantum, i.e., run-to-completion. - { - rtparms_t rtparms; - rtparms.rt_pri = sched_params.priority (); - - if (sched_params.quantum () == ACE_Time_Value::zero) - { - // rtparms.rt_tqsecs is ignored with RT_TQINF - rtparms.rt_tqnsecs = RT_TQINF; - } - else - { - rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec (); - rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000; - } - - // Package up the RT class ID and parameters for the ::priocntl () - // call. - ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms); - } - else - { - errno = EINVAL; - return -1; - } - - if (::priocntl ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD - ? ACE_SCOPE_PROCESS - : sched_params.scope ()), P_MYID, PC_SETPARMS, - (char *) &pcparms) < 0) - { - return ACE_OS::last_error (); - } - - return 0; - -#elif (defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS)) && !defined (ACE_LACKS_SETSCHED) - if (sched_params.quantum () != ACE_Time_Value::zero) - { - // quantums not supported - errno = EINVAL; - return -1; - } - - // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for - // providing this code for 1003.1c PThreads. Please note that this - // has only been tested for POSIX 1003.1c threads, and may cause problems - // with other PThreads flavors! - - int result; - struct sched_param param; - - param.sched_priority = sched_params.priority (); - - if (sched_params.scope () == ACE_SCOPE_PROCESS) - { - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::sched_setscheduler ( - 0, // this process - sched_params.policy (), - ¶m), - result), - int, -1); - } - else if (sched_params.scope () == ACE_SCOPE_THREAD) - { - ACE_thread_t thr_id = ACE_OS::thr_self (); - - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam ( - thr_id, - sched_params.policy (), - ¶m), - result), - int, -1); - } - else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX - { - errno = EINVAL; - return -1; - } - -#elif defined (ACE_WIN32) - - if (sched_params.scope () != ACE_SCOPE_PROCESS || - sched_params.quantum () != ACE_Time_Value::zero) - { - // Win32 only allows setting priority class (therefore, policy) - // at the process level. I don't know of a way to set the quantum. - errno = EINVAL; - return -1; - } - - // Set the priority class of this process to the REALTIME process class - // _if_ the policy is ACE_SCHED_FIFO. Otherwise, set to NORMAL. - if (! ::SetPriorityClass ( - ::GetCurrentProcess (), - sched_params.policy () == ACE_SCHED_FIFO - ? REALTIME_PRIORITY_CLASS - : NORMAL_PRIORITY_CLASS)) - { - return -1; - } - - // Set the thread priority on the current thread. - return ACE_OS::thr_setprio (sched_params.priority ()); - -#elif defined (VXWORKS) - // There is only one class of priorities on VxWorks, and no - // time quanta. So, just set the current thread's priority. - - if (sched_params.policy () != ACE_SCHED_FIFO || - sched_params.scope () != ACE_SCOPE_PROCESS || - sched_params.quantum () != ACE_Time_Value::zero) - { - errno = EINVAL; - return -1; - } - - // Set the thread priority on the current thread. - return ACE_OS::thr_setprio (sched_params.priority ()); - -#elif defined (CHORUS) - int result; - struct sched_param param; - ACE_thread_t thr_id = ACE_OS::thr_self (); - - param.sched_priority = sched_params.priority (); - - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id, - sched_params.policy (), - ¶m), - result), - int, -1); -#else - ACE_UNUSED_ARG (sched_params); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_STHREADS */ -} - -// = Static initialization. - -// This is necessary to deal with POSIX pthreads insanity. This -// guarantees that we've got a "zero'd" thread id even when -// ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented -// as structures... -ACE_thread_t ACE_OS::NULL_thread; -ACE_hthread_t ACE_OS::NULL_hthread; -ACE_thread_key_t ACE_OS::NULL_key; - -ACE_OS::ACE_OS (void) -{ -// ACE_TRACE ("ACE_OS::ACE_OS"); -} - -#if defined (ACE_WIN32) - -// = Static initialization. - -// Keeps track of whether we've initialized the WinSock DLL. -int ACE_OS::socket_initialized_; - -// We need this to initialize the WinSock DLL. - -BOOL WINAPI -DllMain (HINSTANCE, // DLL module handle - DWORD fdwReason, // Reason called - LPVOID) // Reserved -{ - switch (fdwReason) - { - case DLL_PROCESS_ATTACH: - if (ACE_OS::socket_init (ACE_WSOCK_VERSION) != 0) - return FALSE; - break; - - case DLL_PROCESS_DETACH: - if (ACE_OS::socket_fini () != 0) - return FALSE; - break; - - case DLL_THREAD_ATTACH: - case DLL_THREAD_DETACH: - break; - - default: - ACE_ERROR_RETURN ((LM_ERROR, - "Sock.DLL DllMain called with unknown fdwReason = %u\n.", - fdwReason), FALSE); - /* NOTREACHED */ - } - - return TRUE; -} - -#include "ace/Synch.h" -#include "ace/Set.h" - -class ACE_TSS_Ref - // = TITLE - // "Reference count" for thread-specific storage keys. - // - // = DESCRIPTION - // Since the ACE_Unbounded_Set doesn't allow duplicates, the - // "reference count" is the identify of the thread_id. -{ -public: - ACE_TSS_Ref (ACE_thread_t id); - // Constructor - - ACE_TSS_Ref (void); - // Default constructor - - int operator== (const ACE_TSS_Ref &); - // Check for equality. - -// private: - - ACE_thread_t tid_; - // ID of thread using a specific key. -}; - -ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id) - : tid_(id) -{ -// ACE_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref"); -} - -ACE_TSS_Ref::ACE_TSS_Ref (void) -{ -// ACE_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref"); -} - -// Check for equality. -int -ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) -{ -// ACE_TRACE ("ACE_TSS_Ref::operator=="); - - return this->tid_ == info.tid_; -} - -typedef ACE_Unbounded_Set<ACE_TSS_Ref> ACE_TSS_REF_TABLE; -typedef ACE_Unbounded_Set_Iterator<ACE_TSS_Ref> ACE_TSS_REF_TABLE_ITERATOR; - -class ACE_TSS_Info - // = TITLE - // Thread Specific Key management. - // - // = DESCRIPTION - // This class maps a key to a "destructor." -{ -public: - ACE_TSS_Info (ACE_thread_key_t key, - void (*dest)(void *) = 0, - void *tss_inst = 0); - // Constructor - - ACE_TSS_Info (void); - // Default constructor - - int operator== (const ACE_TSS_Info &); - // Check for equality. - - void dump (void); - // Dump the state. - -// private: - ACE_thread_key_t key_; - // Key to the thread-specific storage item. - - void (*destructor_)(void *); - // "Destructor" that gets called when the item is finally released. - - void *tss_obj_; - // Pointer to ACE_TSS<xxx> instance that has/will allocate the key. - - ACE_TSS_REF_TABLE ref_table_; - // Table of thread IDs that are using this key. -}; - -ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key, - void (*dest)(void *), - void *tss_inst) - : key_ (key), - destructor_ (dest), - tss_obj_ (tss_inst) -{ -// ACE_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); -} - -ACE_TSS_Info::ACE_TSS_Info (void) -{ -// ACE_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); -} - -// Check for equality. -int -ACE_TSS_Info::operator== (const ACE_TSS_Info &info) -{ -// ACE_TRACE ("ACE_TSS_Info::operator=="); - - return this->key_ == info.key_; -} - -void -ACE_TSS_Info::dump (void) -{ -// ACE_TRACE ("ACE_TSS_Info::dump"); - - ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, "key_ = %u", this->key_)); - ACE_DEBUG ((LM_DEBUG, "\ndestructor_ = %u", this->destructor_)); - ACE_DEBUG ((LM_DEBUG, "\ntss_obj_ = %u", this->tss_obj_)); - ACE_DEBUG ((LM_DEBUG, "\nref_table_.size_ = %u", this->ref_table_.size ())); - - ACE_TSS_Ref *tid_info = 0; - - ACE_DEBUG ((LM_DEBUG, "\nThread_usage_list\n[\n")); - - for (ACE_TSS_REF_TABLE_ITERATOR iter (this->ref_table_); - iter.next (tid_info) != 0; - iter.advance ()) - ACE_DEBUG ((LM_DEBUG, "\ntid_ = %d", tid_info->tid_)); - - ACE_DEBUG ((LM_DEBUG, "\n]\n")); - ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -} - -// Create a set of <ACE_TSS_Info> objects that will reside -// within thread-specific storage. -typedef ACE_Unbounded_Set<ACE_TSS_Info> ACE_TSS_TABLE; -typedef ACE_Unbounded_Set_Iterator<ACE_TSS_Info> ACE_TSS_TABLE_ITERATOR; - -class ACE_TSS_Cleanup - // = TITLE - // Singleton that knows how to clean up all the thread-specific - // resources for Win32. - // - // = DESCRIPTION - // All this nonsense is required since Win32 doesn't - // automatically cleanup thread-specific storage on thread exit, - // unlike real operating systems... ;-) -{ -public: - static ACE_TSS_Cleanup *instance (void); - - void exit (void *status); - // Cleanup the thread-specific objects and exit with <status>. - - int insert (ACE_thread_key_t key, void (*destructor)(void *), void *inst); - // Insert a <key, destructor> tuple into the table. - - int remove (ACE_thread_key_t key); - // Remove a <key, destructor> tuple from the table. - - int detach (void *inst); - // Detaches a tss_instance from its key. - - int detach (ACE_thread_key_t key, ACE_thread_t tid); - // Detaches a thread from the key. - - int key_used (ACE_thread_key_t key); - // Mark a key as being used by this thread. - -protected: - int mark_cleanup_i (void); - // Mark a thread for actually performing cleanup. - - int check_cleanup_i (void); - // Check if given thread is performing cleanup. - - int exit_cleanup_i (void); - // Indicate that a thread has finished cleanup. - - void dump (void); - - ACE_TSS_Cleanup (void); - // Ensure singleton. - -private: - ACE_TSS_TABLE table_; - // Table of <ACE_TSS_Info>'s. - - ACE_TSS_REF_TABLE ref_table_; - // Table of thread IDs that are performing cleanup activities. - - // = Static data. - static ACE_TSS_Cleanup *instance_; - // Pointer to the singleton instance. - -public: - static ACE_Thread_Mutex lock_; - // Serialize initialization of <key_>. -}; - -// = Static object initialization. - -// Pointer to the singleton instance. -ACE_TSS_Cleanup *ACE_TSS_Cleanup::instance_ = 0; - -// Serialize initialization of <key_>. -ACE_Thread_Mutex ACE_TSS_Cleanup::lock_; - -int -ACE_TSS_Cleanup::mark_cleanup_i (void) -{ - return this->ref_table_.insert (ACE_TSS_Ref (ACE_OS::thr_self ())); -} - -int -ACE_TSS_Cleanup::check_cleanup_i (void) -{ - return this->ref_table_.find (ACE_TSS_Ref (ACE_OS::thr_self ())); -} - -int -ACE_TSS_Cleanup::exit_cleanup_i (void) -{ - return this->ref_table_.remove (ACE_TSS_Ref (ACE_OS::thr_self ())); -} - -void -ACE_TSS_Cleanup::exit (void *status) -{ -// ACE_TRACE ("ACE_TSS_Cleanup::exit"); - - ACE_thread_key_t key_arr[TLS_MINIMUM_AVAILABLE]; - int index = 0; - - ACE_TSS_Info *key_info = 0; - ACE_TSS_Info info_arr[TLS_MINIMUM_AVAILABLE]; - int info_ix = 0; - - // While holding the lock, we only collect the ACE_TSS_Info objects - // in an array without invoking the according destructors. - - { - ACE_GUARD (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_); - - // Prevent recursive deletions - - if (this->check_cleanup_i ()) // Are we already performing cleanup? - return; - - // If we can't insert our thread_id into the list, we will not be - // able to detect recursive invocations for this thread. Therefore - // we better risk memory and key leakages, resulting also in - // missing close() calls as to be invoked recursively. - - if (this->mark_cleanup_i () != 0) // Insert our thread_id in list - return; - - // Iterate through all the thread-specific items and free them all - // up. - - for (ACE_TSS_TABLE_ITERATOR iter (this->table_); - iter.next (key_info) != 0; - iter.advance ()) - { - void *tss_info = 0; - - int val = key_info->ref_table_.remove (ACE_TSS_Ref (ACE_OS::thr_self ())); - - if ((ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0) - && (key_info->destructor_) - && tss_info) - info_arr[info_ix++] = *key_info; // copy this information into array - - if (key_info->ref_table_.size () == 0 - && key_info->tss_obj_ == 0) - key_arr[index++] = key_info->key_; - } - } - - // Now we have given up the ACE_TSS_Cleanup::lock_ and we start - // invoking destructors. - - for (int i = 0; i < info_ix; i++) - { - void *tss_info = 0; - - ACE_OS::thr_getspecific (info_arr[i].key_, &tss_info); - - (*info_arr[i].destructor_)(tss_info); - } - - // Acquiring ACE_TSS_Cleanup::lock_ to free TLS keys and remove - // entries from ACE_TSS_Info table. - { - ACE_GUARD (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_); - - for (int i = 0; i < index; i++) - { - ::TlsFree (key_arr[i]); - this->table_.remove (ACE_TSS_Info (key_arr[i])); - } - - this->exit_cleanup_i (); // remove thread id from reference list. - } - -#if defined (ACE_HAS_MFC) - // allow CWinThread-destructor to be invoked from AfxEndThread - // _endthreadex will be called from AfxEndThread so don't exit the - // thread now if we are running an MFC thread. - CWinThread *pThread = ::AfxGetThread (); - if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ()) -#endif /* ACE_HAS_MFC */ - { -#if 0 - ACE_hthread_t thr; - ACE_OS::thr_self (thr); - if (thr) - ACE_OS::close (thr); -#endif - ::_endthreadex ((DWORD) status); - } -#if 0 - ::ExitThread ((DWORD) status); -#endif - - /* NOTREACHED */ -} - -ACE_TSS_Cleanup::ACE_TSS_Cleanup (void) -{ -// ACE_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup"); -} - -ACE_TSS_Cleanup * -ACE_TSS_Cleanup::instance (void) -{ -// ACE_TRACE ("ACE_TSS_Cleanup::instance"); - - // Create and initialize thread-specific key. - if (ACE_TSS_Cleanup::instance_ == 0) - { - // Insure that we are serialized! - ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, 0); - - // Now, use the Double-Checked Locking pattern to make sure we - // only create the key once. - if (instance_ == 0) - ACE_NEW_RETURN (ACE_TSS_Cleanup::instance_, ACE_TSS_Cleanup, 0); - } - - return ACE_TSS_Cleanup::instance_; -} - -int -ACE_TSS_Cleanup::insert (ACE_thread_key_t key, - void (*destructor)(void *), - void *inst) -{ -// ACE_TRACE ("ACE_TSS_Cleanup::insert"); - ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); - - return this->table_.insert (ACE_TSS_Info (key, destructor, inst)); -} - -int -ACE_TSS_Cleanup::remove (ACE_thread_key_t key) -{ -// ACE_TRACE ("ACE_TSS_Cleanup::remove"); - ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); - - return this->table_.remove (ACE_TSS_Info (key)); -} - -int -ACE_TSS_Cleanup::detach (void *inst) -{ - ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); - - ACE_TSS_Info *key_info = 0; - int success = 0; - int ref_cnt = 0; - - for (ACE_TSS_TABLE_ITERATOR iter (this->table_); - iter.next (key_info) != 0; - iter.advance ()) - { - if (key_info->tss_obj_ == inst) - { - key_info->tss_obj_ = 0; - ref_cnt = key_info->ref_table_.size (); - success = 1; - break; - } - } - - if (success == 0) - return -1; - else if (ref_cnt == 0) - { - ::TlsFree (key_info->key_); - return this->table_.remove (ACE_TSS_Info (key_info->key_)); - } - - return 0; -} - -int -ACE_TSS_Cleanup::detach (ACE_thread_key_t key, ACE_thread_t tid) -{ - ACE_UNUSED_ARG(key); - ACE_UNUSED_ARG(tid); - - return -1; -} - -int -ACE_TSS_Cleanup::key_used (ACE_thread_key_t key) -{ - ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, ACE_TSS_Cleanup::lock_, -1); - - ACE_TSS_Info *key_info = 0; - - for (ACE_TSS_TABLE_ITERATOR iter (this->table_); - iter.next (key_info) != 0; - iter.advance ()) - if (key_info->key_ == key) - return key_info->ref_table_.insert (ACE_TSS_Ref (ACE_OS::thr_self ())); - - return -1; -} - -void -ACE_TSS_Cleanup::dump (void) -{ - ACE_TSS_Info *key_info = 0; - - // Iterate through all the thread-specific items and dump them all. - - for (ACE_TSS_TABLE_ITERATOR iter (this->table_); - iter.next (key_info) != 0; - iter.advance ()) - key_info->dump (); -} - -#endif /* WIN32 */ - -#if !defined (VXWORKS) -class ACE_Thread_Adapter - // = TITLE - // Converts a C++ function into a function <ace_thread_adapter> - // function that can be called from a thread creation routine - // (e.g., pthread_create() or _beginthreadex()) that expects an - // extern "C" entry point. - // - // = DESCRIPTION - // This is used below in <ACE_OS::thr_create> for Win32 and - // MVS. -{ -public: - ACE_Thread_Adapter (ACE_THR_FUNC f, void *a); - // Constructor. - - // private: - // = Arguments to thread startup. - ACE_THR_FUNC func_; - // Thread startup function (C++ linkage). - - void *arg_; - // Argument to thread startup function. - - ACE_Log_Msg *inherit_log_; - // TSS log data of creating thread or NULL. -}; - -// Run the thread exit point. This must be an extern "C" to make -// certain compilers happy... - -extern "C" void * -ace_thread_adapter (void *args) -{ - // ACE_TRACE ("ace_thread_adapter"); - ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args; - - ACE_THR_FUNC func = thread_args->func_; - - // Inherit the logging feature if the parent - // has got an ACE_Log_Msg. - if( thread_args->inherit_log_ ) - { - ACE_Log_Msg *inherit_log = thread_args->inherit_log_; - ACE_Log_Msg *new_log = ACE_LOG_MSG; - new_log->msg_ostream (inherit_log->msg_ostream ()); - new_log->priority_mask (inherit_log->priority_mask ()); - if (inherit_log->tracing_enabled ()) - new_log->start_tracing (); - } - void *arg = thread_args->arg_; - - delete thread_args; - -#if defined (ACE_WIN32) - void *status; - - ACE_SEH_TRY { - status = (*func) (arg); // Call thread entry point. - } - ACE_SEH_EXCEPT (EXCEPTION_EXECUTE_HANDLER) { - ACE_DEBUG ((LM_DEBUG, "(%t) Win32 structured exception exiting thread\n")); - // Here's where we might want to provide a hook to report this... - // As it stands now, we just catch all Win32 structured exceptions - // so that we can make sure to clean up correctly when the thread - // exits. - } - - // If dropped off end, call destructors for thread-specific storage - // and exit. - ACE_TSS_Cleanup::instance ()->exit (status); - /* NOTREACHED */ - return status; -#else - return (void *) (*func) (arg); // Call thread entry point. -#endif /* ACE_WIN32 */ -} - -ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC f, void *a) - : func_(f), - arg_(a), - inherit_log_ (NULL) -{ -// ACE_TRACE ("Ace_Thread_Adapter::Ace_Thread_Adapter"); - if ( ACE_Log_Msg::exists() ) - inherit_log_ = ACE_LOG_MSG; -} -#endif /* VXWORKS */ - -int -ACE_OS::thr_create (ACE_THR_FUNC func, - void *args, - long flags, - ACE_thread_t *thr_id, - ACE_hthread_t *thr_handle, - long priority, - void *stack, - size_t stacksize) -{ - // ACE_TRACE ("ACE_OS::thr_create"); - -#if defined (ACE_HAS_THREADS) - ACE_thread_t tmp_thr; - ACE_hthread_t tmp_handle; - - if (thr_id == 0) - thr_id = &tmp_thr; - - if (thr_handle == 0) - thr_handle = &tmp_handle; - -# if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) - - int result; - pthread_attr_t attr; -# if defined (ACE_HAS_SETKIND_NP) - if (::pthread_attr_create (&attr) != 0) -# else /* ACE_HAS_SETKIND_NP */ - if (::pthread_attr_init (&attr) != 0) -# endif /* ACE_HAS_SETKIND_NP */ - return -1; -# if !defined (ACE_LACKS_SETSCHED) - // The PRIORITY stuff used to be here...-cjc -# endif /* ACE_LACKS_SETSCHED */ - - - // *** Set Stack Size -# if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE) - if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE) - stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE; -# endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */ - - if (stacksize != 0) - { - size_t size = stacksize; - -# if defined (PTHREAD_STACK_MIN) - if (size < PTHREAD_STACK_MIN) - size = PTHREAD_STACK_MIN; -# endif /* PTHREAD_STACK_MIN */ - -# if !defined (ACE_LACKS_THREAD_STACK_SIZE) // JCEJ 12/17/96 - if (::pthread_attr_setstacksize (&attr, size) != 0) - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } -# endif /* !ACE_LACKS_THREAD_STACK_SIZE */ - } - - // *** Set Stack Address -# if !defined (ACE_LACKS_THREAD_STACK_ADDR) - if (stack != 0) - { - if (::pthread_attr_setstackaddr (&attr, stack) != 0) - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } - } -# endif /* !ACE_LACKS_THREAD_STACK_ADDR */ - - - - // *** Deal with various attributes - if (flags != 0) - { - // *** Set Detach state -# if !defined (ACE_LACKS_SETDETACH) - if (ACE_BIT_ENABLED (flags, THR_DETACHED) - || ACE_BIT_ENABLED (flags, THR_JOINABLE)) - { - int dstate = PTHREAD_CREATE_JOINABLE; - - if (ACE_BIT_ENABLED (flags, THR_DETACHED)) - dstate = PTHREAD_CREATE_DETACHED; - -# if defined (ACE_HAS_SETKIND_NP) - if (::pthread_attr_setdetach_np (&attr, dstate) != 0) -# else /* ACE_HAS_SETKIND_NP */ -# if defined (ACE_HAS_PTHREAD_DSTATE_PTR) - if (::pthread_attr_setdetachstate (&attr, &dstate) != 0) -# else - if (::pthread_attr_setdetachstate (&attr, dstate) != 0) -# endif /* ACE_HAS_PTHREAD_DSTATE_PTR */ -# endif /* ACE_HAS_SETKIND_NP */ - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } - } -# endif /* ACE_LACKS_SETDETACH */ - - // *** Set Policy -# if !defined (ACE_LACKS_SETSCHED) - // If we wish to set the priority explicitly, we have to enable - // explicit scheduling, and a policy, too. - if (priority != -1) - { - ACE_SET_BITS (flags, THR_EXPLICIT_SCHED); - if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO) - && ACE_BIT_DISABLED (flags, THR_SCHED_RR) - && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT)) - ACE_SET_BITS (flags, THR_SCHED_DEFAULT); - } - - if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) - || ACE_BIT_ENABLED (flags, THR_SCHED_RR) - || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) - { - int spolicy; - -# if defined (ACE_HAS_ONLY_SCHED_OTHER) - // Solaris, thru version 2.5.1, only supports SCHED_OTHER. - spolicy = SCHED_OTHER; -# else - if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) - spolicy = SCHED_OTHER; - else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) - spolicy = SCHED_FIFO; - else - spolicy = SCHED_RR; -# endif - -# if !defined (ACE_HAS_FSU_PTHREADS) -# if defined (ACE_HAS_SETKIND_NP) - result = ::pthread_attr_setsched (&attr, spolicy); -# else /* ACE_HAS_SETKIND_NP */ - result = ::pthread_attr_setschedpolicy (&attr, spolicy); -# endif /* ACE_HAS_SETKIND_NP */ - if (result != 0) - { - // Preserve the errno value. - errno = result; -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } -# else - int ret; - switch (spolicy) - { - case SCHED_FIFO: - case SCHED_RR: - ret = 0; - break; - default: - ret = 22; - break; - } - if (ret != 0) - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } -# endif /* ACE_HAS_FSU_PTHREADS */ - } - - // *** Set Priority (use reasonable default priorities) -# if defined(ACE_HAS_PTHREADS_1003_DOT_1C) - // If we wish to explicitly set a scheduling policy, we also - // have to specify a priority. We choose a "middle" priority as - // default. Maybe this is also necessary on other POSIX'ish - // implementations? - if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) - || ACE_BIT_ENABLED (flags, THR_SCHED_RR) - || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) - && priority == -1) - { - if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) - priority = ACE_THR_PRI_FIFO_DEF; - else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR)) - priority = ACE_THR_PRI_RR_DEF; - else // THR_SCHED_DEFAULT - priority = ACE_THR_PRI_OTHER_DEF; - } -# endif //ACE_HAS_PTHREADS_1003_DOT_1C - if (priority != -1) - { - struct sched_param sparam; - - ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); - -# if defined (ACE_HAS_DCETHREADS) && !defined (ACE_HAS_SETKIND_NP) - sparam.sched_priority = ACE_MIN (priority, PRIORITY_MAX); -# elif defined(ACE_HAS_IRIX62_THREADS) || defined (ACE_HAS_PTHREADS_XAVIER) - sparam.sched_priority = ACE_MIN (priority, PTHREAD_MAX_PRIORITY); -# elif defined (PTHREAD_MAX_PRIORITY) /* For MIT pthreads... */ - sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY); -# elif defined(ACE_HAS_PTHREADS_1003_DOT_1C) - // The following code forces priority into range. - if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) - sparam.sched_priority = - ACE_MIN (ACE_THR_PRI_FIFO_MAX, ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority)); - else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR)) - sparam.sched_priority = - ACE_MIN (ACE_THR_PRI_RR_MAX, ACE_MAX (ACE_THR_PRI_RR_MIN, priority)); - else // Default policy, whether set or not - sparam.sched_priority = - ACE_MIN (ACE_THR_PRI_OTHER_MAX, ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority)); -# else - sparam.sched_priority = priority; -# endif - -# if !defined (ACE_HAS_FSU_PTHREADS) - int retval = 0; -# if defined (ACE_HAS_SETKIND_NP) - retval = ::pthread_attr_setsched (&attr, SCHED_OTHER); -# else /* ACE_HAS_SETKIND_NP */ - retval = ::pthread_attr_setschedparam (&attr, &sparam); -# endif /* ACE_HAS_SETKIND_NP */ - if (retval != 0) - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - errno = retval; - return -1; - } -# else - if (sparam.sched_priority >= PTHREAD_MIN_PRIORITY - && sparam.sched_priority <= PTHREAD_MAX_PRIORITY) - attr.prio = sparam.sched_priority; - else - { - pthread_attr_destroy (&attr); - return -1; - } -# endif /* ACE_HAS_FSU_PTHREADS */ - } - - // *** Set scheduling explicit or inherited - if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED) - || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED)) - { -# if defined (ACE_HAS_SETKIND_NP) - int sched = PTHREAD_DEFAULT_SCHED; -# else /* ACE_HAS_SETKIND_NP */ - int sched = PTHREAD_EXPLICIT_SCHED; -# endif /* ACE_HAS_SETKIND_NP */ - if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)) - sched = PTHREAD_INHERIT_SCHED; - if (::pthread_attr_setinheritsched (&attr, sched) != 0) - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } - } -# endif /* ACE_LACKS_SETSCHED */ - - - // *** Set Scope -# if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING) - if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM) - || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS)) - { - int scope = PTHREAD_SCOPE_PROCESS; - if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)) - scope = PTHREAD_SCOPE_SYSTEM; - - if (::pthread_attr_setscope (&attr, scope) != 0) - { -# if defined (ACE_HAS_SETKIND_NP) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_SETKIND_NP */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ - return -1; - } - } -# endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */ - - if (ACE_BIT_ENABLED (flags, THR_NEW_LWP)) - { - // Increment the number of LWPs by one to emulate the - // Solaris semantics. - int lwps = ACE_OS::thr_getconcurrency (); - ACE_OS::thr_setconcurrency (lwps + 1); - } - } - -# if defined (ACE_HAS_SETKIND_NP) - ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id, attr, func, args), - result), - int, -1, result); - ::pthread_attr_delete (&attr); -# else /* !ACE_HAS_SETKIND_NP */ -# if defined (ACE_HAS_THR_C_FUNC) - ACE_Thread_Adapter *thread_args; - ACE_NEW_RETURN (thread_args, ACE_Thread_Adapter (func, args), -1); - - ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id, &attr, - ACE_THR_C_FUNC (&ace_thread_adapter), - thread_args), - result), - int, -1, result); -# else - ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id, &attr, func, args), - result), - int, -1, result); -# endif /* ACE_HAS_THR_C_FUNC */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_SETKIND_NP */ -# if defined (ACE_HAS_STHREADS) - // This is the Solaris implementation of pthreads, where - // ACE_thread_t and ACE_hthread_t are the same. - if (result != -1) - *thr_handle = *thr_id; -# else - *thr_handle = ACE_OS::NULL_hthread; -# endif /* ACE_HAS_STHREADS */ - return result; -# elif defined (ACE_HAS_STHREADS) - int result; - int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED); - - if (priority >= 0) - // If we need to set the priority, then we need to start the - // thread in a suspended mode. - ACE_SET_BITS (flags, THR_SUSPENDED); - - ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize, func, args, - flags, thr_id), result), - int, -1, result); - - if (result != -1) - { - if (priority >= 0) - { - // Set the priority of the new thread and then let it - // continue, but only if the user didn't start it suspended - // in the first place! - ACE_OS::thr_setprio (*thr_handle, priority); - - if (start_suspended == 0) - ACE_OS::thr_continue (*thr_handle); - } - } - return result; -# elif defined (ACE_HAS_WTHREADS) - ACE_UNUSED_ARG (stack); - ACE_Thread_Adapter *thread_args; - ACE_NEW_RETURN (thread_args, ACE_Thread_Adapter (func, args), -1); -# if defined (ACE_HAS_MFC) - if (ACE_BIT_ENABLED (flags, THR_USE_AFX)) - { - CWinThread *cwin_thread = - ::AfxBeginThread ((AFX_THREADPROC) &ace_thread_adapter, - thread_args, priority, 0, - flags | THR_SUSPENDED); - // Have to duplicate the handle because - // CWinThread::~CWinThread() closes the original handle. - (void) ::DuplicateHandle (::GetCurrentProcess (), - cwin_thread->m_hThread, - ::GetCurrentProcess (), - thr_handle, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); - - *thr_id = cwin_thread->m_nThreadID; - - if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0) - cwin_thread->ResumeThread (); - // cwin_thread will be deleted in AfxThreadExit() - // Warning: If AfxThreadExit() is called from within the - // thread, ACE_TSS_Cleanup->exit() never gets called ! - } - else -# endif /* ACE_HAS_MFC */ - { - int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED); - - if (priority >= 0) - // If we need to set the priority, then we need to start the - // thread in a suspended mode. - ACE_SET_BITS (flags, THR_SUSPENDED); - - *thr_handle = (void *) ::_beginthreadex - (NULL, - stacksize, - ACE_THR_C_FUNC (&ace_thread_adapter), - thread_args, - flags, - (unsigned int *) thr_id); - - if (priority >= 0 && *thr_handle != 0) - { - // Set the priority of the new thread and then let it - // continue, but only if the user didn't start it suspended - // in the first place! - ACE_OS::thr_setprio (*thr_handle, priority); - - if (start_suspended == 0) - ACE_OS::thr_continue (*thr_handle); - } - } -# if 0 - *thr_handle = ::CreateThread - (NULL, stacksize, - LPTHREAD_START_ROUTINE (ACE_THR_C_FUNC (ace_thread_adapter)), - thread_args, flags, thr_id); -# endif /* 0 */ - - // Close down the handle if no one wants to use it. - if (thr_handle == &tmp_handle) - ::CloseHandle (tmp_handle); - - if (*thr_handle != 0) - return 0; - else - ACE_FAIL_RETURN (-1); - /* NOTREACHED */ -# elif defined (VXWORKS) - // The call below to ::taskSpawn () causes VxWorks to assign a - // unique task name of the form: "t" + an integer, because the - // first argument is 0. - - // args must be an array of _exactly_ 10 ints. - - // The stack arg is ignored: if there's a need for it, we'd have to - // use ::taskInit ()/::taskActivate () instead of ::taskSpawn (). - - // The hard-coded arguments are what ::sp () would use. ::taskInit () - // is used instead of ::sp () so that we can set the priority, flags, - // and stacksize. (::sp () also hardcodes priority to 100, flags - // to VX_FP_TASK, and stacksize to 20,000.) stacksize should be - // an even integer. - - // If called with thr_create() defaults, use same default values as ::sp (): - if (priority == -1) priority = 100; - if (flags == 0) flags = VX_FP_TASK; // Assumes that there is a - // floating point coprocessor. - // As noted above, ::sp () hardcodes - // this, so we should be safe with it. - - if (stacksize == 0) stacksize = 20000; - - ACE_hthread_t tid = ::taskSpawn (0, priority, - (int) flags, (int) stacksize, func, - (int)args, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); - - if (tid == ERROR) - return -1; - else - { - // ::taskTcb (int tid) returns the address of the WIND_TCB - // (task control block). According to the ::taskSpawn() - // documentation, the name of the new task is stored at - // pStackBase, but is that of the current task? If so, it - // might be a bit quicker than this extraction of the tcb . . . - *thr_id = ::taskTcb (tid)->name; - *thr_handle = tid; - return 0; - } - -# endif /* ACE_HAS_STHREADS */ -#else - ACE_UNUSED_ARG (func); - ACE_UNUSED_ARG (args); - ACE_UNUSED_ARG (flags); - ACE_UNUSED_ARG (thr_id); - ACE_UNUSED_ARG (thr_handle); - ACE_UNUSED_ARG (priority); - ACE_UNUSED_ARG (stack); - ACE_UNUSED_ARG (stacksize); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_THREADS */ -} - -void -ACE_OS::thr_exit (void *status) -{ -// ACE_TRACE ("ACE_OS::thr_exit"); -#if defined (ACE_HAS_THREADS) -#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) - ::pthread_exit (status); -#elif defined (ACE_HAS_STHREADS) - ::thr_exit (status); -#elif defined (ACE_HAS_WTHREADS) - // Cleanup the thread-specific resources and exit. - ACE_TSS_Cleanup::instance ()->exit (status); -#elif defined (VXWORKS) - ACE_hthread_t tid; - ACE_OS::thr_self (tid); - - *((int *) status) = ::taskDelete (tid); -#endif /* ACE_HAS_STHREADS */ -#else - ACE_UNUSED_ARG (status); -#endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data) -{ -// ACE_TRACE ("ACE_OS::thr_setspecific"); -#if defined (ACE_HAS_THREADS) -#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) -#if defined (ACE_HAS_FSU_PTHREADS) -// Call pthread_init() here to initialize threads package. FSU -// threads need an initialization before the first thread constructor. -// This seems to be the one; however, a segmentation fault may -// indicate that another pthread_init() is necessary, perhaps in -// Synch.cpp or Synch_T.cpp. FSU threads will not reinit if called -// more than once, so another call to pthread_init will not adversely -// affect existing threads. - pthread_init (); -#endif /* ACE_HAS_FSU_PTHREADS */ - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setspecific (key, data), ace_result_), - int, -1); -#elif defined (ACE_HAS_STHREADS) - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), ace_result_), int, -1); -#elif defined (ACE_HAS_WTHREADS) - ::TlsSetValue (key, data); - ACE_TSS_Cleanup::instance ()->key_used (key); - return 0; -#elif defined (VXWORKS) - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_STHREADS */ -#else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (data); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::thr_keyfree (ACE_thread_key_t key) -{ -// ACE_TRACE ("ACE_OS::thr_keyfree"); -#if defined (ACE_HAS_THREADS) -#if defined (ACE_LACKS_KEYDELETE) - ACE_NOTSUP_RETURN (-1); -#elif defined (ACE_HAS_PTHREADS) && !defined (ACE_HAS_FSU_PTHREADS) - return ::pthread_key_delete (key); -#elif defined (ACE_HAS_DCETHREADS) - ACE_NOTSUP_RETURN (-1); -#elif defined (ACE_HAS_THR_KEYDELETE) - return ::thr_keydelete (key); -#elif defined (ACE_HAS_STHREADS) - ACE_NOTSUP_RETURN (-1); -#elif defined (ACE_HAS_WTHREADS) - // Extract out the thread-specific table instance and and free up - // the key and destructor. - ACE_TSS_Cleanup::instance ()->remove (key); - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1); -#elif defined (VXWORKS) - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_STHREADS */ -#else - ACE_UNUSED_ARG (key); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::thr_keycreate (ACE_thread_key_t *key, -#if defined (ACE_HAS_THR_C_DEST) - ACE_THR_C_DEST dest, -#else - ACE_THR_DEST dest, -#endif /* ACE_HAS_THR_C_DEST */ - void *inst) -{ -// ACE_TRACE ("ACE_OS::thr_keycreate"); - inst = inst; -#if defined (ACE_HAS_THREADS) -#if defined (ACE_HAS_DCETHREADS) || defined (ACE_HAS_PTHREADS) -#if defined (ACE_HAS_SETKIND_NP) - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_keycreate (key, dest), - ace_result_), - int, -1); -#else /* ACE_HAS_SETKIND_NP */ - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest), - ace_result_), - int, -1); -#endif /* ACE_HAS_SETKIND_NP */ -#elif defined (ACE_HAS_STHREADS) - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest), - ace_result_), - int, -1); -#elif defined (ACE_HAS_WTHREADS) - *key = ::TlsAlloc (); - - if (*key != ACE_SYSCALL_FAILED) - { - // Extract out the thread-specific table instance and stash away - // the key and destructor so that we can free it up later on... - return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst); - } - else - ACE_FAIL_RETURN (-1); - /* NOTREACHED */ - -#elif defined (VXWORKS) - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_STHREADS */ -#else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (dest); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::thr_key_used (ACE_thread_key_t key) -{ -#if defined (ACE_WIN32) - return ACE_TSS_Cleanup::instance ()->key_used (key); -#else - key = key; - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_WIN32 */ -} - -int -ACE_OS::thr_key_detach (void *inst) -{ -#if defined (ACE_WIN32) - return ACE_TSS_Cleanup::instance()->detach (inst); -#else - inst = inst; - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_WIN32 */ -} - -// Create a contiguous command-line argument buffer with each arg -// separated by spaces. - -pid_t -ACE_OS::fork_exec (char *argv[]) -{ -#if defined (ACE_WIN32) - ACE_ARGV argv_buf (argv); - - LPTSTR buf = (LPTSTR) ACE_WIDE_STRING (argv_buf.buf ()); - - if (buf != 0) - { - PROCESS_INFORMATION process_info; - STARTUPINFO startup_info; - ACE_OS::memset ((void *) &startup_info, 0, sizeof startup_info); - startup_info.cb = sizeof startup_info; - - if (::CreateProcess (NULL, - buf, - NULL, // No process attributes. - NULL, // No thread attributes. - TRUE, // Allow handle inheritance. - CREATE_NEW_CONSOLE, // Create a new console window. - NULL, // No environment. - NULL, // No current directory. - &startup_info, - &process_info)) - { - // Free resources allocated in kernel. - ACE_OS::close (process_info.hThread); - ACE_OS::close (process_info.hProcess); - // Return new process id. - return process_info.dwProcessId; - } - } - - // CreateProcess failed. - return -1; -#elif defined (CHORUS) - return -1; // do it later!!! -#else - pid_t result = ACE_OS::fork (); - - switch (result) - { - case -1: - // Error. - return -1; - case 0: - // Child process. - if (ACE_OS::execv (argv[0], argv) == -1) - { - ACE_ERROR ((LM_ERROR, "%p Exec failed\n")); - - // If the execv fails, this child needs to exit. - ACE_OS::exit (errno); - } - default: - // Server process. The fork succeeded. - return result; - } -#endif /* ACE_WIN32 */ - } - -#if defined (ACE_NEEDS_WRITEV) - -// "Fake" writev for sites without it. Note that this is thread-safe. - -extern "C" int -writev (ACE_HANDLE handle, ACE_WRITEV_TYPE iov[], int n) -{ -// ACE_TRACE ("::writev"); - - size_t length = 0; - int i; - - // Determine the total length of all the buffers in <iov>. - for (i = 0; i < n; i++) - if (iov[i].iov_len < 0) - return -1; - else - length += iov[i].iov_len; - - char *buf; - -#if defined (ACE_HAS_ALLOCA) - buf = (char *) alloca (length); -#else - ACE_NEW_RETURN (buf, char[length], -1); -#endif /* !defined (ACE_HAS_ALLOCA) */ - - char *ptr = buf; - - for (i = 0; i < n; i++) - { - ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len); - ptr += iov[i].iov_len; - } - - ssize_t result = ACE::send_n (handle, buf, length); -#if !defined (ACE_HAS_ALLOCA) - delete [] buf; -#endif /* !defined (ACE_HAS_ALLOCA) */ - return result; -} -#endif /* ACE_NEEDS_WRITEV */ - -#if defined (ACE_NEEDS_READV) - -// "Fake" readv for sites without it. Note that this is thread-safe. - -extern "C" int -readv (ACE_HANDLE handle, struct iovec *iov, int n) -{ -// ACE_TRACE ("::readv"); - - ssize_t length = 0; - int i; - - for (i = 0; i < n; i++) - if (iov[i].iov_len < 0) - return -1; - else - length += iov[i].iov_len; - - char *buf; -#if defined (ACE_HAS_ALLOCA) - buf = (char *) alloca (length); -#else - ACE_NEW_RETURN (buf, char[length], -1); -#endif /* !defined (ACE_HAS_ALLOCA) */ - - length = ACE::recv_n (handle, buf, length); - - if (length != -1) - { - char *ptr = buf; - int copyn = length; - - for (i = 0; - i < n && copyn > 0; - i++) - { - ACE_OS::memcpy (iov[i].iov_base, ptr, - // iov_len is int on some platforms, size_t on others - copyn > (int) iov[i].iov_len - ? (size_t) iov[i].iov_len - : (size_t) copyn); - ptr += iov[i].iov_len; - copyn -= iov[i].iov_len; - } - } - -#if !defined (ACE_HAS_ALLOCA) - delete [] buf; -#endif /* !defined (ACE_HAS_ALLOCA) */ - return length; -} -#endif /* ACE_NEEDS_READV */ - -#if defined (ACE_NEEDS_FTRUNCATE) -extern "C" int -ftruncate (ACE_HANDLE handle, long len) -{ - struct flock fl; - fl.l_whence = 0; - fl.l_len = 0; - fl.l_start = len; - fl.l_type = F_WRLCK; - - return ::fcntl (handle, F_FREESP, &fl); -} -#endif /* ACE_NEEDS_FTRUNCATE */ - -char * -ACE_OS::mktemp (char *s) -{ - // ACE_TRACE ("ACE_OS::mktemp"); -#if defined (ACE_LACKS_MKTEMP) - if (s == 0) - // check for null template string failed! - return 0; - else - { - char *xxxxxx = ACE_OS::strstr (s, "XXXXXX"); - - if (xxxxxx == 0) - // the template string doesn't contain "XXXXXX"! - return s; - else - { - char unique_letter = 'a'; - struct stat sb; - - // Find an unused filename for this process. It is assumed - // that the user will open the file immediately after - // getting this filename back (so, yes, there is a race - // condition if multiple threads in a process use the same - // template). This appears to match the behavior of the - // Solaris 2.5 mktemp(). - ACE_OS::sprintf (xxxxxx, "%05d%c", getpid (), unique_letter); - while (::stat (s, &sb) >= 0) - { - if (++unique_letter <= 'z') - ACE_OS::sprintf (xxxxxx, "%05d%c", getpid (), unique_letter); - else - { - // maximum of 26 unique files per template, per process - ACE_OS::sprintf (xxxxxx, "%s", ""); - return s; - } - } - } - return s; - } - -#else - return ::mktemp (s); -#endif /* ACE_LACKS_MKTEMP */ -} - -int -ACE_OS::socket_init (int version_high, int version_low) -{ -#if defined (ACE_WIN32) - if (ACE_OS::socket_initialized_ == 0) - { - WORD version_requested = MAKEWORD (version_high, version_low); - WSADATA wsa_data; - int error = ::WSAStartup (version_requested, &wsa_data); - - if (error != 0) - ACE_ERROR_RETURN ((LM_ERROR, - "WSAStartup failed, WSAGetLastError returned %u.\n", - error), -1); - - ACE_OS::socket_initialized_ = 1; - } -#else - version_high = version_high; - version_low = version_low; -#endif /* ACE_WIN32 */ - return 0; -} - -int -ACE_OS::socket_fini (void) -{ -#if defined (ACE_WIN32) - if (ACE_OS::socket_initialized_ != 0) - { - if (::WSACleanup () != 0) - { - int error = ::WSAGetLastError (); - ACE_ERROR_RETURN ((LM_ERROR, - "WSACleanup failed, WSAGetLastError returned %u.\n", - error), -1); - } - ACE_OS::socket_initialized_ = 0; - } -#endif /* ACE_WIN32 */ - return 0; -} - -#if defined (ACE_LACKS_SYS_NERR) -int sys_nerr = ERRMAX + 1; -#endif /* ACE_LACKS_SYS_NERR */ - -#if defined (VXWORKS) -#include /**/ <usrLib.h> /* for ::sp() */ - -// This global function can be used from the VxWorks shell to pass -// arguments to a C main () function. usage: -> spa main, "arg1", -// "arg2" All arguments must be quoted, even numbers. -int -spa (FUNCPTR entry, ...) -{ - static const unsigned int MAX_ARGS = 10; - static char *argv[MAX_ARGS]; - va_list pvar; - int argc; - - // Hardcode a program name because the real one isn't available - // through the VxWorks shell. - argv[0] = "spa ():t"; - - // Peel off arguments to spa () and put into argv. va_arg () isn't - // necessarily supposed to return 0 when done, though since the - // VxWorks shell uses a fixed number (10) of arguments, it might 0 - // the unused ones. This function could be used to increase that - // limit, but then it couldn't depend on the trailing 0. So, the - // number of arguments would have to be passed. - va_start (pvar, entry); - - for (argc = 1; argc <= MAX_ARGS; ++argc) - { - argv[argc] = va_arg (pvar, char *); - - if (argv[argc] == 0) - break; - } - - if (argc > MAX_ARGS && argv[argc-1] != 0) - { - // try to read another arg, and warn user if the limit was exceeded - if (va_arg (pvar, char *) != 0) - fprintf (stderr, "spa(): number of arguments limited to %d\n", - MAX_ARGS); - } - else - { - // fill unused argv slots with 0 to get rid of leftovers - // from previous invocations - for (int i = argc; i <= MAX_ARGS; ++i) - argv[i] = 0; - } - - int ret = ::sp (entry, argc, (int) argv, 0, 0, 0, 0, 0, 0, 0); - va_end (pvar); - - // ::sp () returns the taskID on success: return 0 instead if - // successful - return ret > 0 ? 0 : ret; -} -#endif /* VXWORKS */ - -#if !defined (ACE_HAS_SIGINFO_T) -siginfo_t::siginfo_t (ACE_HANDLE handle) - : si_handle_ (handle), - si_handles_ (&handle) -{ -} - -siginfo_t::siginfo_t (ACE_HANDLE *handles) - : si_handle_ (handles[0]), - si_handles_ (handles) -{ -} -#endif /* ACE_HAS_SIGINFO_T */ - -pid_t -ACE_OS::fork (const char *program_name) -{ - // ACE_TRACE ("ACE_OS::fork"); -#if defined (ACE_LACKS_EXEC) - ACE_UNUSED_ARG (program_name); - ACE_NOTSUP_RETURN (pid_t (-1)); -#else - pid_t pid = ::fork (); - - if (pid == 0) - ACE_LOG_MSG->sync (program_name); - - return pid; -#endif /* ACE_WIN32 */ -} - -// This is necessary to work around nasty problems with MVS C++. - -extern "C" void -ace_mutex_lock_cleanup_adapter (void *args) -{ - ACE_OS::mutex_lock_cleanup (args); -} - -ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id, - ACE_hthread_t thread_handle) - : thread_id_ (thread_id), - thread_handle_ (thread_handle) -{ -} - -ACE_thread_t -ACE_Thread_ID::id (void) -{ - return this->thread_id_; -} - -void -ACE_Thread_ID::id (ACE_thread_t thread_id) -{ - this->thread_id_ = thread_id; -} - -ACE_hthread_t -ACE_Thread_ID::handle (void) -{ - return this->thread_handle_; -} - -void -ACE_Thread_ID::handle (ACE_hthread_t thread_handle) -{ - this->thread_handle_ = thread_handle; -} - -int -ACE_Thread_ID::operator == (const ACE_Thread_ID &rhs) -{ - return ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_) == 0 - && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_) == 0; -} - -int -ACE_Thread_ID::operator != (const ACE_Thread_ID &rhs) -{ - return !(*this == rhs); -} - -int -ACE_OS::inet_aton (const char *host_name, struct in_addr *addr) -{ - long ip_addr = ACE_OS::inet_addr (host_name); - if (ip_addr == (long) htonl ((ACE_UINT32) ~0) - // Broadcast addresses are weird... - && ACE_OS::strcmp (host_name, "255.255.255.255") != 0) - return 0; - else if (addr != 0) - { - ACE_OS::memcpy ((void *) addr, (void *) &ip_addr, sizeof ip_addr); - return 1; - } - else - return 1; -} - |