diff options
Diffstat (limited to 'ace/OS.cpp')
-rw-r--r-- | ace/OS.cpp | 7231 |
1 files changed, 0 insertions, 7231 deletions
diff --git a/ace/OS.cpp b/ace/OS.cpp deleted file mode 100644 index e20f99abb76..00000000000 --- a/ace/OS.cpp +++ /dev/null @@ -1,7231 +0,0 @@ -// $Id$ - -#include "ace/OS.h" -#include "ace/Sched_Params.h" - -#include "ace/Log_Msg.h" // @@ Should go away! - -// 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 */ - -ACE_RCSID(ace, OS, "$Id$") - -#if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) -# if defined (ACE_HAS_WINCE) -const wchar_t *ACE_OS::day_of_week_name[] = {ACE_TEXT ("Sun"), ACE_TEXT ("Mon"), - ACE_TEXT ("Tue"), ACE_TEXT ("Wed"), - ACE_TEXT ("Thr"), ACE_TEXT ("Fri"), - ACE_TEXT ("Sat")}; -const wchar_t *ACE_OS::month_name[] = {ACE_TEXT ("Jan"), ACE_TEXT ("Feb"), - ACE_TEXT ("Mar"), ACE_TEXT ("Apr"), - ACE_TEXT ("May"), ACE_TEXT ("Jun"), - ACE_TEXT ("Jul"), ACE_TEXT ("Aug"), - ACE_TEXT ("Sep"), ACE_TEXT ("Oct"), - ACE_TEXT ("Nov"), ACE_TEXT ("Dec") }; - -static const ACE_TCHAR *ACE_OS_CTIME_R_FMTSTR = ACE_TEXT ("%3s %3s %02d %02d:%02d:%02d %04d\n"); -# endif /* ACE_HAS_WINCE */ - -# if defined (ACE_WIN32) -OSVERSIONINFO ACE_OS::win32_versioninfo_; -// Cached win32 version information. -# endif /* ACE_WIN32 */ - -class ACE_OS_Thread_Mutex_Guard -{ - // = TITLE - // This data structure is meant to be used within an ACE_OS - // function. It performs automatic aquisition and release of - // an ACE_thread_mutex_t. - // - // = DESCRIPTION - // For internal use only by ACE_OS. -public: - ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m); - // Implicitly and automatically acquire the lock. - - ~ACE_OS_Thread_Mutex_Guard (void); - // Implicitly release the lock. - - int acquire (void); - // Explicitly acquire the lock. - - int release (void); - // Explicitly release the lock. - -protected: - ACE_thread_mutex_t &lock_; - // Reference to the mutex. - - int owner_; - // Keeps track of whether we acquired the lock or failed. - - // = Prevent assignment and initialization. - ACE_OS_Thread_Mutex_Guard &operator= (const ACE_OS_Thread_Mutex_Guard &); - ACE_OS_Thread_Mutex_Guard (const ACE_OS_Thread_Mutex_Guard &); -}; - -#if defined (ACE_IS_SPLITTING) -# define ACE_SPECIAL_INLINE -#else -# define ACE_SPECIAL_INLINE inline -#endif - -ACE_SPECIAL_INLINE -int -ACE_OS_Thread_Mutex_Guard::acquire (void) -{ - return owner_ = ACE_OS::thread_mutex_lock (&lock_); -} - -ACE_SPECIAL_INLINE -int -ACE_OS_Thread_Mutex_Guard::release (void) -{ - if (owner_ == -1) - return 0; - else - { - owner_ = -1; - return ACE_OS::thread_mutex_unlock (&lock_); - } -} - -ACE_SPECIAL_INLINE -ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m) - : lock_ (m) -{ - acquire (); -} - -ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard () -{ - release (); -} - -class ACE_OS_Recursive_Thread_Mutex_Guard -{ - // = TITLE - // This data structure is meant to be used within an ACE_OS - // function. It performs automatic aquisition and release of - // an ACE_recursive_thread_mutex_t. - // - // = DESCRIPTION - // For internal use only by ACE_OS. -public: - ACE_OS_Recursive_Thread_Mutex_Guard (ACE_recursive_thread_mutex_t &m); - // Implicitly and automatically acquire the lock. - - ~ACE_OS_Recursive_Thread_Mutex_Guard (void); - // Implicitly release the lock. - - int acquire (void); - // Explicitly acquire the lock. - - int release (void); - // Explicitly release the lock. - -protected: - ACE_recursive_thread_mutex_t &lock_; - // Reference to the mutex. - - int owner_; - // Keeps track of whether we acquired the lock or failed. - - // = Prevent assignment and initialization. - ACE_OS_Recursive_Thread_Mutex_Guard &operator= ( - const ACE_OS_Recursive_Thread_Mutex_Guard &); - ACE_OS_Recursive_Thread_Mutex_Guard ( - const ACE_OS_Recursive_Thread_Mutex_Guard &); -}; - -ACE_SPECIAL_INLINE -int -ACE_OS_Recursive_Thread_Mutex_Guard::acquire (void) -{ - return owner_ = ACE_OS::recursive_mutex_lock (&lock_); -} - -ACE_SPECIAL_INLINE -int -ACE_OS_Recursive_Thread_Mutex_Guard::release (void) -{ - if (owner_ == -1) - return 0; - else - { - owner_ = -1; - return ACE_OS::recursive_mutex_unlock (&lock_); - } -} - -ACE_SPECIAL_INLINE -ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard ( - ACE_recursive_thread_mutex_t &m) - : lock_ (m), - owner_ (-1) -{ - acquire (); -} - -ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard () -{ - release (); -} - -#define ACE_OS_GUARD \ - ACE_OS_Thread_Mutex_Guard (*(ACE_thread_mutex_t *) \ - ACE_OS_Object_Manager::preallocated_object[ \ - ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]); - -#define ACE_TSS_CLEANUP_GUARD \ - ACE_OS_Recursive_Thread_Mutex_Guard (*(ACE_recursive_thread_mutex_t *) \ - ACE_OS_Object_Manager::preallocated_object[ \ - ACE_OS_Object_Manager::ACE_TSS_CLEANUP_LOCK]); - -#define ACE_TSS_BASE_GUARD \ - ACE_OS_Recursive_Thread_Mutex_Guard (*(ACE_recursive_thread_mutex_t *) \ - ACE_OS_Object_Manager::preallocated_object[ \ - ACE_OS_Object_Manager::ACE_TSS_BASE_LOCK]); - - -# if defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) -int -ACE_OS::netdb_acquire (void) -{ - return ACE_OS::thread_mutex_lock ((ACE_thread_mutex_t *) - ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]); -} - -int -ACE_OS::netdb_release (void) -{ - return ACE_OS::thread_mutex_unlock ((ACE_thread_mutex_t *) - ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]); -} -# endif /* defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */ -#else /* ! ACE_MT_SAFE */ -# define ACE_OS_GUARD -# define ACE_TSS_CLEANUP_GUARD -# define ACE_TSS_BASE_GUARD -#endif /* ! ACE_MT_SAFE */ - -ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0; -ACE_INIT_LOG_MSG_HOOK ACE_Thread_Adapter::init_log_msg_hook_ = 0; -ACE_INHERIT_LOG_MSG_HOOK ACE_Thread_Adapter::inherit_log_msg_hook_ = 0; - -u_int ACE_Thread_Exit::is_constructed_ = 0; - -// Static constant representing `zero-time'. -// Note: this object requires static construction. -const ACE_Time_Value ACE_Time_Value::zero; - -// Constant for maximum time representable. Note that this time -// is not intended for use with select () or other calls that may -// have *their own* implementation-specific maximum time representations. -// Its primary use is in time computations such as those used by the -// dynamic subpriority strategies in the ACE_Dynamic_Message_Queue class. -// Note: this object requires static construction. -const ACE_Time_Value ACE_Time_Value::max_time (LONG_MAX, - ACE_ONE_SECOND_IN_USECS - 1); - -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 - -// Static constant to remove time skew between FILETIME and POSIX -// time. -// -// In the beginning (Jan. 1, 1601), there was no time and no computer. -// And Bill said: "Let there be time," and there was time.... -const DWORDLONG ACE_Time_Value::FILETIME_to_timval_skew = -ACE_INT64_LITERAL (0x19db1ded53e8000); - -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 - ULARGE_INTEGER _100ns = - { - file_time.dwLowDateTime, - file_time.dwHighDateTime - }; - _100ns.QuadPart -= ACE_Time_Value::FILETIME_to_timval_skew; - - // Convert 100ns units to seconds; - this->tv_.tv_sec = (long) (_100ns.QuadPart / (10000 * 1000)); - // Convert remainder to microseconds; - this->tv_.tv_usec = (long) ((_100ns.QuadPart % (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"); - ULARGE_INTEGER _100ns; - _100ns.QuadPart = (((DWORDLONG) this->tv_.tv_sec * (10000 * 1000) + - this->tv_.tv_usec * 10) + - ACE_Time_Value::FILETIME_to_timval_skew); - FILETIME file_time; - - file_time.dwLowDateTime = _100ns.LowPart; - file_time.dwHighDateTime = _100ns.HighPart; - - return file_time; -} - -#endif /* ACE_WIN32 */ - -ACE_Cleanup_Info::ACE_Cleanup_Info (void) - : object_ (0), - cleanup_hook_ (0), - param_ (0) -{ -} - -int -ACE_Cleanup_Info::operator== (const ACE_Cleanup_Info &o) const -{ - return o.object_ == this->object_ - && o.cleanup_hook_ == this->cleanup_hook_ - && o.param_ == this->param_; -} - -int -ACE_Cleanup_Info::operator!= (const ACE_Cleanup_Info &o) const -{ - return !(*this == o); -} - -class ACE_Cleanup_Info_Node -{ - // = TITLE - // For maintaining a list of ACE_Cleanup_Info items. - // - // = DESCRIPTION - // For internal use by ACE_Object_Manager. -public: - ACE_Cleanup_Info_Node (void); - ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info, - ACE_Cleanup_Info_Node *next); - ~ACE_Cleanup_Info_Node (void); - ACE_Cleanup_Info_Node *insert (const ACE_Cleanup_Info &); -private: - ACE_Cleanup_Info cleanup_info_; - ACE_Cleanup_Info_Node *next_; - - friend class ACE_OS_Exit_Info; -}; - -ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (void) - : cleanup_info_ (), - next_ (0) -{ -} - -ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info, - ACE_Cleanup_Info_Node *next) - : cleanup_info_ (new_info), - next_ (next) -{ -} - -ACE_Cleanup_Info_Node::~ACE_Cleanup_Info_Node (void) -{ - delete next_; -} - -ACE_Cleanup_Info_Node * -ACE_Cleanup_Info_Node::insert (const ACE_Cleanup_Info &new_info) -{ - ACE_Cleanup_Info_Node *new_node; - - ACE_NEW_RETURN (new_node, - ACE_Cleanup_Info_Node (new_info, this), - 0); - - return new_node; -} - -ACE_OS_Exit_Info::ACE_OS_Exit_Info (void) -{ - ACE_NEW (registered_objects_, ACE_Cleanup_Info_Node); -} - -ACE_OS_Exit_Info::~ACE_OS_Exit_Info (void) -{ - delete registered_objects_; - registered_objects_ = 0; -} - -int -ACE_OS_Exit_Info::at_exit_i (void *object, - ACE_CLEANUP_FUNC cleanup_hook, - void *param) -{ - ACE_Cleanup_Info new_info; - new_info.object_ = object; - new_info.cleanup_hook_ = cleanup_hook; - new_info.param_ = param; - - // Return -1 and sets errno if unable to allocate storage. Enqueue - // at the head and dequeue from the head to get LIFO ordering. - - ACE_Cleanup_Info_Node *new_node; - - if ((new_node = registered_objects_->insert (new_info)) == 0) - return -1; - else - { - registered_objects_ = new_node; - return 0; - } -} - -int -ACE_OS_Exit_Info::find (void *object) -{ - // Check for already in queue, and return 1 if so. - for (ACE_Cleanup_Info_Node *iter = registered_objects_; - iter && iter->next_ != 0; - iter = iter->next_) - { - if (iter->cleanup_info_.object_ == object) - { - // The object has already been registered. - return 1; - } - } - - return 0; -} - -void -ACE_OS_Exit_Info::call_hooks () -{ - // Call all registered cleanup hooks, in reverse order of - // registration. - for (ACE_Cleanup_Info_Node *iter = registered_objects_; - iter && iter->next_ != 0; - iter = iter->next_) - { - ACE_Cleanup_Info &info = iter->cleanup_info_; - if (info.cleanup_hook_ == ACE_reinterpret_cast (ACE_CLEANUP_FUNC, - ace_cleanup_destroyer)) - // The object is an ACE_Cleanup. - ace_cleanup_destroyer (ACE_reinterpret_cast (ACE_Cleanup *, - info.object_), - info.param_); - else if (info.object_ == &ace_exit_hook_marker) - // The hook is an ACE_EXIT_HOOK. - (* ACE_reinterpret_cast (ACE_EXIT_HOOK, info.cleanup_hook_)) (); - else - (*info.cleanup_hook_) (info.object_, info.param_); - } -} - -void -ACE_Time_Value::dump (void) const -{ - ACE_TRACE ("ACE_Time_Value::dump"); - ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntv_sec_ = %d"), this->tv_.tv_sec)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\ntv_usec_ = %d\n"), this->tv_.tv_usec)); - ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -} - -void -ACE_Time_Value::normalize (void) -{ - // ACE_TRACE ("ACE_Time_Value::normalize"); - // New code from Hans Rohnert... - - if (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS) - { - do - { - this->tv_.tv_sec++; - this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS; - } - while (this->tv_.tv_usec >= ACE_ONE_SECOND_IN_USECS); - } - else if (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS) - { - do - { - this->tv_.tv_sec--; - this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS; - } - while (this->tv_.tv_usec <= -ACE_ONE_SECOND_IN_USECS); - } - - if (this->tv_.tv_sec >= 1 && this->tv_.tv_usec < 0) - { - this->tv_.tv_sec--; - this->tv_.tv_usec += ACE_ONE_SECOND_IN_USECS; - } - else if (this->tv_.tv_sec < 0 && this->tv_.tv_usec > 0) - { - this->tv_.tv_sec++; - this->tv_.tv_usec -= ACE_ONE_SECOND_IN_USECS; - } -} - -ACE_Countdown_Time::ACE_Countdown_Time (ACE_Time_Value *max_wait_time) - : max_wait_time_ (max_wait_time), - stopped_ (0) -{ - this->start (); -} - -ACE_Countdown_Time::~ACE_Countdown_Time (void) -{ - this->stop (); -} - -#if defined (ACE_HAS_POWERPC_TIMER) && 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)"); -} -#elif defined (ACE_HAS_POWERPC_TIMER) && defined (__GNUG__) -void -ACE_OS::readPPCTimeBase (u_long &most, u_long &least) -{ - ACE_TRACE ("ACE_OS::readPPCTimeBase"); - - // This function can't be inline because it defines a symbol, - // aclock. If there are multiple calls to the function in a - // compilation unit, then that symbol would be multiply defined if - // the function was inline. - asm volatile ("aclock:\n" - "mftbu 5\n" /* upper time base register */ - "mftb 6\n" /* lower time base register */ - "mftbu 7\n" /* upper time base register */ - "cmpw 5,7\n" /* check for rollover of upper */ - "bne aclock\n" - "stw 5,%0\n" /* most */ - "stw 6,%1" /* least */ - : "=m" (most), "=m" (least) /* outputs */ - : /* no inputs */ - : "5", "6", "7", "memory" /* constraints */); -} -#endif /* ACE_HAS_POWERPC_TIMER && (ghs or __GNUG__) */ - -#if defined (ACE_WIN32) || defined (VXWORKS) || defined (CHORUS) || defined (ACE_PSOS) -// 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; - ACE_OS::strcpy (name->sysname, - ACE_TEXT ("Win32")); - - OSVERSIONINFO vinfo; - vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - ::GetVersionEx (&vinfo); - - SYSTEM_INFO sinfo; -# if defined (ACE_HAS_PHARLAP) - // PharLap doesn't do GetSystemInfo. What's really wanted is the CPU - // architecture, so we can get that with EtsGetSystemInfo. Fill in what's - // wanted in the SYSTEM_INFO structure, and carry on. Note that the - // CPU type values in EK_KERNELINFO have the same values are the ones - // defined for SYSTEM_INFO. - EK_KERNELINFO ets_kern; - EK_SYSTEMINFO ets_sys; - EtsGetSystemInfo (&ets_kern, &ets_sys); - sinfo.wProcessorLevel = ACE_static_cast (WORD, ets_kern.CpuType); - sinfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; - sinfo.dwProcessorType = ets_kern.CpuType * 100 + 86; -# else - ::GetSystemInfo(&sinfo); - - ACE_OS::strcpy (name->sysname, ACE_TEXT ("Win32")); -# endif /* ACE_HAS_PHARLAP */ - - if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT) - { - // Get information from the two structures - ACE_OS::sprintf (name->release, -# if defined (ACE_HAS_WINCE) - ACE_TEXT ("Windows CE %d.%d"), -# else - ACE_TEXT ("Windows NT %d.%d"), -# endif /* ACE_HAS_WINCE */ - vinfo.dwMajorVersion, - vinfo.dwMinorVersion); - ACE_OS::sprintf (name->version, - ACE_TEXT ("Build %d %s"), - vinfo.dwBuildNumber, - vinfo.szCSDVersion); - - // We have to make sure that the size of (processor + subtype) is - // not greater than the size of name->machine. So we give half - // the space to the processor and half the space to subtype. The - // -1 is necessary for because of the space between processor and - // subtype in the machine name. - const int bufsize = ((sizeof (name->machine) / sizeof (ACE_TCHAR)) / 2) - 1; - ACE_TCHAR processor[bufsize] = ACE_TEXT ("Unknown"); - ACE_TCHAR subtype[bufsize] = ACE_TEXT ("Unknown"); - - WORD arch = sinfo.wProcessorArchitecture; - - switch (arch) - { - case PROCESSOR_ARCHITECTURE_INTEL: - ACE_OS::strcpy (processor, ACE_TEXT ("Intel")); - if (sinfo.wProcessorLevel == 3) - ACE_OS::strcpy (subtype, ACE_TEXT ("80386")); - else if (sinfo.wProcessorLevel == 4) - ACE_OS::strcpy (subtype, ACE_TEXT ("80486")); - else if (sinfo.wProcessorLevel == 5) - ACE_OS::strcpy (subtype, ACE_TEXT ("Pentium")); - else if (sinfo.wProcessorLevel == 6) - ACE_OS::strcpy (subtype, ACE_TEXT ("Pentium Pro")); - else if (sinfo.wProcessorLevel == 7) // I'm guessing here - ACE_OS::strcpy (subtype, ACE_TEXT ("Pentium II")); - break; - case PROCESSOR_ARCHITECTURE_MIPS: - ACE_OS::strcpy (processor, ACE_TEXT ("MIPS")); - ACE_OS::strcpy (subtype, ACE_TEXT ("R4000")); - break; - case PROCESSOR_ARCHITECTURE_ALPHA: - ACE_OS::strcpy (processor, ACE_TEXT ("Alpha")); - ACE_OS::sprintf (subtype, ACE_TEXT ("%d"), sinfo.wProcessorLevel); - break; - case PROCESSOR_ARCHITECTURE_PPC: - ACE_OS::strcpy (processor, ACE_TEXT ("PPC")); - if (sinfo.wProcessorLevel == 1) - ACE_OS::strcpy (subtype, ACE_TEXT ("601")); - else if (sinfo.wProcessorLevel == 3) - ACE_OS::strcpy (subtype, ACE_TEXT ("603")); - else if (sinfo.wProcessorLevel == 4) - ACE_OS::strcpy (subtype, ACE_TEXT ("604")); - else if (sinfo.wProcessorLevel == 6) - ACE_OS::strcpy (subtype, ACE_TEXT ("603+")); - else if (sinfo.wProcessorLevel == 9) - ACE_OS::strcpy (subtype, ACE_TEXT ("804+")); - else if (sinfo.wProcessorLevel == 20) - ACE_OS::strcpy (subtype, ACE_TEXT ("620")); - break; - case PROCESSOR_ARCHITECTURE_UNKNOWN: - default: - // @@ We could provide WinCE specific info here. But let's - // defer that to some later point. - ACE_OS::strcpy (processor, ACE_TEXT ("Unknown")); - break; - } - ACE_OS::sprintf(name->machine, ACE_TEXT ("%s %s"), processor, subtype); - } - else if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) - { - // Get Windows 95 Information - ACE_OS::strcpy (name->release, ACE_TEXT ("Windows 95")); - ACE_OS::sprintf (name->version, ACE_TEXT ("%d"), LOWORD (vinfo.dwBuildNumber)); - if (sinfo.dwProcessorType == PROCESSOR_INTEL_386) - ACE_OS::strcpy (name->machine, ACE_TEXT ("Intel 80386")); - else if (sinfo.dwProcessorType == PROCESSOR_INTEL_486) - ACE_OS::strcpy (name->machine, ACE_TEXT ("Intel 80486")); - else if (sinfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM) - ACE_OS::strcpy (name->machine, ACE_TEXT ("Intel Pentium")); - } - else - { - // We don't know what this is! - - ACE_OS::strcpy (name->release, ACE_TEXT ("???")); - ACE_OS::strcpy (name->version, ACE_TEXT ("???")); - ACE_OS::strcpy (name->machine, ACE_TEXT ("???")); - } - - return ACE_OS::hostname (name->nodename, maxnamelen); -# elif defined (VXWORKS) - size_t maxnamelen = sizeof name->nodename; - ACE_OS::strcpy (name->sysname, "VxWorks"); - ACE_OS::strcpy (name->release, "???"); - ACE_OS::strcpy (name->version, sysBspRev ()); - ACE_OS::strcpy (name->machine, sysModel ()); - - return ACE_OS::hostname (name->nodename, maxnamelen); -# elif defined (CHORUS) - size_t maxnamelen = sizeof name->nodename; - ACE_OS::strcpy (name->sysname, "CHORUS/ClassiX"); - ACE_OS::strcpy (name->release, "???"); - ACE_OS::strcpy (name->version, "???"); - ACE_OS::strcpy (name->machine, "???"); - - return ACE_OS::hostname (name->nodename, maxnamelen); -#elif defined (ACE_PSOS) - const unsigned long buflen(64); - char buf[buflen]; - unsigned long len; - sys_info(PSOS_VERSION,(void *)buf,buflen,&len); - ACE_OS::strcpy (name->sysname, "pSOS"); - ACE_OS::strcpy (name->release, "???"); - ACE_OS::strcpy (name->version, buf); - ACE_OS::strcpy (name->machine, "PPC 405"); // a bit of a hack - -#endif /* ACE_WIN32 */ -} -#endif /* ACE_WIN32 || VXWORKS */ - - -#if defined (VXWORKS) -struct hostent * -ACE_OS::gethostbyname (const char *name) -{ - ACE_TRACE ("ACE_OS::gethostbyname"); - - // not thread safe! - static hostent ret; - static int first_addr; - static char *hostaddr[2]; - static char *aliases[1]; - - ACE_OSCALL (::hostGetByName ((char *) name), int, -1, first_addr); - if (first_addr == -1) - return 0; - - hostaddr[0] = (char *) &first_addr; - hostaddr[1] = 0; - aliases[0] = 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; - ret.h_aliases = aliases; - - return &ret; -} - -struct hostent * -ACE_OS::gethostbyaddr (const char *addr, int length, int type) -{ - ACE_TRACE ("ACE_OS::gethostbyaddr"); - - if (length != 4 || type != AF_INET) - { - errno = EINVAL; - return 0; - } - - // not thread safe! - static hostent ret; - static char name [MAXNAMELEN + 1]; - static char *hostaddr[2]; - static char *aliases[1]; - - if (::hostGetByAddr (*(int *) addr, name) != 0) - { - // errno will have been set to S_hostLib_UNKNOWN_HOST. - return 0; - } - - // Might not be official: just echo input arg. - hostaddr[0] = (char *) addr; - hostaddr[1] = 0; - aliases[0] = 0; - - ret.h_name = 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; - ret.h_aliases = aliases; - - return &ret; -} - -struct hostent * -ACE_OS::gethostbyaddr_r (const char *addr, int length, int type, - hostent *result, ACE_HOSTENT_DATA buffer, - int *h_errnop) -{ - ACE_TRACE ("ACE_OS::gethostbyaddr_r"); - if (length != 4 || type != AF_INET) - { - errno = EINVAL; - return 0; - } - - if (ACE_OS::netdb_acquire ()) - return 0; - else - { - // buffer layout: - // buffer[0-3]: h_addr_list[0], the first (and only) addr. - // buffer[4-7]: h_addr_list[1], the null terminator for the h_addr_list. - // buffer[8]: the name of the host, null terminated. - - // Call ::hostGetByAddr (), which puts the (one) hostname into - // buffer. - if (::hostGetByAddr (*(int *) addr, &buffer[8]) == 0) - { - // Store the return values in result. - result->h_name = &buffer[8]; // null-terminated host name - result->h_addrtype = AF_INET; - result->h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN. - - result->h_addr_list = (char **) buffer; - // Might not be official: just echo input arg. - result->h_addr_list[0] = (char *) addr; - // Null-terminate the list of addresses. - result->h_addr_list[1] = 0; - // And no aliases, so null-terminate h_aliases. - result->h_aliases = &result->h_addr_list[1]; - } - else - { - // errno will have been set to S_hostLib_UNKNOWN_HOST. - result = 0; - } - } - - ACE_OS::netdb_release (); - *h_errnop = errno; - return result; -} - -struct hostent * -ACE_OS::gethostbyname_r (const char *name, hostent *result, - ACE_HOSTENT_DATA buffer, - int *h_errnop) -{ - ACE_TRACE ("ACE_OS::gethostbyname_r"); - - if (ACE_OS::netdb_acquire ()) - return 0; - else - { - int addr; - ACE_OSCALL (::hostGetByName ((char *) name), int, -1, addr); - - if (addr == -1) - { - // errno will have been set to S_hostLib_UNKNOWN_HOST - result = 0; - } - else - { - // Might not be official: just echo input arg. - result->h_name = (char *) name; - result->h_addrtype = AF_INET; - result->h_length = 4; // VxWorks 5.2/3 doesn't define IP_ADDR_LEN; - - // buffer layout: - // buffer[0-3]: h_addr_list[0], pointer to the addr. - // buffer[4-7]: h_addr_list[1], null terminator for the h_addr_list. - // buffer[8-11]: the first (and only) addr. - - // Store the address list in buffer. - result->h_addr_list = (char **) buffer; - // Store the actual address _after_ the address list. - result->h_addr_list[0] = (char *) &result->h_addr_list[2]; - result->h_addr_list[2] = (char *) addr; - // Null-terminate the list of addresses. - result->h_addr_list[1] = 0; - // And no aliases, so null-terminate h_aliases. - result->h_aliases = &result->h_addr_list[1]; - } - } - - ACE_OS::netdb_release (); - *h_errnop = errno; - return result; -} -#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, ACE_TEXT ("handle_ = %u"), this->handle_)); -#if defined (ACE_WIN32) - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nInternal = %d"), this->overlapped_.Internal)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nInternalHigh = %d"), this->overlapped_.InternalHigh)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nOffsetHigh = %d"), this->overlapped_.OffsetHigh)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nhEvent = %d"), this->overlapped_.hEvent)); -#elif !defined (CHORUS) - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_whence = %d"), this->lock_.l_whence)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_start = %d"), this->lock_.l_start)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\nl_len = %d"), this->lock_.l_len)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("\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_PACE) - pace_pthread_mutex_t *p_lock = (pace_pthread_mutex_t *) mutex; - pace_pthread_mutex_unlock (p_lock); -# elif 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_PACE */ -} - -#if defined (ACE_HAS_WINCE) -FILE * -ACE_OS::fopen (const ACE_TCHAR *filename, - const ACE_TCHAR *mode) -{ - return ::_wfopen (filename, mode); -} - -#elif defined (ACE_WIN32) -FILE * -ACE_OS::fopen (const ACE_TCHAR *filename, - const ACE_TCHAR *mode) -{ - ACE_TRACE ("ACE_OS::fopen"); - int hmode = _O_TEXT; - - for (const ACE_TCHAR *mode_ptr = mode; *mode_ptr != 0; mode_ptr++) - ACE_OS::fopen_mode_to_open_mode_converter (*mode_ptr, hmode); - - ACE_HANDLE handle = ACE_OS::open (filename, hmode); - if (handle != ACE_INVALID_HANDLE) - { - hmode &= _O_TEXT | _O_RDONLY | _O_APPEND; - int fd = _open_osfhandle ((long) handle, hmode); - if (fd != -1) - { -# if defined(__BORLANDC__) - FILE *fp = _fdopen (fd, ACE_const_cast (char *, mode)); -# elif defined (ACE_USES_WCHAR) - FILE *fp = _wfdopen (fd, mode); -# else - FILE *fp = _fdopen (fd, mode); -# endif /* defined(__BORLANDC__) */ - if (fp != NULL) - return fp; - _close (fd); - } - ACE_OS::close (handle); - } - return NULL; -} -#endif /* ACE_WIN32 */ - -// 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"); -#if defined (ACE_HAS_WINCE) - ACE_NOTSUP_RETURN (-1); -# else /* ACE_HAS_WINCE */ - int result = 0; - va_list ap; - va_start (ap, format); - ACE_OSCALL (::vfprintf (fp, format, ap), int, -1, result); - va_end (ap); - return result; -# endif /* ACE_HAS_WINCE */ -} - -#if defined (ACE_HAS_WCHAR) -int -ACE_OS::fprintf (FILE *fp, const wchar_t *format, ...) -{ - ACE_TRACE ("ACE_OS::fprintf"); -# if defined (ACE_HAS_WINCE) - ACE_NOTSUP_RETURN (-1); -# else /* ACE_HAS_WINCE */ - int result = 0; - va_list ap; - va_start (ap, format); - ACE_OSCALL (::vfwprintf (fp, format, ap), int, -1, result); - va_end (ap); - return result; -# endif /* ACE_HAS_WINCE */ -} -#endif /* ACE_HAS_WCHAR */ - -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_WCHAR) -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_HAS_WCHAR */ - -char * -ACE_OS::gets (char *str, int n) -{ - ACE_TRACE ("ACE_OS::gets"); -#if defined (ACE_HAS_PACE) - return pace_fgets (str, n, stdin); -#else - int c; - char *s = str; - - if (str == 0 || n < 0) n = 0; - if (n == 0) str = 0; - else n--; - - while ((c = getchar ()) != '\n') - { - -# if defined (ACE_HAS_SIGNAL_SAFE_OS_CALLS) - if (c == EOF && errno == EINTR && ACE_LOG_MSG->restart ()) - continue; -# endif /* ACE_HAS_SIGNAL_SAFE_OS_CALLS */ - - if (c == EOF) - break; - - if (n > 0) - n--, *s++ = c; - } - if (s) *s = '\0'; - - return (c == EOF) ? 0 : str; -#endif /* ACE_HAS_PACE */ -} - -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 */ -} - -int -ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id) -{ -#if defined (ACE_HAS_PRIOCNTL) - // Get the priority class ID. - pcinfo_t pcinfo; - // The following is just to avoid Purify warnings about unitialized - // memory reads. - ACE_OS::memset (&pcinfo, 0, sizeof pcinfo); - - ACE_OS::strcpy (pcinfo.pc_clname, class_name); - if (ACE_OS::priority_control (P_ALL /* ignored */, - P_MYID /* ignored */, - PC_GETCID, - (char *) &pcinfo) == -1) - { - return -1; - } - else - { - id = pcinfo.pc_cid; - return 0; - } -#else /* ! ACE_HAS_PRIOCNTL */ - ACE_UNUSED_ARG (class_name); - ACE_UNUSED_ARG (id); - ACE_NOTSUP_RETURN (-1); -#endif /* ! ACE_HAS_PRIOCNTL */ -} - -int -ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params, - ACE_id_t id) -{ -#if defined (ACE_HAS_PRIOCNTL) - // Set priority class, priority, and quantum of this LWP or process as - // specified in sched_params. - - // Get the priority class ID. - ACE_id_t class_id; - if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER ? - "TS" : - "RT", class_id) == -1) - { - return -1; - } - - pcparms_t pcparms; - // The following is just to avoid Purify warnings about unitialized - // memory reads. - ACE_OS::memset (&pcparms, 0, sizeof pcparms); - - pcparms.pc_cid = class_id; - - if (sched_params.policy () == ACE_SCHED_OTHER && - sched_params.quantum () == ACE_Time_Value::zero) - // SunOS doesn't support non-zero quantums in time-sharing class: use - // real-time class instead. - { - tsparms_t tsparms; - // The following is just to avoid Purify warnings about unitialized - // memory reads. - ACE_OS::memset (&tsparms, 0, sizeof 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 - // priority_control () 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; - // The following is just to avoid Purify warnings about unitialized - // memory reads. - ACE_OS::memset (&rtparms, 0, sizeof 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 - // priority_control () call. - ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms); - } - else - { - errno = EINVAL; - return -1; - } - - if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == - ACE_SCOPE_THREAD ? - ACE_SCOPE_PROCESS : - sched_params.scope ()), - id, - PC_SETPARMS, - (char *) &pcparms) < 0) - { - return ACE_OS::last_error (); - } - - return 0; -#else /* ! ACE_HAS_PRIOCNTL */ - ACE_UNUSED_ARG (sched_params); - ACE_UNUSED_ARG (id); - ACE_NOTSUP_RETURN (-1); -#endif /* ! ACE_HAS_PRIOCNTL */ -} - -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); - - int status = ACE_OS::thr_setprio (my_thread_id, prio); - -# if defined (ACE_NEEDS_LWP_PRIO_SET) - // If the thread is in the RT class, then set the priority on its - // LWP. (Instead of doing this if the thread is in the RT class, it - // should be done for all bound threads. But, there doesn't appear - // to be an easy way to determine if the thread is bound.) - - if (status == 0) - { - // Find what scheduling class the thread's LWP is in. - ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0); - if (ACE_OS::lwp_getparams (sched_params) == -1) - { - return -1; - } - else if (sched_params.policy () == ACE_SCHED_FIFO || - sched_params.policy () == ACE_SCHED_RR) - { - // This thread's LWP is in the RT class, so we need to set - // its priority. - sched_params.priority (prio); - return ACE_OS::lwp_setparams (sched_params); - } - // else this is not an RT thread. Nothing more needs to be - // done. - } -# endif /* ACE_NEEDS_LWP_PRIO_SET */ - - return status; -} - -int -ACE_OS::sched_params (const ACE_Sched_Params &sched_params, - ACE_id_t id) -{ - ACE_TRACE ("ACE_OS::sched_params"); -#if defined (ACE_HAS_PACE) - ACE_UNUSED_ARG (id); - 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! - - struct sched_param param; - param.sched_priority = sched_params.priority (); - - if (sched_params.scope () == ACE_SCOPE_PROCESS) - { - return pace_sched_setscheduler (0, // this process - sched_params.policy (), - ¶m) == -1 ? -1 : 0; - } - else if (sched_params.scope () == ACE_SCOPE_THREAD) - { - ACE_thread_t thr_id = ACE_OS::thr_self (); - return pthread_setschedparam (thr_id, - sched_params.policy (), - ¶m); - } -#if defined (sun) - // We need to be able to set LWP priorities on Suns, even without - // ACE_HAS_STHREADS, to obtain preemption. - else if (sched_params.scope () == ACE_SCOPE_LWP) - { - return ACE_OS::set_scheduling_params (sched_params, id); - } -#endif /* sun */ - else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX - { - errno = EINVAL; - return -1; - } -# elif defined (CHORUS) - ACE_UNUSED_ARG (id); - 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); -# elif defined (ACE_HAS_STHREADS) - return ACE_OS::set_scheduling_params (sched_params, id); -# elif defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_SETSCHED) - ACE_UNUSED_ARG (id); - 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! - - struct sched_param param; - param.sched_priority = sched_params.priority (); - - if (sched_params.scope () == ACE_SCOPE_PROCESS) - { - int result = ::sched_setscheduler (0, // this process - sched_params.policy (), - ¶m) == -1 ? -1 : 0; -# if defined (DIGITAL_UNIX) - return result == 0 - ? // Use priocntl (2) to set the process in the RT class, - // if using an RT policy. - ACE_OS::set_scheduling_params (sched_params) - : result; -# else /* ! DIGITAL_UNIX */ - return result; -# endif /* ! DIGITAL_UNIX */ - } - else if (sched_params.scope () == ACE_SCOPE_THREAD) - { - ACE_thread_t thr_id = ACE_OS::thr_self (); - -# if defined (ACE_HAS_PTHREADS_DRAFT4) - return (::pthread_setscheduler(thr_id, - sched_params.policy (), - sched_params.priority()) == -1 ? -1 : 0); -# else - int result; - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam ( - thr_id, - sched_params.policy (), - ¶m), - result), - int, -1); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - - } -#if defined (sun) - // We need to be able to set LWP priorities on Suns, even without - // ACE_HAS_STHREADS, to obtain preemption. - else if (sched_params.scope () == ACE_SCOPE_LWP) - return ACE_OS::set_scheduling_params (sched_params, id); -#endif /* sun */ - else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX - { - errno = EINVAL; - return -1; - } - -# elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE) - - // PharLap ETS can act on the current thread - it can set the quantum also, - // unlike Win32. All this only works on the RT version. -# if defined (ACE_HAS_PHARLAP_RT) - if (id != ACE_SELF) - ACE_NOTSUP_RETURN (-1); - - if (sched_params.quantum() != ACE_Time_Value::zero) - EtsSetTimeSlice (sched_params.quantum().msec()); - -# else - ACE_UNUSED_ARG (id); - - 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; - } -# endif /* ACE_HAS_PHARLAP_RT */ - - // Set the thread priority on the current thread. - return ACE_OS::thr_setprio (sched_params.priority ()); - -# elif defined (VXWORKS) || defined (ACE_PSOS) - ACE_UNUSED_ARG (id); - - // 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 ()); -#else - ACE_UNUSED_ARG (sched_params); - ACE_UNUSED_ARG (id); - ACE_NOTSUP_RETURN (-1); -#endif /* ACE_HAS_PACE */ -} - -// = 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... Under no circumstances should these be given -// initial values. -// Note: these three objects require static construction. -ACE_thread_t ACE_OS::NULL_thread; -ACE_hthread_t ACE_OS::NULL_hthread; -#if defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - ACE_thread_key_t ACE_OS::NULL_key = ACE_static_cast (ACE_thread_key_t, -1); -#else /* ! ACE_HAS_TSS_EMULATION */ - ACE_thread_key_t ACE_OS::NULL_key; -#endif /* ! ACE_HAS_TSS_EMULATION */ - -#if defined (CHORUS) -KnCap ACE_OS::actorcaps_[ACE_CHORUS_MAX_ACTORS]; -// This is used to map an actor's id into a KnCap for killing and -// waiting actors. -#endif /* CHORUS */ - -#if defined (ACE_WIN32) - -// = Static initialization. - -// Keeps track of whether we've initialized the WinSock DLL. -int ACE_OS::socket_initialized_; - -#endif /* WIN32 */ - -#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - -// Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to -// the single file of template instantiations. - -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) const -{ -ACE_TRACE ("ACE_TSS_Ref::operator=="); - - return this->tid_ == info.tid_; -} - -// Check for inequality. -ACE_SPECIAL_INLINE -int -ACE_TSS_Ref::operator!= (const ACE_TSS_Ref &tss_ref) const -{ -ACE_TRACE ("ACE_TSS_Ref::operator=="); - - return !(*this == tss_ref); -} - -// moved class ACE_TSS_Info declaration -// to OS.h so it can be visible to the -// single file of template instantiations - -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), - thread_count_ (-1) -{ -ACE_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); -} - -ACE_TSS_Info::ACE_TSS_Info (void) - : key_ (ACE_OS::NULL_key), - destructor_ (0), - tss_obj_ (0), - thread_count_ (-1) -{ -ACE_TRACE ("ACE_TSS_Info::ACE_TSS_Info"); -} - -# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T) -static inline int operator== (const ACE_thread_key_t &lhs, - const ACE_thread_key_t &rhs) -{ - return ! ACE_OS::memcmp (&lhs, &rhs, sizeof (ACE_thread_key_t)); -} - -static inline int operator!= (const ACE_thread_key_t &lhs, - const ACE_thread_key_t &rhs) -{ - return ! (lhs == rhs); -} -# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */ - -// Check for equality. -int -ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const -{ -ACE_TRACE ("ACE_TSS_Info::operator=="); - - return this->key_ == info.key_; -} - -// Check for inequality. -int -ACE_TSS_Info::operator!= (const ACE_TSS_Info &info) const -{ -ACE_TRACE ("ACE_TSS_Info::operator=="); - - return !(*this == info); -} - -void -ACE_TSS_Info::dump (void) -{ -// ACE_TRACE ("ACE_TSS_Info::dump"); - - ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("key_ = %u\n"), this->key_)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("destructor_ = %u\n"), this->destructor_)); - ACE_DEBUG ((LM_DEBUG, ACE_TEXT ("tss_obj_ = %u\n"), this->tss_obj_)); - ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP)); -} - -// Moved class ACE_TSS_Keys declaration to OS.h so it can be visible -// to the single file of template instantiations. - -ACE_TSS_Keys::ACE_TSS_Keys (void) -{ - for (u_int i = 0; i < ACE_WORDS; ++i) - { - key_bit_words_[i] = 0; - } -} - -ACE_SPECIAL_INLINE -void -ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit) -{ - word = key / ACE_BITS_PER_WORD; - bit = key % ACE_BITS_PER_WORD; -} - -int -ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key) -{ - ACE_KEY_INDEX (key_index, key); - u_int word, bit; - find (key_index, word, bit); - - if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit)) - { - return 1; - } - else - { - ACE_SET_BITS (key_bit_words_[word], 1 << bit); - return 0; - } -} - -int -ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key) -{ - ACE_KEY_INDEX (key_index, key); - - u_int word, bit; - find (key_index, word, bit); - - if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit)) - { - ACE_CLR_BITS (key_bit_words_[word], 1 << bit); - return 0; - } - else - { - return 1; - } -} - -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); - - ~ACE_TSS_Cleanup (void); - - void exit (void *status); - // Cleanup the thread-specific objects. Does _NOT_ exit the thread. - - 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. - - void key_used (ACE_thread_key_t key); - // Mark a key as being used by this thread. - - int free_all_keys_left (void); - // Free all keys left in the table before destruction. - - static int lockable () { return instance_ != 0; } - // Indication of whether the ACE_TSS_CLEANUP_LOCK is usable, and - // therefore whether we are in static constructor/destructor phase - // or not. - -protected: - void dump (void); - - ACE_TSS_Cleanup (void); - // Ensure singleton. - -private: - // Array of <ACE_TSS_Info> objects. - typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS]; - typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR; - - ACE_TSS_TABLE table_; - // Table of <ACE_TSS_Info>'s. - - ACE_thread_key_t in_use_; - // Key for the thread-specific array of whether each TSS key is in use. - - ACE_TSS_Keys *tss_keys (); - // Accessor for this threads ACE_TSS_Keys instance. - -#if defined (ACE_HAS_TSS_EMULATION) - ACE_thread_key_t in_use_key_; - // Key that is used by in_use_. We save this key so that we know - // not to call its destructor in free_all_keys_left (). -#endif /* ACE_HAS_TSS_EMULATION */ - - // = Static data. - static ACE_TSS_Cleanup *instance_; - // Pointer to the singleton instance. -}; - -// = Static object initialization. - -// Pointer to the singleton instance. -ACE_TSS_Cleanup *ACE_TSS_Cleanup::instance_ = 0; - -ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void) -{ - // Zero out the instance pointer to support lockable () accessor. - ACE_TSS_Cleanup::instance_ = 0; -} - -void -ACE_TSS_Cleanup::exit (void * /* status */) -{ - ACE_TRACE ("ACE_TSS_Cleanup::exit"); - - ACE_TSS_TABLE_ITERATOR key_info = table_; - ACE_TSS_Info info_arr[ACE_DEFAULT_THREAD_KEYS]; - 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_TSS_CLEANUP_GUARD - - // Iterate through all the thread-specific items and free them all - // up. - - for (unsigned int i = 0; - i < ACE_DEFAULT_THREAD_KEYS; - ++key_info, ++i) - { - if (key_info->key_ == ACE_OS::NULL_key || - ! key_info->key_in_use ()) continue; - - // If the key's ACE_TSS_Info in-use bit for this thread was set, - // unset it and decrement the key's thread_count_. - if (! tss_keys ()->test_and_clear (key_info->key_)) - { - --key_info->thread_count_; - } - - void *tss_info = 0; - - if (key_info->destructor_ - && ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0 - && tss_info) - { - info_arr[info_ix].key_ = key_info->key_; - info_arr[info_ix].destructor_ = key_info->destructor_; - info_arr[info_ix++].tss_obj_ = key_info->tss_obj_; - } - } - } - - // Now we have given up the ACE_TSS_Cleanup::lock_ and we start - // invoking destructors, in the reverse order of creation. - for (int i = info_ix - 1; i >= 0; --i) - { - void *tss_info = 0; - - ACE_OS::thr_getspecific (info_arr[i].key_, &tss_info); - - if (tss_info != 0) - { - // Only call the destructor if the value is non-zero for this - // thread. - (*info_arr[i].destructor_)(tss_info); - } - } - - // Acquire the ACE_TSS_CLEANUP_LOCK, then free TLS keys and remove - // entries from ACE_TSS_Info table. - { - ACE_TSS_CLEANUP_GUARD - -# if 0 - // We shouldn't free the key and remove it from the table here - // because if we do and some thread ends before other threads - // even get started (or their TSS object haven't been created yet,) - // it's entry will be removed from the table and we are in big chaos. - // For TSS object, these have been done in ACE_TSS_Cleanup::detach. - // Two other use cases will be user managed TSS'es and system wide - // TSS, ones are users responsibilities and the others should be - // persistant system wide. - for (int i = 0; i < index; i++) - { -# if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - // Calling thr_keyfree here ensure the key - // gets removed appropriately. Notice that - // a key should be removed before freeing it. - ACE_OS::thr_keyfree (key_info->key_); -# else - // don't bother to free the key - this->remove (key_info->key_); -# endif /* ACE_WIN32 */ - } -# endif /* 0 */ - } -} - -int -ACE_TSS_Cleanup::free_all_keys_left (void) - // This is called from ACE_OS::cleanup_tss (). When this gets - // called, all threads should have exited except the main thread. - // No key should be freed from this routine. It there's any, - // something might be wrong. -{ - ACE_thread_key_t key_arr[ACE_DEFAULT_THREAD_KEYS]; - ACE_TSS_TABLE_ITERATOR key_info = table_; - unsigned int idx = 0; - unsigned int i; - - for (i = 0; - i < ACE_DEFAULT_THREAD_KEYS; - ++key_info, ++i) -#if defined (ACE_HAS_TSS_EMULATION) - if (key_info->key_ != in_use_key_) -#endif /* ACE_HAS_TSS_EMULATION */ - // Don't call ACE_OS::thr_keyfree () on ACE_TSS_Cleanup's own - // key. See the comments in ACE_OS::thr_key_detach (): the key - // doesn't get detached, so it will be in the table here. - // However, there's no resource associated with it, so we don't - // need to keyfree it. The dynamic memory associated with it - // was already deleted by ACE_TSS_Cleanup::exit (), so we don't - // want to access it again. - key_arr [idx++] = key_info->key_; - - for (i = 0; i < idx; i++) - if (key_arr[i] != ACE_OS::NULL_key) -#if defined (ACE_HAS_TSS_EMULATION) - ACE_OS::thr_keyfree (key_arr[i]); -#elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) - // Don't call ACE_OS::thr_keyfree here. It will try to use - // <in_use_> which has already been cleaned up here. - ::tsd_delete (key_arr[i]); -#else /* ACE_WIN32 */ - // Don't call ACE_OS::thr_keyfree here. It will try to use - // <in_use_> which has already been cleaned up here. - TlsFree (key_arr[i]); -#endif /* ACE_HAS_TSS_EMULATION */ - - return 0; -} - -extern "C" void -ACE_TSS_Cleanup_keys_destroyer (void *tss_keys) -{ - delete ACE_reinterpret_cast (ACE_TSS_Keys *, tss_keys); -} - -ACE_TSS_Cleanup::ACE_TSS_Cleanup (void) - : in_use_ (ACE_OS::NULL_key) -#if defined (ACE_HAS_TSS_EMULATION) - // ACE_TSS_Emulation::total_keys () provides the value of the next - // key to be created. - , in_use_key_ (ACE_TSS_Emulation::total_keys ()) -#endif /* ACE_HAS_TSS_EMULATION */ -{ - 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_TSS_CLEANUP_GUARD - - // Now, use the Double-Checked Locking pattern to make sure we - // only create the ACE_TSS_Cleanup instance once. - if (ACE_TSS_Cleanup::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_TSS_CLEANUP_GUARD - - ACE_KEY_INDEX (key_index, key); - if (key_index < ACE_DEFAULT_THREAD_KEYS) - { - table_[key_index] = ACE_TSS_Info (key, destructor, inst); - return 0; - } - else - { - return -1; - } -} - -int -ACE_TSS_Cleanup::remove (ACE_thread_key_t key) -{ - ACE_TRACE ("ACE_TSS_Cleanup::remove"); - ACE_TSS_CLEANUP_GUARD - - ACE_KEY_INDEX (key_index, key); - if (key_index < ACE_DEFAULT_THREAD_KEYS) - { - // "Remove" the TSS_Info table entry by zeroing out its key_ and - // destructor_ fields. Also, keep track of the number threads - // using the key. - ACE_TSS_Info &info = this->table_ [key_index]; - - // Don't bother to check <in_use_> if the program is shutting - // down. Doing so will cause a new ACE_TSS object getting - // created again. - if (!ACE_OS_Object_Manager::shutting_down () - && ! tss_keys ()->test_and_clear (info.key_)) - --info.thread_count_; - - info.key_ = ACE_OS::NULL_key; - info.destructor_ = 0; - return 0; - } - else - return -1; -} - -int -ACE_TSS_Cleanup::detach (void *inst) -{ - ACE_TSS_CLEANUP_GUARD - - ACE_TSS_TABLE_ITERATOR key_info = table_; - int success = 0; - int ref_cnt = 0; - - // Mark the key as detached in the TSS_Info table. - // It only works for the first key that "inst" owns. - // I don't know why. - for (unsigned int i = 0; - i < ACE_DEFAULT_THREAD_KEYS; - ++key_info, ++i) - { - if (key_info->tss_obj_ == inst) - { - key_info->tss_obj_ = 0; - ref_cnt = key_info->thread_count_; - success = 1; - break; - } - } - - if (success == 0) - return -1; - else if (ref_cnt == 0) - { - // Mark the key as no longer being used. - key_info->key_in_use (0); -# if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - ACE_thread_key_t temp_key = key_info->key_; -# endif /* ACE_WIN32 */ - int retv = this->remove (key_info->key_); - -# if defined (ACE_WIN32) - ::TlsFree (temp_key); -# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) - ::tsd_delete (temp_key); -# endif /* ACE_WIN32 */ - return retv; - } - - return 0; -} - -void -ACE_TSS_Cleanup::key_used (ACE_thread_key_t key) -{ - // If the key's ACE_TSS_Info in-use bit for this thread is not set, - // set it and increment the key's thread_count_. - if (! tss_keys ()->test_and_set (key)) - { - ACE_TSS_CLEANUP_GUARD - - // Retrieve the key's ACE_TSS_Info and increment its thread_count_. - ACE_KEY_INDEX (key_index, key); - ACE_TSS_Info &key_info = this->table_ [key_index]; - if (key_info.thread_count_ == -1) - key_info.key_in_use (1); - else - ++key_info.thread_count_; - } -} - -void -ACE_TSS_Cleanup::dump (void) -{ - // Iterate through all the thread-specific items and dump them all. - - ACE_TSS_TABLE_ITERATOR key_info = table_; - for (unsigned int i = 0; - i < ACE_DEFAULT_THREAD_KEYS; - ++key_info, ++i) - key_info->dump (); -} - -ACE_TSS_Keys * -ACE_TSS_Cleanup::tss_keys () -{ - if (in_use_ == ACE_OS::NULL_key) - { - ACE_TSS_CLEANUP_GUARD - // Double-check; - if (in_use_ == ACE_OS::NULL_key) - { - // Initialize in_use_ with a new key. - if (ACE_OS::thr_keycreate (&in_use_, - &ACE_TSS_Cleanup_keys_destroyer)) - return 0; // Major problems, this should *never* happen! - } - } - - ACE_TSS_Keys *ts_keys = 0; - if (ACE_OS::thr_getspecific (in_use_, - ACE_reinterpret_cast (void **, &ts_keys)) == -1) - return 0; // This should not happen! - - if (ts_keys == 0) - { - ACE_NEW_RETURN (ts_keys, - ACE_TSS_Keys, - 0); - // Store the dynamically allocated pointer in thread-specific - // storage. - if (ACE_OS::thr_setspecific (in_use_, - ACE_reinterpret_cast (void *, - ts_keys)) == -1) - { - delete ts_keys; - return 0; // Major problems, this should *never* happen! - } - } - - return ts_keys; -} - -# if defined (ACE_HAS_TSS_EMULATION) -u_int ACE_TSS_Emulation::total_keys_ = 0; - -ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR -ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX] - = { 0 }; - -# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) - -int ACE_TSS_Emulation::key_created_ = 0; - -ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_; - -/* static */ -# if defined (ACE_HAS_THR_C_FUNC) -extern "C" -void -ACE_TSS_Emulation_cleanup (void *ptr) -{ - ACE_UNUSED_ARG (ptr); - // Really this must be used for ACE_TSS_Emulation code to make the TSS - // cleanup -} -#else -void -ACE_TSS_Emulation_cleanup (void *ptr) -{ - ACE_UNUSED_ARG (ptr); - // Really this must be used for ACE_TSS_Emulation code to make the TSS - // cleanup -} -# endif /* ACE_HAS_THR_C_FUNC */ - -void ** -ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created) -{ - // TSS Singleton implementation. - - // Create the one native TSS key, if necessary. - if (key_created_ == 0) - { - // Double-checked lock . . . - ACE_TSS_BASE_GUARD - - if (key_created_ == 0) - { - ACE_NO_HEAP_CHECK; - if (ACE_OS::thr_keycreate (&native_tss_key_, - &ACE_TSS_Emulation_cleanup) != 0) - { - return 0; // Major problems, this should *never* happen! - } - key_created_ = 1; - } - } - - void **old_ts_storage = 0; - - // Get the tss_storage from thread-OS specific storage. - if (ACE_OS::thr_getspecific (native_tss_key_, - (void **) &old_ts_storage) == -1) - return 0; // This should not happen! - - // Check to see if this is the first time in for this thread. - // This block can also be entered after a fork () in the child process, - // at least on Pthreads Draft 4 platforms. - if (old_ts_storage == 0) - { - if (ts_created) - *ts_created = 1u; - - // Use the ts_storage passed as argument, if non-zero. It is - // possible that this has been implemented in the stack. At the - // moment, this is unknown. The cleanup must not do nothing. - // If ts_storage is zero, allocate (and eventually leak) the - // storage array. - if (ts_storage == 0) - { - ACE_NO_HEAP_CHECK; - - ACE_NEW_RETURN (ts_storage, - void*[ACE_TSS_THREAD_KEYS_MAX], - 0); - - // Zero the entire TSS array. Do it manually instead of - // using memset, for optimum speed. Though, memset may be - // faster :-) - void **tss_base_p = ts_storage; - - for (u_int i = 0; - i < ACE_TSS_THREAD_KEYS_MAX; - ++i) - *tss_base_p++ = 0; - } - - // Store the pointer in thread-specific storage. It gets - // deleted via the ACE_TSS_Emulation_cleanup function when the - // thread terminates. - if (ACE_OS::thr_setspecific (native_tss_key_, - (void *) ts_storage) != 0) - return 0; // Major problems, this should *never* happen! - } - else - if (ts_created) - ts_created = 0; - - return ts_storage ? ts_storage : old_ts_storage; -} -# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ - -u_int -ACE_TSS_Emulation::total_keys () -{ - ACE_OS_Recursive_Thread_Mutex_Guard ( - *ACE_static_cast (ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK])); - - return total_keys_; -} - -int -ACE_TSS_Emulation::next_key (ACE_thread_key_t &key) -{ - ACE_OS_Recursive_Thread_Mutex_Guard ( - *ACE_static_cast (ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK])); - - if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX) - { -# if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T) - ACE_OS::memset (&key, 0, sizeof (ACE_thread_key_t)); - ACE_OS::memcpy (&key, &total_keys_, sizeof (u_int)); -# else - key = total_keys_; -# endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */ - - ++total_keys_; - return 0; - } - else - { - key = ACE_OS::NULL_key; - return -1; - } -} - -void * -ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX]) -{ -# if defined (ACE_PSOS) - u_long tss_base; - - // Use the supplied array for this thread's TSS. - tss_base = (u_long) ts_storage; - t_setreg (0, PSOS_TASK_REG_TSS, tss_base); - - // Zero the entire TSS array. - void **tss_base_p = ts_storage; - for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p) - { - *tss_base_p = 0; - } - - return (void *) tss_base; -# else /* ! ACE_PSOS */ -# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) - // On VxWorks, in particular, don't check to see if the field - // is 0. It isn't always, specifically, when a program is run - // directly by the shell (without spawning a new task) after - // another program has been run. - - u_int ts_created = 0; - tss_base (ts_storage, &ts_created); - if (ts_created) - { -# else /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */ - tss_base () = ts_storage; -# endif - - // Zero the entire TSS array. Do it manually instead of using - // memset, for optimum speed. Though, memset may be faster :-) - void **tss_base_p = tss_base (); - for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p) - { - *tss_base_p = 0; - } - - return tss_base (); -# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) - } - else - { - return 0; - } -# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ -# endif /* ! ACE_PSOS */ -} - -void -ACE_TSS_Emulation::tss_close () -{ -#if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) - // Free native_tss_key_ here. -#endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ -} - -# endif /* ACE_HAS_TSS_EMULATION */ - -#endif /* WIN32 || ACE_HAS_TSS_EMULATION */ - -void -ACE_OS::cleanup_tss (const u_int main_thread) -{ -#if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - // Call TSS destructors for current thread. - ACE_TSS_Cleanup::instance ()->exit (0); -#endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 || ACE_PSOS_HAS_TSS */ - - if (main_thread) - { -#if !defined (ACE_HAS_TSS_EMULATION) && !defined (ACE_HAS_MINIMAL_ACE_OS) - // Just close the ACE_Log_Msg for the current (which should be - // main) thread. We don't have TSS emulation; if there's native - // TSS, it should call its destructors when the main thread - // exits. - ACE_Log_Msg::close (); -#endif /* ! ACE_HAS_TSS_EMULATION && ! ACE_HAS_MINIMAL_ACE_OS */ - -#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) -#if ! defined (ACE_HAS_TSS_EMULATION) - // Don't do this with TSS_Emulation, because the the - // ACE_TSS_Cleanup::instance () has already exited (). We can't - // safely access the TSS values that were created by the main - // thread. - - // Remove all TSS_Info table entries. - ACE_TSS_Cleanup::instance ()->free_all_keys_left (); -#endif /* ! ACE_HAS_TSS_EMULATION */ - - // Finally, free up the ACE_TSS_Cleanup instance. This method gets - // called by the ACE_Object_Manager. - delete ACE_TSS_Cleanup::instance (); -#endif /* WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */ - -#if defined (ACE_HAS_TSS_EMULATION) - ACE_TSS_Emulation::tss_close (); -#endif /* ACE_HAS_TSS_EMULATION */ - } -} - -void -ACE_Thread_Adapter::inherit_log_msg (void) -{ - if (ACE_Thread_Adapter::inherit_log_msg_hook_ != 0) - (*ACE_Thread_Adapter::inherit_log_msg_hook_)(this->thr_desc_, - this->log_msg_attributes_); -} - -#if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) -#define ACE_ENDTHREADEX(STATUS) ::_endthread () -#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ - (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID) -#elif defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400) - -struct __IBMCPP__thread_params { - __IBMCPP__thread_params(ACE_THR_C_FUNC e, LPVOID a) - :entry_point(e),args(a) {} - ACE_THR_C_FUNC entry_point; - LPVOID args; -}; - -#pragma handler(initThread) -extern "C" DWORD __stdcall __IBMCPP__initThread(void *arg) -{ - // Must reset 387 since using CreateThread - _fpreset(); - - // Dispatch user function... - auto_ptr<__IBMCPP__thread_params> parms((__IBMCPP__thread_params *)arg); - (*parms->entry_point)(parms->args); - _endthread(); - return 0; -} - -HANDLE WINAPI __IBMCPP__beginthreadex(void *stack, - DWORD stacksize, - ACE_THR_C_FUNC entry_point, - LPVOID args, - DWORD flags, - LPDWORD thr_id) -{ - return CreateThread(NULL, - stacksize, - (LPTHREAD_START_ROUTINE)__IBMCPP__initThread, - new __IBMCPP__thread_params(entry_point, args), - flags, - thr_id); -} - -#define ACE_ENDTHREADEX(STATUS) ::_endthread () -#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ - __IBMCPP__beginthreadex(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) - -#elif defined (ACE_HAS_WINCE) && defined (UNDER_CE) && (UNDER_CE >= 211) -#define ACE_ENDTHREADEX(STATUS) ExitThread ((DWORD) STATUS) -#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ - CreateThread (NULL, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & CREATE_SUSPENDED, (unsigned long *) THR_ID) -#else -#define ACE_ENDTHREADEX(STATUS) ::_endthreadex ((DWORD) STATUS) -#define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \ - ::_beginthreadex (STACK, STACKSIZE, (unsigned (__stdcall *) (void *)) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID) -#endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */ - -void * -ACE_Thread_Hook::start (ACE_THR_FUNC func, - void *arg) -{ - return (func) (arg); -} - -ACE_Thread_Hook * -ACE_Thread_Hook::thread_hook (ACE_Thread_Hook *hook) -{ - return ACE_OS_Object_Manager::thread_hook (hook); -} - -ACE_Thread_Hook * -ACE_Thread_Hook::thread_hook (void) -{ - return ACE_OS_Object_Manager::thread_hook (); -} - -void * -ACE_Thread_Adapter::invoke (void) -{ - // Inherit the logging features if the parent thread has an - // ACE_Log_Msg instance in thread-specific storage. - this->inherit_log_msg (); - -#if !defined(ACE_USE_THREAD_MANAGER_ADAPTER) - // NOTE: this preprocessor directive should match the one in - // above ACE_Thread_Exit::instance (). With the Xavier Pthreads - // package, the exit_hook in TSS causes a seg fault. So, this - // works around that by creating exit_hook on the stack. -# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) || defined (ACE_HAS_TSS_EMULATION) - // Obtain our thread-specific exit hook and make sure that it - // knows how to clean us up! Note that we never use this - // pointer directly (it's stored in thread-specific storage), so - // it's ok to dereference it here and only store it as a - // reference. - if (this->thr_mgr () != 0) - { - ACE_Thread_Exit &exit_hook = *ACE_Thread_Exit::instance (); - // Keep track of the <Thread_Manager> that's associated with this - // <exit_hook>. - exit_hook.thr_mgr (this->thr_mgr ()); - } -# else - // Without TSS, create an <ACE_Thread_Exit> instance. When this - // function returns, its destructor will be called because the - // object goes out of scope. The drawback with this appraoch is - // that the destructor _won't_ get called if <thr_exit> is - // called. So, threads shouldn't exit that way. Instead, they - // should return from <svc>. - ACE_Thread_Exit exit_hook; - exit_hook.thr_mgr (this->thr_mgr ()); -# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE || ACE_HAS_TSS_EMULATION */ - -#endif /* ! ACE_USE_THREAD_MANAGER_ADAPTER */ - - // Extract the arguments. - ACE_THR_FUNC_INTERNAL func = ACE_reinterpret_cast (ACE_THR_FUNC_INTERNAL, - this->user_func_); - void *arg = this->arg_; - -#if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) - ACE_OS_Thread_Descriptor *thr_desc = this->thr_desc_; -#endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */ - - // Delete ourselves since we don't need <this> anymore. Make sure - // not to access <this> anywhere below this point. - delete this; - -#if defined (ACE_NEEDS_LWP_PRIO_SET) - // On SunOS, the LWP priority needs to be set in order to get - // preemption when running in the RT class. This is the ACE way to - // do that . . . - ACE_hthread_t thr_handle; - ACE_OS::thr_self (thr_handle); - int prio; - - // thr_getprio () on the current thread should never fail. - ACE_OS::thr_getprio (thr_handle, prio); - - // ACE_OS::thr_setprio () has the special logic to set the LWP priority, - // if running in the RT class. - ACE_OS::thr_setprio (prio); - -#endif /* ACE_NEEDS_LWP_PRIO_SET */ - - void *status = 0; - - ACE_SEH_TRY - { - ACE_SEH_TRY - { - ACE_Thread_Hook *hook = - ACE_OS_Object_Manager::thread_hook (); - - if (hook) - // Invoke the start hook to give the user a chance to - // perform some initialization processing before the - // <func> is invoked. - status = hook->start (ACE_reinterpret_cast (ACE_THR_FUNC, func), - arg); - else - { - // Call thread entry point. -#if defined (ACE_PSOS) - (*func) (arg); -#else /* ! ACE_PSOS */ - status = ACE_reinterpret_cast (void *, (*func) (arg)); -#endif /* ACE_PSOS */ - } -#if defined (ACE_PSOS) - // pSOS task functions do not return a value. - status = 0; -#endif /* ACE_PSOS */ - } - -#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) - ACE_SEH_EXCEPT (ACE_LOG_MSG->seh_except_selector ()( - (void *) GetExceptionInformation ())) - { - ACE_LOG_MSG->seh_except_handler ()(0); - } -#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ - } - - ACE_SEH_FINALLY - { - // If we changed this to 1, change the respective if in - // Task::svc_run to 0. -#if 0 - // Call the <Task->close> hook. - if (func == ACE_reinterpret_cast (ACE_THR_FUNC_INTERNAL, - ACE_Task_Base::svc_run)) - { - ACE_Task_Base *task_ptr = (ACE_Task_Base *) arg; - ACE_Thread_Manager *thr_mgr_ptr = task_ptr->thr_mgr (); - - // This calls the Task->close () hook. - task_ptr->cleanup (task_ptr, 0); - - // This prevents a second invocation of the cleanup code - // (called later by <ACE_Thread_Manager::exit>. - thr_mgr_ptr->at_exit (task_ptr, 0, 0); - } -#endif /* 0 */ - -#if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) -# if defined (ACE_WIN32) && defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) - int using_afx = -1; - if (thr_desc) - using_afx = ACE_BIT_ENABLED (thr_desc->flags (), THR_USE_AFX); -# endif /* ACE_WIN32 && ACE_HAS_MFC && (ACE_HAS_MFC != 0) */ - // Call TSS destructors. - ACE_OS::cleanup_tss (0 /* not main thread */); - -# if defined (ACE_WIN32) - // Exit the thread. 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. -# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) - if (using_afx != -1) - { - if (using_afx) - ::AfxEndThread ((DWORD) status); - else - ACE_ENDTHREADEX (status); - } - else - { - // Not spawned by ACE_Thread_Manager, use the old buggy - // version. You should seriously consider using - // ACE_Thread_Manager to spawn threads. The following code - // is know to cause some problem. - CWinThread *pThread = ::AfxGetThread (); - - if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ()) - ACE_ENDTHREADEX (status); - else - ::AfxEndThread ((DWORD)status); - } -# else - - ACE_ENDTHREADEX (status); -# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/ -# endif /* ACE_WIN32 */ -#endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */ - -#if defined (ACE_PSOS) - // This sequence of calls is documented by ISI as the proper way to - // clean up a pSOS task. They affect different components, so only - // try the ones for components that are built with ACE. -# if defined (SC_PREPC) && (SC_PREPC == YES) - ::fclose (0); // Return pREPC+ resources -# endif /* SC_PREPC */ -# if defined (SC_PHILE) && (SC_PHILE == YES) - ::close_f (0); // Return pHILE+ resources -# endif /* SC_PHILE */ -# if defined (SC_PNA) && (SC_PNA == YES) - ::close (0); // Return pNA+ resources -# endif /* SC_PNA */ -# if defined (SC_SC_PREPC) && (SC_PREPC == YES) - ::free (-1); // Return pREPC+ memory -# endif /* SC_PREPC */ - status = ::t_delete (0); // Suicide - only returns on error -#endif /* ACE_PSOS */ - - return status; - } - - ACE_NOTREACHED (return status); -} - -#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) -int ACE_SEH_Default_Exception_Selector (void *) -{ - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("(%t) Win32 structured exception exiting thread\n"))); - return (DWORD) ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION; -} - -int ACE_SEH_Default_Exception_Handler (void *) -{ - return 0; -} -#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ - -extern "C" void -ace_cleanup_destroyer (ACE_Cleanup *object, void *param) -{ - object->cleanup (param); -} - -// Run the thread entry point for the <ACE_Thread_Adapter>. This must -// be an extern "C" to make certain compilers happy... - -#if defined (ACE_PSOS) -extern "C" void ace_thread_adapter (unsigned long args) -{ - ACE_TRACE ("ace_thread_adapter"); - -#if defined (ACE_HAS_TSS_EMULATION) - // As early as we can in the execution of the new thread, allocate - // its local TS storage. Allocate it on the stack, to save dynamic - // allocation/dealloction. - void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]; - ACE_TSS_Emulation::tss_open (ts_storage); -#endif /* ACE_HAS_TSS_EMULATION */ - - ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args; - - // Invoke the user-supplied function with the args. - thread_args->invoke (); -} -#else /* ! defined (ACE_PSOS) */ -extern "C" void * ace_thread_adapter (void *args) -{ - ACE_TRACE ("ace_thread_adapter"); - -#if defined (ACE_HAS_TSS_EMULATION) - // As early as we can in the execution of the new thread, allocate - // its local TS storage. Allocate it on the stack, to save dynamic - // allocation/dealloction. - void *ts_storage[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]; - ACE_TSS_Emulation::tss_open (ts_storage); -#endif /* ACE_HAS_TSS_EMULATION */ - - ACE_Thread_Adapter *thread_args = (ACE_Thread_Adapter *) args; - - // Invoke the user-supplied function with the args. - void *status = thread_args->invoke (); - - return status; -} -#endif /* ACE_PSOS */ - - -ACE_Thread_Adapter::ACE_Thread_Adapter (ACE_THR_FUNC user_func, - void *arg, - ACE_THR_C_FUNC entry_point, - ACE_Thread_Manager *tm, - ACE_Thread_Descriptor *td -#if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) - , ACE_SEH_EXCEPT_HANDLER selector, - ACE_SEH_EXCEPT_HANDLER handler -#endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ - ) - : user_func_ (user_func), - arg_ (arg), - entry_point_ (entry_point), - thr_mgr_ (tm), - // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor. - // But without #including ace/Thread_Manager.h, we don't know that. - thr_desc_ (ACE_reinterpret_cast (ACE_OS_Thread_Descriptor *,td)), - log_msg_attributes_ (0) -{ - ACE_TRACE ("Ace_Thread_Adapter::Ace_Thread_Adapter"); - - if (ACE_Thread_Adapter::init_log_msg_hook_ != 0) - (*ACE_Thread_Adapter::init_log_msg_hook_) (this->log_msg_attributes_ -# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) - , selector - , handler -# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ - ); -} - -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_Thread_Adapter *thread_adapter) -{ - ACE_TRACE ("ACE_OS::thr_create"); - - if (ACE_BIT_DISABLED (flags, THR_DETACHED) && - ACE_BIT_DISABLED (flags, THR_JOINABLE)) - ACE_SET_BITS (flags, THR_JOINABLE); - -# if defined (ACE_NO_THREAD_ADAPTER) -# define ACE_THREAD_FUNCTION func -# define ACE_THREAD_ARGUMENT args -# else /* ! defined (ACE_NO_THREAD_ADAPTER) */ -# if defined (ACE_PSOS) -# define ACE_THREAD_FUNCTION (PSOS_TASK_ENTRY_POINT) thread_args->entry_point () -# else -# define ACE_THREAD_FUNCTION thread_args->entry_point () -# endif /* defined (ACE_PSOS) */ -# define ACE_THREAD_ARGUMENT thread_args -# endif /* ! defined (ACE_NO_THREAD_ADAPTER) */ - - ACE_Thread_Adapter *thread_args; - if (thread_adapter == 0) -# if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS) - ACE_NEW_RETURN (thread_args, - ACE_Thread_Adapter (func, args, - (ACE_THR_C_FUNC) ace_thread_adapter, - 0, - 0, - ACE_LOG_MSG->seh_except_selector(), - ACE_LOG_MSG->seh_except_handler()), - -1); -# else - ACE_NEW_RETURN (thread_args, - ACE_Thread_Adapter (func, args, - (ACE_THR_C_FUNC) ace_thread_adapter), - -1); - -# endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */ - else - thread_args = thread_adapter; - -# if defined (ACE_HAS_THREADS) - - // *** 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 !defined (VXWORKS) - // On VxWorks, the OS will provide a task name if the user doesn't. - // So, we don't need to create a tmp_thr. If the caller of this - // member function is the Thread_Manager, than thr_id will be non-zero - // anyways. - ACE_thread_t tmp_thr; - - if (thr_id == 0) - thr_id = &tmp_thr; -# endif /* ! VXWORKS */ - - ACE_hthread_t tmp_handle; - if (thr_handle == 0) - thr_handle = &tmp_handle; - -# if defined (ACE_HAS_PTHREADS) - - int result; - pthread_attr_t attr; -# if defined (ACE_HAS_PTHREADS_DRAFT4) - if (::pthread_attr_create (&attr) != 0) -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - if (::pthread_attr_init (&attr) != 0) -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - return -1; - -# if defined (CHORUS) - // If it is a super actor, we can't set stacksize. But for the time - // being we are all non-super actors. Should be fixed to take care - // of super actors!!! - if (stacksize == 0) - stacksize = ACE_CHORUS_DEFAULT_MIN_STACK_SIZE; - else if (stacksize < ACE_CHORUS_DEFAULT_MIN_STACK_SIZE) - stacksize = ACE_CHORUS_DEFAULT_MIN_STACK_SIZE; -# endif /*CHORUS */ - - if (stacksize != 0) - { - size_t size = stacksize; - -# if defined (PTHREAD_STACK_MIN) - if (size < ACE_static_cast (size_t, PTHREAD_STACK_MIN)) - size = PTHREAD_STACK_MIN; -# endif /* PTHREAD_STACK_MIN */ - -# if !defined (ACE_LACKS_THREAD_STACK_SIZE) // JCEJ 12/17/96 -# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) - if (::pthread_attr_setstacksize (&attr, size) != 0) -# else - if (ACE_ADAPT_RETVAL(pthread_attr_setstacksize (&attr, size), result) == -1) -# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ - { -# if defined (ACE_HAS_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - return -1; - } -# else - ACE_UNUSED_ARG (size); -# 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_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - return -1; - } - } -# else - ACE_UNUSED_ARG (stack); -# 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_PTHREADS_DRAFT4) - if (::pthread_attr_setdetach_np (&attr, dstate) != 0) -# else /* ACE_HAS_PTHREADS_DRAFT4 */ -# if defined (ACE_HAS_PTHREADS_DRAFT6) - if (::pthread_attr_setdetachstate (&attr, &dstate) != 0) -# else - if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate), - result) != 0) -# endif /* ACE_HAS_PTHREADS_DRAFT6 */ -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - { -# if defined (ACE_HAS_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - return -1; - } - } - - // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we - // call ::pthread_detach () below. If THR_DETACHED is not - // enabled, we call ::pthread_detach () in the Thread_Manager, - // after joining with the thread. -# 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 != ACE_DEFAULT_THREAD_PRIORITY) - { - 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) - // SunOS, thru version 5.6, only supports SCHED_OTHER. - spolicy = SCHED_OTHER; -# else - // Make sure to enable explicit scheduling, in case we didn't - // enable it above (for non-default priority). - ACE_SET_BITS (flags, THR_EXPLICIT_SCHED); - - if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT)) - spolicy = SCHED_OTHER; - else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)) - spolicy = SCHED_FIFO; -# if defined (SCHED_IO) - else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO)) - spolicy = SCHED_IO; -# else - else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO)) - { - errno = ENOSYS; - return -1; - } -# endif /* SCHED_IO */ - else - spolicy = SCHED_RR; - -# if defined (ACE_HAS_FSU_PTHREADS) - int ret; - switch (spolicy) - { - case SCHED_FIFO: - case SCHED_RR: - ret = 0; - break; - default: - ret = 22; - break; - } - if (ret != 0) - { - ::pthread_attr_destroy (&attr); - return -1; - } -# endif /* ACE_HAS_FSU_PTHREADS */ - -# endif /* ACE_HAS_ONLY_SCHED_OTHER */ - -# if defined (ACE_HAS_PTHREADS_DRAFT4) - result = ::pthread_attr_setsched (&attr, spolicy); -# elif defined (ACE_HAS_PTHREADS_DRAFT6) - result = ::pthread_attr_setschedpolicy (&attr, spolicy); -# else /* draft 7 or std */ - ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy), - result); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - if (result != 0) - { -# if defined (ACE_HAS_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - return -1; - } - } - - // *** Set Priority (use reasonable default priorities) -# if defined(ACE_HAS_PTHREADS_STD) - // 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 == ACE_DEFAULT_THREAD_PRIORITY) - { - 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_STD */ - if (priority != ACE_DEFAULT_THREAD_PRIORITY) - { - struct sched_param sparam; - ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); - -# if defined (ACE_HAS_IRIX62_THREADS) - sparam.sched_priority = ACE_MIN (priority, - (long) PTHREAD_MAX_PRIORITY); -# elif defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS_STD) - /* For MIT pthreads... */ - sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY); -# elif defined(ACE_HAS_PTHREADS_STD) && !defined (ACE_HAS_STHREADS) - // 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)); -# elif defined (PRIORITY_MAX) - sparam.sched_priority = ACE_MIN (priority, - (long) PRIORITY_MAX); -# else - sparam.sched_priority = priority; -# endif /* ACE_HAS_IRIX62_THREADS */ - -# if defined (ACE_HAS_FSU_PTHREADS) - if (sparam.sched_priority >= PTHREAD_MIN_PRIORITY - && sparam.sched_priority <= PTHREAD_MAX_PRIORITY) - attr.prio = sparam.sched_priority; - else - { - pthread_attr_destroy (&attr); - errno = EINVAL; - return -1; - } -# else - { -# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER) - // SunOS, through 5.6, POSIX only allows priorities > 0 to - // ::pthread_attr_setschedparam. If a priority of 0 was - // requested, set the thread priority after creating it, below. - if (priority > 0) -# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */ - { -# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) - result = ::pthread_attr_setprio (&attr, - sparam.sched_priority); -# else /* this is draft 7 or std */ - ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam), - result); -# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ - if (result != 0) - { -# if defined (ACE_HAS_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - 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_PTHREADS_DRAFT4) - int sched = PTHREAD_DEFAULT_SCHED; -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - int sched = PTHREAD_EXPLICIT_SCHED; -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)) - sched = PTHREAD_INHERIT_SCHED; - if (::pthread_attr_setinheritsched (&attr, sched) != 0) - { -# if defined (ACE_HAS_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - return -1; - } - } -# else /* ACE_LACKS_SETSCHED */ - ACE_UNUSED_ARG (priority); -# 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_PTHREADS_DRAFT4) - ::pthread_attr_delete (&attr); -# else /* ACE_HAS_PTHREADS_DRAFT4 */ - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - 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 - // SunOS semantics. - int lwps = ACE_OS::thr_getconcurrency (); - if (lwps == -1) - { - if (errno == ENOTSUP) - { - // Suppress the ENOTSUP because it's harmless. - errno = 0; - } - else - { - // This should never happen on SunOS: - // ::thr_getconcurrency () should always succeed. - return -1; - } - } - else - { - if (ACE_OS::thr_setconcurrency (lwps + 1) == -1) - { - if (errno == ENOTSUP) - { - // Unlikely: ::thr_getconcurrency () is supported but - // ::thr_setconcurrency () is not? - } - else - { - return -1; - } - } - } - } - } - -# if defined (ACE_HAS_PTHREADS_DRAFT4) - ACE_OSCALL (::pthread_create (thr_id, attr, - thread_args->entry_point (), - thread_args), - int, -1, result); - -# if defined (ACE_LACKS_SETDETACH) - if (ACE_BIT_ENABLED (flags, THR_DETACHED)) - { -# if defined (HPUX_10) - // HP-UX DCE threads' pthread_detach will smash thr_id if it's - // just given as an argument. This will cause ACE_Thread_Manager - // (if it's doing this create) to lose track of the new thread - // since the ID will be passed back equal to 0. So give - // pthread_detach a junker to scribble on. - ACE_thread_t junker; - cma_handle_assign(thr_id, &junker); - ::pthread_detach (&junker); -# else - ::pthread_detach (thr_id); -# endif /* HPUX_10 */ - } -# endif /* ACE_LACKS_SETDETACH */ - - ::pthread_attr_delete (&attr); - -# elif defined (ACE_HAS_PTHREADS_DRAFT6) - ACE_OSCALL (::pthread_create (thr_id, &attr, - thread_args->entry_point (), - thread_args), - int, -1, result); - ::pthread_attr_destroy (&attr); - -# else /* this is draft 7 or std */ - ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id, - &attr, - thread_args->entry_point (), - thread_args), - result), - int, -1, result); - ::pthread_attr_destroy (&attr); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - - // This is a SunOS or POSIX implementation of pthreads, - // where we assume that ACE_thread_t and ACE_hthread_t are the same. - // If this *isn't* correct on some platform, please let us know. - if (result != -1) - *thr_handle = *thr_id; - -# if defined (sun) && defined (ACE_HAS_ONLY_SCHED_OTHER) - // SunOS prior to 5.7: - - // If the priority is 0, then we might have to set it now - // because we couldn't set it with - // ::pthread_attr_setschedparam, as noted above. This doesn't - // provide strictly correct behavior, because the thread was - // created (above) with the priority of its parent. (That - // applies regardless of the inherit_sched attribute: if it - // was PTHREAD_INHERIT_SCHED, then it certainly inherited its - // parent's priority. If it was PTHREAD_EXPLICIT_SCHED, then - // "attr" was initialized by the SunOS ::pthread_attr_init - // () to contain NULL for the priority, which indicated to - // SunOS ::pthread_create () to inherit the parent - // priority.) - if (priority == 0) - { - // Check the priority of this thread, which is the parent - // of the newly created thread. If it is 0, then the - // newly created thread will have inherited the priority - // of 0, so there's no need to explicitly set it. - struct sched_param sparam; - int policy = 0; - ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (), - &policy, - &sparam), - result), int, - -1, result); - - // The only policy supported by by SunOS, thru version 5.6, - // is SCHED_OTHER, so that's hard-coded here. - policy = ACE_SCHED_OTHER; - - if (sparam.sched_priority != 0) - { - ACE_OS::memset ((void *) &sparam, 0, sizeof sparam); - // The memset to 0 sets the priority to 0, so we don't need - // to explicitly set sparam.sched_priority. - - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam ( - *thr_id, - policy, - &sparam), - result), - int, -1); - } - } - -# if defined (ACE_NEEDS_LWP_PRIO_SET) -# if 0 - // It would be useful if we could make this work. But, it - // requires a mechanism for determining the ID of an LWP - // to which another thread is bound. Is there a way to do - // that? Instead, just rely on the code in - // ACE_Thread_Adapter::invoke () to set the LWP priority. - - // If the thread is bound, then set the priority on its LWP. - if (ACE_BIT_ENABLED (flags, THR_BOUND)) - { - ACE_Sched_Params sched_params ( - ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) || - ACE_BIT_ENABLED (flags, THR_SCHED_RR) ? - ACE_SCHED_FIFO : - ACE_SCHED_OTHER, - priority); - result = ACE_OS::lwp_setparams (sched_params, - /* ? How do we find the ID of the LWP - to which *thr_id is bound? */); - } -# endif /* 0 */ -# endif /* ACE_NEEDS_LWP_PRIO_SET */ - -# endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */ - return result; -# elif defined (ACE_HAS_STHREADS) - int result; - int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED); - - if (priority != ACE_DEFAULT_THREAD_PRIORITY) - // 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, - thread_args->entry_point (), - thread_args, - flags, thr_id), result), - int, -1, result); - - if (result != -1) - { - // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same. - *thr_handle = *thr_id; - - if (priority != ACE_DEFAULT_THREAD_PRIORITY) - { - // 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! - if ((result = ACE_OS::thr_setprio (*thr_id, priority)) != 0) - { - errno = result; - return -1; - } - - if (start_suspended == 0) - { - if ((result = ACE_OS::thr_continue (*thr_id)) != 0) - { - errno = result; - return -1; - } - } - } - } - return result; -# elif defined (ACE_HAS_WTHREADS) - ACE_UNUSED_ARG (stack); -# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) - if (ACE_BIT_ENABLED (flags, THR_USE_AFX)) - { - CWinThread *cwin_thread = - ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (), - thread_args, - priority, - 0, - flags | THR_SUSPENDED); - // Have to duplicate the handle because - // CWinThread::~CWinThread() closes the original handle. -# if !defined (ACE_HAS_WINCE) - (void) ::DuplicateHandle (::GetCurrentProcess (), - cwin_thread->m_hThread, - ::GetCurrentProcess (), - thr_handle, - 0, - TRUE, - DUPLICATE_SAME_ACCESS); -# endif /* ! ACE_HAS_WINCE */ - *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 != ACE_DEFAULT_THREAD_PRIORITY) - // 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 *) ACE_BEGINTHREADEX (0, - stacksize, - thread_args->entry_point (), - thread_args, - flags, - thr_id); - - if (priority != ACE_DEFAULT_THREAD_PRIORITY && *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 - (0, - stacksize, - LPTHREAD_START_ROUTINE (thread_args->entry_point ()), - 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 (ACE_PSOS) - - // stack is created in the task's memory region 0 - ACE_UNUSED_ARG (stack); - - // task creation and start flags are fixed - ACE_UNUSED_ARG (flags); - - // lowest priority is reserved for the IDLE pSOS+ system daemon, - // highest are reserved for high priority pSOS+ system daemons - if (priority < PSOS_TASK_MIN_PRIORITY) - { - priority = PSOS_TASK_MIN_PRIORITY; - } - else if (priority > PSOS_TASK_MAX_PRIORITY) - { - priority = PSOS_TASK_MAX_PRIORITY; - } - - // set the stacksize to a default value if no size is specified - if (stacksize == 0) - stacksize = ACE_PSOS_DEFAULT_STACK_SIZE; - - ACE_hthread_t tid; - *thr_handle = 0; - - // create the thread - if (t_create ((char *) thr_id, // task name - priority, // (possibly adjusted) task priority - stacksize, // passed stack size is used for supervisor stack - 0, // no user stack: tasks run strictly in supervisor mode - T_LOCAL, // local to the pSOS+ node (does not support pSOS+m) - &tid) // receives task id - != 0) - { - return -1; - } - - // pSOS tasks are passed an array of 4 u_longs - u_long targs[4]; - targs[0] = (u_long) ACE_THREAD_ARGUMENT; - targs[1] = 0; - targs[2] = 0; - targs[3] = 0; - - // start the thread - if (t_start (tid, - T_PREEMPT | // Task can be preempted -// T_NOTSLICE | // Task is not timesliced with other tasks at same priority - T_TSLICE | // Task is timesliced with other tasks at same priority - T_NOASR | // Task level signals disabled - T_SUPV | // Task runs strictly in supervisor mode - T_ISR, // Hardware interrupts are enabled - ACE_THREAD_FUNCTION, // Task entry point - targs) // Task argument(s) - != 0) - { - return -1; - } - - // store the task id in the handle and return success - *thr_handle = tid; - return 0; - -# elif defined (VXWORKS) - // The hard-coded values below are what ::sp () would use. (::sp () - // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to - // 20,000.) stacksize should be an even integer. If a stack is not - // specified, ::taskSpawn () is used so that we can set the - // priority, flags, and stacksize. If a stack is specified, - // ::taskInit ()/::taskActivate() are used. - - // If called with thr_create() defaults, use same default values as ::sp (): - if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100; - // Assumes that there is a floating point coprocessor. As noted - // above, ::sp () hardcodes this, so we should be safe with it. - if (flags == 0) flags = VX_FP_TASK; - if (stacksize == 0) stacksize = 20000; - - const u_int thr_id_provided = - thr_id && *thr_id && (*thr_id)[0] != ACE_THR_ID_ALLOCATED; - - ACE_hthread_t tid; -# if 0 /* Don't support setting of stack, because it doesn't seem to work. */ - if (stack == 0) - { -# else - ACE_UNUSED_ARG (stack); -# endif /* 0 */ - // 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. - tid = ::taskSpawn (thr_id_provided ? *thr_id : 0, - priority, - (int) flags, - (int) stacksize, - thread_args->entry_point (), - (int) thread_args, - 0, 0, 0, 0, 0, 0, 0, 0, 0); -# if 0 /* Don't support setting of stack, because it doesn't seem to work. */ - } - else - { - // If a task name (thr_id) was not supplied, then the task will - // not have a unique name. That's VxWorks' behavior. - - // Carve out a TCB at the beginning of the stack space. The TCB - // occupies 400 bytes with VxWorks 5.3.1/I386. - WIND_TCB *tcb = (WIND_TCB *) stack; - - // The TID is defined to be the address of the TCB. - int status = ::taskInit (tcb, - thr_id_provided ? *thr_id : 0, - priority, - (int) flags, - (char *) stack + sizeof (WIND_TCB), - (int) (stacksize - sizeof (WIND_TCB)), - thread_args->entry_point (), - (int) thread_args, - 0, 0, 0, 0, 0, 0, 0, 0, 0); - - if (status == OK) - { - // The task was successfully initialized, now activate it. - status = ::taskActivate ((ACE_hthread_t) tcb); - } - - tid = status == OK ? (ACE_hthread_t) tcb : ERROR; - } -# endif /* 0 */ - - if (tid == ERROR) - return -1; - else - { - if (! thr_id_provided && thr_id) - { - if (*thr_id && (*thr_id)[0] == ACE_THR_ID_ALLOCATED) - // *thr_id was allocated by the Thread_Manager. ::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 - // . . . - ACE_OS::strncpy (*thr_id + 1, ::taskTcb (tid)->name, 10); - else - // *thr_id was not allocated by the Thread_Manager. - // Pass back the task name in the location pointed to - // by thr_id. - *thr_id = ::taskTcb (tid)->name; - } - // else if the thr_id was provided, there's no need to overwrite - // it with the same value (string). If thr_id is 0, then we can't - // pass the task name back. - - if (thr_handle) - *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_PTHREADS) - ::pthread_exit (status); -# elif defined (ACE_HAS_STHREADS) - ::thr_exit (status); -# elif defined (ACE_HAS_WTHREADS) - // Can't call it here because on NT, the thread is exited - // directly by ACE_Thread_Adapter::invoke (). - // ACE_TSS_Cleanup::instance ()->exit (status); - -# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) - int using_afx = -1; - // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor. - // But without #including ace/Thread_Manager.h, we don't know that. - ACE_OS_Thread_Descriptor *td = - ACE_reinterpret_cast (ACE_OS_Thread_Descriptor *, - ACE_Log_Msg::instance ()->thr_desc ()); - if (td) - using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX); -# endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */ - - // Call TSS destructors. - ACE_OS::cleanup_tss (0 /* not main thread */); - - // Exit the thread. - // 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. -# if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0) - if (using_afx != -1) - { - if (using_afx) - ::AfxEndThread ((DWORD)status); - else - ACE_ENDTHREADEX (status); - } - else - { - // Not spawned by ACE_Thread_Manager, use the old buggy - // version. You should seriously consider using - // ACE_Thread_Manager to spawn threads. The following code is - // know to cause some problem. - CWinThread *pThread = ::AfxGetThread (); - if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ()) - ACE_ENDTHREADEX (status); - else - ::AfxEndThread ((DWORD)status); - } -# else - ACE_ENDTHREADEX (status); -# endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/ - -# elif defined (VXWORKS) - ACE_hthread_t tid; - ACE_OS::thr_self (tid); - *((int *) status) = ::taskDelete (tid); -# elif defined (ACE_PSOS) - ACE_hthread_t tid; - ACE_OS::thr_self (tid); - -# if defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) - // Call TSS destructors. - ACE_OS::cleanup_tss (0 /* not main thread */); -# endif /* ACE_PSOS && ACE_PSOS_HAS_TSS */ - - *((u_long *) status) = ::t_delete (tid); -# endif /* ACE_HAS_PTHREADS */ -# else - ACE_UNUSED_ARG (status); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params) -{ -# if defined (ACE_HAS_STHREADS) || defined (sun) - // Get the class TS and RT class IDs. - ACE_id_t rt_id; - ACE_id_t ts_id; - if (ACE_OS::scheduling_class ("RT", rt_id) == -1 - || ACE_OS::scheduling_class ("TS", ts_id) == -1) - return -1; - - // Get this LWP's scheduling parameters. - pcparms_t pcparms; - // The following is just to avoid Purify warnings about unitialized - // memory reads. - ACE_OS::memset (&pcparms, 0, sizeof pcparms); - pcparms.pc_cid = PC_CLNULL; - - if (ACE_OS::priority_control (P_LWPID, - P_MYID, - PC_GETPARMS, - (char *) &pcparms) == -1) - return -1; - else if (pcparms.pc_cid == rt_id) - { - // RT class. - rtparms_t rtparms; - ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms); - - sched_params.policy (ACE_SCHED_FIFO); - sched_params.priority (rtparms.rt_pri); - sched_params.scope (ACE_SCOPE_THREAD); - ACE_Time_Value quantum (rtparms.rt_tqsecs, - rtparms.rt_tqnsecs == RT_TQINF - ? 0 : rtparms.rt_tqnsecs * 1000); - sched_params.quantum (quantum); - return 0; - } - else if (pcparms.pc_cid == ts_id) - { - /* TS class */ - tsparms_t tsparms; - ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms); - - sched_params.policy (ACE_SCHED_OTHER); - sched_params.priority (tsparms.ts_upri); - sched_params.scope (ACE_SCOPE_THREAD); - return 0; - } - else - return -1; - -# else /* ! ACE_HAS_STHREADS && ! sun */ - ACE_UNUSED_ARG (sched_params); - ACE_NOTSUP_RETURN (-1); -# endif /* ! ACE_HAS_STHREADS && ! sun */ -} - -int -ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params) -{ -# if defined (ACE_HAS_STHREADS) || defined (sun) - ACE_Sched_Params lwp_params (sched_params); - lwp_params.scope (ACE_SCOPE_LWP); - return ACE_OS::sched_params (lwp_params); -# else /* ! ACE_HAS_STHREADS && ! sun */ - ACE_UNUSED_ARG (sched_params); - ACE_NOTSUP_RETURN (-1); -# endif /* ! ACE_HAS_STHREADS && ! sun */ -} - -# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) -int -ACE_OS::thr_setspecific (ACE_OS_thread_key_t key, void *data) -{ - // ACE_TRACE ("ACE_OS::thr_setspecific"); -# if defined (ACE_HAS_THREADS) -# if 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); - return 0; -# endif /* ACE_HAS_STHREADS */ -# else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (data); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} -# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ - -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_TSS_EMULATION) - ACE_KEY_INDEX (key_index, key); - - if (key_index >= ACE_TSS_Emulation::total_keys ()) - { - errno = EINVAL; - data = 0; - return -1; - } - else - { - ACE_TSS_Emulation::ts_object (key) = data; - ACE_TSS_Cleanup::instance ()->key_used (key); - - return 0; - } -# elif 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 */ - -# if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) - ACE_OSCALL_RETURN (::pthread_setspecific (key, data), int, -1); -# else - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setspecific (key, data), - ace_result_), - int, -1); -# endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */ - -# elif defined (ACE_HAS_STHREADS) - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), ace_result_), int, -1); -# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) - ACE_hthread_t tid; - ACE_OS::thr_self (tid); - if (::tsd_setval (key, tid, data) != 0) - return -1; - ACE_TSS_Cleanup::instance ()->key_used (key); - return 0; -# elif defined (ACE_HAS_WTHREADS) - ::TlsSetValue (key, data); - ACE_TSS_Cleanup::instance ()->key_used (key); - return 0; -# else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (data); - 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_HAS_TSS_EMULATION) - return ACE_TSS_Cleanup::instance ()->remove (key); -# elif defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6) - ACE_UNUSED_ARG (key); - ACE_NOTSUP_RETURN (-1); -# elif defined (ACE_HAS_PTHREADS) - return ::pthread_key_delete (key); -# elif defined (ACE_HAS_THR_KEYDELETE) - return ::thr_keydelete (key); -# elif defined (ACE_HAS_STHREADS) - ACE_UNUSED_ARG (key); - ACE_NOTSUP_RETURN (-1); -# elif defined (ACE_HAS_WTHREADS) - // Extract out the thread-specific table instance and free up - // the key and destructor. - ACE_TSS_Cleanup::instance ()->remove (key); - ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1); -# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) - // Extract out the thread-specific table instance and free up - // the key and destructor. - ACE_TSS_Cleanup::instance ()->remove (key); - return (::tsd_delete (key) == 0) ? 0 : -1; -# else - ACE_UNUSED_ARG (key); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_TSS_EMULATION */ -# else - ACE_UNUSED_ARG (key); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -# if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) -int -ACE_OS::thr_keycreate (ACE_OS_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"); -# if defined (ACE_HAS_THREADS) -# if defined (ACE_HAS_PTHREADS) - ACE_UNUSED_ARG (inst); - - -# if defined (ACE_HAS_PTHREADS_DRAFT4) -# if defined (ACE_HAS_STDARG_THR_DEST) - ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1); -# else /* ! ACE_HAS_STDARG_THR_DEST */ - ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1); -# endif /* ! ACE_HAS_STDARG_THR_DEST */ -# elif defined (ACE_HAS_PTHREADS_DRAFT6) - ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1); -# else - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest), - ace_result_), - int, -1); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ -# elif defined (ACE_HAS_STHREADS) - ACE_UNUSED_ARG (inst); - 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 */ -# endif /* ACE_HAS_STHREADS */ -# else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (dest); - ACE_UNUSED_ARG (inst); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} -# endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */ - -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"); -# if defined (ACE_HAS_THREADS) -# if defined (ACE_HAS_TSS_EMULATION) - if (ACE_TSS_Emulation::next_key (*key) == 0) - { - ACE_TSS_Emulation::tss_destructor (*key, dest); - - // 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 - { - errno = EAGAIN; - return -1; - } -# elif defined (ACE_HAS_PTHREADS) - ACE_UNUSED_ARG (inst); - -# if defined (ACE_HAS_PTHREADS_DRAFT4) -# if defined (ACE_HAS_STDARG_THR_DEST) - ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1); -# else /* ! ACE_HAS_STDARG_THR_DEST */ - ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1); -# endif /* ! ACE_HAS_STDARG_THR_DEST */ -# elif defined (ACE_HAS_PTHREADS_DRAFT6) - ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1); -# else - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest), - ace_result_), - int, -1); -# endif /* ACE_HAS_PTHREADS_DRAFT4 */ - -# elif defined (ACE_HAS_STHREADS) - ACE_UNUSED_ARG (inst); - ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest), - ace_result_), - int, -1); -# elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS) - - static u_long unique_name = 0; - void *tsdanchor; - - ++unique_name; - if (::tsd_create (ACE_reinterpret_cast (char *, unique_name), - 0, - TSD_NOALLOC, - (void ****) &tsdanchor, - key) != 0) - { - return -1; - } - - return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst); -# 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 */ -# else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (dest); - ACE_UNUSED_ARG (inst); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_TSS_EMULATION */ -# else - ACE_UNUSED_ARG (key); - ACE_UNUSED_ARG (dest); - ACE_UNUSED_ARG (inst); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::thr_key_used (ACE_thread_key_t key) -{ -# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - ACE_TSS_Cleanup::instance ()->key_used (key); - return 0; -# else - ACE_UNUSED_ARG (key); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */ -} - -int -ACE_OS::thr_key_detach (void *inst) -{ -# if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)) - if (ACE_TSS_Cleanup::lockable ()) - return ACE_TSS_Cleanup::instance()->detach (inst); - else - // We're in static constructor/destructor phase. Don't - // try to use the ACE_TSS_Cleanup instance because its lock - // might not have been constructed yet, or might have been - // destroyed already. Just leak the key . . . - return -1; -# else - ACE_UNUSED_ARG (inst); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */ -} - -void -ACE_OS::unique_name (const void *object, - ACE_TCHAR *name, - size_t length) -{ - // The process ID will provide uniqueness between processes on the - // same machine. The "this" pointer of the <object> will provide - // uniqueness between other "live" objects in the same process. The - // uniqueness of this name is therefore only valid for the life of - // <object>. - ACE_TCHAR temp_name[ACE_UNIQUE_NAME_LEN]; - ACE_OS::sprintf (temp_name, - ACE_TEXT ("%lx%d"), - ACE_reinterpret_cast (long, object), - ACE_static_cast (int, ACE_OS::getpid ())); - ACE_OS::strncpy (name, - temp_name, - length); -} - -int -ACE_OS::argv_to_string (ACE_TCHAR **argv, - ACE_TCHAR *&buf, - int substitute_env_args) -{ - if (argv == 0 || argv[0] == 0) - return 0; - - int buf_len = 0; - - // Determine the length of the buffer. - - for (int i = 0; argv[i] != 0; i++) - { - ACE_TCHAR *temp = 0; - - // Account for environment variables. - if (substitute_env_args - && (argv[i][0] == '$' - && (temp = ACE_OS::getenv (&argv[i][1])) != 0)) - buf_len += ACE_OS::strlen (temp); - else - buf_len += ACE_OS::strlen (argv[i]); - - // Add one for the extra space between each string. - buf_len++; - } - - // Step through all argv params and copy each one into buf; separate - // each param with white space. - - ACE_NEW_RETURN (buf, - ACE_TCHAR[buf_len + 1], - 0); - - // Initial null charater to make it a null string. - buf[0] = '\0'; - ACE_TCHAR *end = buf; - int j; - - for (j = 0; argv[j] != 0; j++) - { - ACE_TCHAR *temp = 0; - - // Account for environment variables. - if (substitute_env_args - && (argv[j][0] == '$' - && (temp = ACE_OS::getenv (&argv[j][1])) != 0)) - end = ACE_OS::strecpy (end, temp); - else - end = ACE_OS::strecpy (end, argv[j]); - - // Replace the null char that strecpy put there with white - // space. - end[-1] = ' '; - } - - // Null terminate the string. - *end = '\0'; - // The number of arguments. - return j; -} - -int -ACE_OS::string_to_argv (ACE_TCHAR *buf, - size_t &argc, - ACE_TCHAR **&argv, - int substitute_env_args) -{ - // Reset the number of arguments - argc = 0; - - if (buf == 0) - return -1; - - ACE_TCHAR *cp = buf; - - // First pass: count arguments. - - // '#' is the start-comment token.. - while (*cp != '\0' && *cp != '#') - { - // Skip whitespace.. - while (ACE_OS::ace_isspace (*cp)) - cp++; - - // Increment count and move to next whitespace.. - if (*cp != '\0') - argc++; - - // Grok quotes.... - if (*cp == '\'' || *cp == '"') - { - ACE_TCHAR quote = *cp; - - // Scan past the string.. - for (cp++; *cp != '\0' && *cp != quote; cp++) - continue; - - // '\0' implies unmatched quote.. - if (*cp == '\0') - { - ACE_ERROR ((LM_ERROR, - ACE_TEXT ("unmatched %c detected\n"), - quote)); - argc--; - break; - } - else - cp++; - } - else // Skip over non-whitespace.... - while (*cp != '\0' && !ACE_OS::ace_isspace (*cp)) - cp++; - } - - // Second pass: copy arguments. - ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ]; - ACE_TCHAR *argp = arg; - - // Make sure that the buffer we're copying into is always large - // enough. - if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ) - ACE_NEW_RETURN (argp, - ACE_TCHAR[cp - buf + 1], - -1); - - // Make a new argv vector of argc + 1 elements. - ACE_NEW_RETURN (argv, - ACE_TCHAR *[argc + 1], - -1); - - ACE_TCHAR *ptr = buf; - - for (size_t i = 0; i < argc; i++) - { - // Skip whitespace.. - while (ACE_OS::ace_isspace (*ptr)) - ptr++; - - // Copy next argument and move to next whitespace.. - if (*ptr == '\'' || *ptr == '"') - { - ACE_TCHAR quote = *ptr++; - - for (cp = argp; - *ptr != '\0' && *ptr != quote; - ptr++, cp++) - { - // @@ We can probably remove this since we ensure it's - // big enough earlier! - ACE_ASSERT (unsigned (cp - argp) < ACE_DEFAULT_ARGV_BUFSIZ); - *cp = *ptr; - } - - *cp = '\0'; - if (*ptr == quote) - ptr++; - } - else - { - for (cp = arg; - *ptr && !ACE_OS::ace_isspace (*ptr); - ptr++, cp++) - { - // @@ We can probably remove this since we ensure it's - // big enough earlier! - ACE_ASSERT (u_int (cp - argp) < ACE_DEFAULT_ARGV_BUFSIZ); - *cp = *ptr; - } - - *cp = '\0'; - } - - // Check for environment variable substitution here. - if (substitute_env_args) - ACE_ALLOCATOR_RETURN (argv[i], - ACE_OS::strenvdup (arg), - -1); - else - ACE_ALLOCATOR_RETURN (argv[i], - ACE_OS::strdup (arg), - -1); - } - - if (argp != arg) - delete [] argp; - - argv[argc] = 0; - return 0; -} - -// Create a contiguous command-line argument buffer with each arg -// separated by spaces. - -pid_t -ACE_OS::fork_exec (ACE_TCHAR *argv[]) -{ -# if defined (ACE_WIN32) - ACE_TCHAR *buf; - - if (ACE_OS::argv_to_string (argv, buf) != -1) - { - PROCESS_INFORMATION process_info; -# if !defined (ACE_HAS_WINCE) - ACE_TEXT_STARTUPINFO startup_info; - ACE_OS::memset ((void *) &startup_info, - 0, - sizeof startup_info); - startup_info.cb = sizeof startup_info; - - if (ACE_TEXT_CreateProcess (0, - buf, - 0, // No process attributes. - 0, // No thread attributes. - TRUE, // Allow handle inheritance. - 0, // Don't create a new console window. - 0, // No environment. - 0, // No current directory. - &startup_info, - &process_info)) -# else - if (ACE_TEXT_CreateProcess (0, - buf, - 0, // No process attributes. - 0, // No thread attributes. - FALSE, // Can's inherit handles on CE - 0, // Don't create a new console window. - 0, // No environment. - 0, // No current directory. - 0, // Can't use startup info on CE - &process_info)) -# endif /* ! ACE_HAS_WINCE */ - { - // Free resources allocated in kernel. - ACE_OS::close (process_info.hThread); - ACE_OS::close (process_info.hProcess); - // Return new process id. - delete [] buf; - return process_info.dwProcessId; - } - } - - // CreateProcess failed. - return -1; -# elif defined (CHORUS) - return ACE_OS::execv (argv[0], argv); -# 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 */ -} - -ssize_t -ACE_OS::read_n (ACE_HANDLE handle, - void *buf, - size_t len, - size_t *bt) -{ - size_t temp; - size_t &bytes_transferred = bt == 0 ? temp : *bt; - ssize_t n; - - for (bytes_transferred = 0; - bytes_transferred < len; - bytes_transferred += n) - { - n = ACE_OS::read (handle, - (char *) buf + bytes_transferred, - len - bytes_transferred); - - if (n == -1 || n == 0) - return n; - } - - return bytes_transferred; -} - -// Write <len> bytes from <buf> to <handle> (uses the <write> -// system call on UNIX and the <WriteFile> call on Win32). - -ssize_t -ACE_OS::write_n (ACE_HANDLE handle, - const void *buf, - size_t len, - size_t *bt) -{ - size_t temp; - size_t &bytes_transferred = bt == 0 ? temp : *bt; - ssize_t n; - - for (bytes_transferred = 0; - bytes_transferred < len; - bytes_transferred += n) - { - n = ACE_OS::write (handle, - (char *) buf + bytes_transferred, - len - bytes_transferred); - - if (n == -1 || n == 0) - return n; - } - - return bytes_transferred; -} - -# if defined (ACE_LACKS_WRITEV) - -// "Fake" writev for operating systems 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 (ACE_static_cast (int, 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_OS::write (handle, buf, length); -# if !defined (ACE_HAS_ALLOCA) - delete [] buf; -# endif /* !defined (ACE_HAS_ALLOCA) */ - return result; -} -# endif /* ACE_LACKS_WRITEV */ - -# if defined (ACE_LACKS_READV) - -// "Fake" readv for operating systems without it. Note that this is -// thread-safe. - -extern "C" int -readv (ACE_HANDLE handle, - ACE_READV_TYPE *iov, - int n) -{ -ACE_TRACE ("readv"); - - ssize_t length = 0; - int i; - - for (i = 0; i < n; i++) - if (ACE_static_cast (int, 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_OS::read (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_LACKS_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 ACE_OS::fcntl (handle, F_FREESP, ACE_reinterpret_cast (long, &fl)); -} -# endif /* ACE_NEEDS_FTRUNCATE */ - -# if defined (ACE_LACKS_MKTEMP) -ACE_TCHAR * -ACE_OS::mktemp (ACE_TCHAR *s) -{ - ACE_TRACE ("ACE_OS::mktemp"); - if (s == 0) - // check for null template string failed! - return 0; - else - { - ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_TEXT ("XXXXXX")); - - if (xxxxxx == 0) - // the template string doesn't contain "XXXXXX"! - return s; - else - { - ACE_TCHAR unique_letter = ACE_TEXT ('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 - // SunOS 5.5 mktemp(). - ACE_OS::sprintf (xxxxxx, - ACE_TEXT ("%05d%c"), - ACE_OS::getpid (), - unique_letter); - while (ACE_OS::stat (s, &sb) >= 0) - { - if (++unique_letter <= ACE_TEXT ('z')) - ACE_OS::sprintf (xxxxxx, - ACE_TEXT ("%05d%c"), - ACE_OS::getpid (), - unique_letter); - else - { - // maximum of 26 unique files per template, per process - ACE_OS::sprintf (xxxxxx, ACE_TEXT ("%s"), ACE_TEXT ("")); - return s; - } - } - } - return 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) -# if defined (ACE_HAS_WINCE) - { - wchar_t fmt[] = ACE_TEXT ("%s failed, WSAGetLastError returned %d"); - wchar_t buf[80]; // @@ Eliminate magic number. - ACE_OS::sprintf (buf, fmt, ACE_TEXT ("WSAStartup"), error); - ::MessageBox (NULL, buf, ACE_TEXT ("WSAStartup failed!"), MB_OK); - } -# else - ACE_OS::fprintf (stderr, - "ACE_OS::socket_init; WSAStartup failed, " - "WSAGetLastError returned %d\n", - error); -# endif /* ACE_HAS_WINCE */ - - ACE_OS::socket_initialized_ = 1; - } -# else - ACE_UNUSED_ARG (version_high); - ACE_UNUSED_ARG (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 (); -# if defined (ACE_HAS_WINCE) - wchar_t fmt[] = ACE_TEXT ("%s failed, WSAGetLastError returned %d"); - wchar_t buf[80]; // @@ Eliminate magic number. - ACE_OS::sprintf (buf, fmt, ACE_TEXT ("WSACleanup"), error); - ::MessageBox (NULL, buf , ACE_TEXT ("WSACleanup failed!"), MB_OK); -# else - ACE_OS::fprintf (stderr, - "ACE_OS::socket_fini; WSACleanup failed, " - "WSAGetLastError returned %d\n", - error); -# endif /* ACE_HAS_WINCE */ - } - 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; - unsigned int argc; - - // Hardcode a program name because the real one isn't available - // through the VxWorks shell. - argv[0] = "ace_main"; - - // 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) - ACE_OS::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 (unsigned int i = argc; i <= MAX_ARGS; ++i) - argv[i] = 0; - } - - // The hard-coded options are what ::sp () uses, except for the - // larger stack size (instead of ::sp ()'s 20000). - const int ret = ::taskSpawn (argv[0], // task name - 100, // task priority - VX_FP_TASK, // task options - ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size - entry, // entry point - argc, // first argument to main () - (int) argv, // second argument to main () - 0, 0, 0, 0, 0, 0, 0, 0); - va_end (pvar); - - // ::taskSpawn () 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 ACE_TCHAR *program_name) -{ - ACE_TRACE ("ACE_OS::fork"); -# if defined (ACE_LACKS_FORK) - ACE_UNUSED_ARG (program_name); - ACE_NOTSUP_RETURN (pid_t (-1)); -# else - pid_t pid = -# if defined (ACE_HAS_STHREADS) - ::fork1 (); -#else - ::fork (); -#endif /* ACE_HAS_STHREADS */ - -#if !defined (ACE_HAS_MINIMAL_ACE_OS) - if (pid == 0) - ACE_LOG_MSG->sync (program_name); -#endif /* ! ACE_HAS_MINIMAL_ACE_OS */ - - return pid; -# endif /* ACE_WIN32 */ -} - -void -ACE_Cleanup::cleanup (void *) -{ - delete this; -} - - -ACE_Cleanup::~ACE_Cleanup (void) -{ -} - -// 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_ID::ACE_Thread_ID (const ACE_Thread_ID &id) - : thread_id_ (id.thread_id_), - thread_handle_ (id.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) const -{ - 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) const -{ - return !(*this == rhs); -} - -// All other platforms have this inlined in OS.i -#if defined (ACE_PSOS) -char * -ACE_OS::inet_ntoa (const struct in_addr addr) -{ - ACE_TRACE ("ACE_OS::inet_ntoa"); - - char *addrstr = new char[17]; - unsigned long ipaddr = ntohl(addr.s_addr); - //printf("Socket address %X, IP address %X.\n",addr.s_addr,ipaddr); - sprintf(addrstr, "%d.%d.%d.%d", - ((ipaddr & 0xff000000) >> 24) & 0x000000ff, - (ipaddr & 0x00ff0000) >> 16, - (ipaddr & 0x0000ff00) >> 8, - (ipaddr & 0x000000ff)); - return addrstr; -} -#endif /* defined (ACE_PSOS) */ - -int -ACE_OS::inet_aton (const ACE_TCHAR *host_name, struct in_addr *addr) -{ - ACE_UINT32 ip_addr = ACE_OS::inet_addr (host_name); - - if (ip_addr == (ACE_UINT32) htonl ((ACE_UINT32) ~0) - // Broadcast addresses are weird... - && ACE_OS::strcmp (host_name, ACE_TEXT ("255.255.255.255")) != 0) - return 0; - else if (addr == 0) - return 0; - else - { -#if !defined(_UNICOS) - ACE_OS::memcpy ((void *) addr, (void *) &ip_addr, sizeof ip_addr); -#else /* ! _UNICOS */ - // on UNICOS, perform assignment to bitfield, since doing the above - // actually puts the address outside of the 32-bit bitfield - addr->s_addr = ip_addr; -#endif /* ! _UNICOS */ - return 1; - } -} - -struct tm * -ACE_OS::localtime_r (const time_t *t, struct tm *res) -{ - ACE_TRACE ("ACE_OS::localtime_r"); -#if defined (ACE_HAS_REENTRANT_FUNCTIONS) -# if defined (DIGITAL_UNIX) - ACE_OSCALL_RETURN (::_Plocaltime_r (t, res), struct tm *, 0); -# elif defined (HPUX_10) - return (::localtime_r (t, res) == 0 ? res : (struct tm *)0); -# else - ACE_OSCALL_RETURN (::localtime_r (t, res), struct tm *, 0); -# endif /* DIGITAL_UNIX */ -#elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME) - ACE_OS_GUARD - - ACE_UNUSED_ARG (res); - struct tm * res_ptr; - ACE_OSCALL (::localtime (t), struct tm *, 0, res_ptr); - if (res_ptr == 0) - return 0; - else - { - *res = *res_ptr; - return res; - } -#else - // @@ Same as ACE_OS::localtime (), you need to implement it - // yourself. - ACE_UNUSED_ARG (t); - ACE_UNUSED_ARG (res); - ACE_NOTSUP_RETURN (0); -#endif /* ACE_HAS_REENTRANT_FUNCTIONS */ -} - -ssize_t -ACE_OS::pread (ACE_HANDLE handle, - void *buf, - size_t nbytes, - off_t offset) -{ -# if defined (ACE_HAS_P_READ_WRITE) -# if defined (ACE_WIN32) - - ACE_OS_GUARD - - // Remember the original file pointer position - DWORD original_position = ::SetFilePointer (handle, - 0, - NULL, - FILE_CURRENT); - - if (original_position == 0xFFFFFFFF) - return -1; - - // Go to the correct position - DWORD altered_position = ::SetFilePointer (handle, - offset, - NULL, - FILE_BEGIN); - if (altered_position == 0xFFFFFFFF) - return -1; - - DWORD bytes_read; - -# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) - - OVERLAPPED overlapped; - overlapped.Internal = 0; - overlapped.InternalHigh = 0; - overlapped.Offset = offset; - overlapped.OffsetHigh = 0; - overlapped.hEvent = 0; - - BOOL result = ::ReadFile (handle, - buf, - nbytes, - &bytes_read, - &overlapped); - - if (result == FALSE) - { - if (::GetLastError () != ERROR_IO_PENDING) - return -1; - - else - { - result = ::GetOverlappedResult (handle, - &overlapped, - &bytes_read, - TRUE); - if (result == FALSE) - return -1; - } - } - -# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ - - BOOL result = ::ReadFile (handle, - buf, - nbytes, - &bytes_read, - NULL); - if (result == FALSE) - return -1; - -# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ - - // Reset the original file pointer position - if (::SetFilePointer (handle, - original_position, - NULL, - FILE_BEGIN) == 0xFFFFFFFF) - return -1; - - return (ssize_t) bytes_read; - -# else /* ACE_WIN32 */ - - return ::pread (handle, buf, nbytes, offset); - -# endif /* ACE_WIN32 */ - -# else /* ACE_HAS_P_READ_WRITE */ - - ACE_OS_GUARD - - // Remember the original file pointer position - off_t original_position = ACE_OS::lseek (handle, - 0, - SEEK_SET); - - if (original_position == -1) - return -1; - - // Go to the correct position - off_t altered_position = ACE_OS::lseek (handle, - offset, - SEEK_SET); - - if (altered_position == -1) - return -1; - - ssize_t bytes_read = ACE_OS::read (handle, - buf, - nbytes); - - if (bytes_read == -1) - return -1; - - if (ACE_OS::lseek (handle, - original_position, - SEEK_SET) == -1) - return -1; - - return bytes_read; - -# endif /* ACE_HAD_P_READ_WRITE */ -} - -ssize_t -ACE_OS::pwrite (ACE_HANDLE handle, - const void *buf, - size_t nbytes, - off_t offset) -{ -# if defined (ACE_HAS_P_READ_WRITE) -# if defined (ACE_WIN32) - - ACE_OS_GUARD - - // Remember the original file pointer position - DWORD original_position = ::SetFilePointer (handle, - 0, - NULL, - FILE_CURRENT); - - if (original_position == 0xFFFFFFFF) - return -1; - - // Go to the correct position - DWORD altered_position = ::SetFilePointer (handle, - offset, - NULL, - FILE_BEGIN); - if (altered_position == 0xFFFFFFFF) - return -1; - - DWORD bytes_written; - -# if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0) - - OVERLAPPED overlapped; - overlapped.Internal = 0; - overlapped.InternalHigh = 0; - overlapped.Offset = offset; - overlapped.OffsetHigh = 0; - overlapped.hEvent = 0; - - BOOL result = ::WriteFile (handle, - buf, - nbytes, - &bytes_written, - &overlapped); - - if (result == FALSE) - { - if (::GetLastError () != ERROR_IO_PENDING) - return -1; - - else - { - result = ::GetOverlappedResult (handle, - &overlapped, - &bytes_written, - TRUE); - if (result == FALSE) - return -1; - } - } - -# else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ - - BOOL result = ::WriteFile (handle, - buf, - nbytes, - &bytes_written, - NULL); - if (result == FALSE) - return -1; - -# endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */ - - // Reset the original file pointer position - if (::SetFilePointer (handle, - original_position, - NULL, - FILE_BEGIN) == 0xFFFFFFFF) - return -1; - - return (ssize_t) bytes_written; - -# else /* ACE_WIN32 */ - - return ::pwrite (handle, buf, nbytes, offset); -# endif /* ACE_WIN32 */ -# else /* ACE_HAS_P_READ_WRITE */ - - ACE_OS_GUARD - - // Remember the original file pointer position - off_t original_position = ACE_OS::lseek (handle, - 0, - SEEK_SET); - if (original_position == -1) - return -1; - - // Go to the correct position - off_t altered_position = ACE_OS::lseek (handle, - offset, - SEEK_SET); - if (altered_position == -1) - return -1; - - ssize_t bytes_written = ACE_OS::write (handle, - buf, - nbytes); - if (bytes_written == -1) - return -1; - - if (ACE_OS::lseek (handle, - original_position, - SEEK_SET) == -1) - return -1; - - return bytes_written; -# endif /* ACE_HAD_P_READ_WRITE */ -} - -ACE_HANDLE -ACE_OS::open (const ACE_TCHAR *filename, - int mode, - int perms, - LPSECURITY_ATTRIBUTES sa) -{ - ACE_TRACE ("ACE_OS::open"); -#if defined (ACE_WIN32) - ACE_UNUSED_ARG (perms); - - DWORD access = GENERIC_READ; - if (ACE_BIT_ENABLED (mode, O_WRONLY)) - access = GENERIC_WRITE; - else if (ACE_BIT_ENABLED (mode, O_RDWR)) - access = GENERIC_READ | GENERIC_WRITE; - - DWORD creation = OPEN_EXISTING; - - if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL)) - creation = CREATE_NEW; - else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC)) - creation = CREATE_ALWAYS; - else if (ACE_BIT_ENABLED (mode, _O_CREAT)) - creation = OPEN_ALWAYS; - else if (ACE_BIT_ENABLED (mode, _O_TRUNC)) - creation = TRUNCATE_EXISTING; - - DWORD flags = 0; - - if (ACE_BIT_ENABLED (mode, _O_TEMPORARY)) - flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY; - - if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH)) - flags |= FILE_FLAG_WRITE_THROUGH; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED)) - flags |= FILE_FLAG_OVERLAPPED; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING)) - flags |= FILE_FLAG_NO_BUFFERING; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS)) - flags |= FILE_FLAG_RANDOM_ACCESS; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN)) - flags |= FILE_FLAG_SEQUENTIAL_SCAN; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE)) - flags |= FILE_FLAG_DELETE_ON_CLOSE; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS)) - flags |= FILE_FLAG_BACKUP_SEMANTICS; - if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS)) - flags |= FILE_FLAG_POSIX_SEMANTICS; - - ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;) - - if (ACE_BIT_ENABLED (mode, _O_APPEND)) - { - ACE_MT - ( - ace_os_monitor_lock = (ACE_thread_mutex_t *) - ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]; - ACE_OS::thread_mutex_lock (ace_os_monitor_lock); - ) - } - - DWORD shared_mode = FILE_SHARE_READ | FILE_SHARE_WRITE; -#if !defined (ACE_HAS_WINCE) // CE doesn't have FILE_SHARE_DELETE - if (ACE_OS::get_win32_versioninfo().dwPlatformId == - VER_PLATFORM_WIN32_NT) - shared_mode |= FILE_SHARE_DELETE; -#endif /* ACE_HAS_WINCE */ - - ACE_HANDLE h = ACE_TEXT_CreateFile (filename, access, - shared_mode, - ACE_OS::default_win32_security_attributes (sa), - creation, - flags, - 0); - - if (ACE_BIT_ENABLED (mode, _O_APPEND)) - { - if (h != ACE_INVALID_HANDLE) - { - ::SetFilePointer (h, 0, 0, FILE_END); - } - - ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);) - } - - if (h == ACE_INVALID_HANDLE) - ACE_FAIL_RETURN (h); - else - return h; -#elif defined (ACE_PSOS) - ACE_UNUSED_ARG (perms); - ACE_UNUSED_ARG (sa); -# if defined (ACE_PSOS_LACKS_PHILE) - ACE_UNUSED_ARG (filename); - return 0; -# else - unsigned long result, handle; - result = ::open_f (&handle, ACE_const_cast(char *, filename), 0); - if (result != 0) - { - // We need to clean this up...not 100% correct! - // To correct we should handle all the cases of TRUNC and CREAT - if ((result == 0x200B) && (ACE_BIT_ENABLED (mode, O_CREAT))) - { - result = ::create_f(ACE_const_cast(char *, filename),1,0); - if (result != 0) - { - errno = result; - return ACE_static_cast (ACE_HANDLE, -1); - } - else //File created...try to open it again - { - result = ::open_f (&handle, ACE_const_cast(char *, filename), 0); - if (result != 0) - { - errno = result; - return ACE_static_cast (ACE_HANDLE, -1); - } - - } - } - else - { - errno = result; - return ACE_static_cast (ACE_HANDLE, -1); - } - } - return ACE_static_cast (ACE_HANDLE, handle); -# endif /* defined (ACE_PSOS_LACKS_PHILE) */ -#else - ACE_UNUSED_ARG (sa); - ACE_OSCALL_RETURN (::open (filename, mode, perms), ACE_HANDLE, -1); -#endif /* ACE_WIN32 */ -} - -# if defined (ACE_LACKS_DIFFTIME) -double -ACE_OS::difftime (time_t t1, time_t t0) -{ - /* return t1 - t0 in seconds */ - struct tm tms[2], *ptms[2], temp; - double seconds; - double days; - int swap = 0; - - /* extract the tm structure from time_t */ - ptms[1] = gmtime_r (&t1, &tms[1]); - if (ptms[1] == 0) return 0.0; - - ptms[0] = gmtime_r (&t0, &tms[0]); - if (ptms[0] == 0) return 0.0; - - /* make sure t1 is > t0 */ - if (tms[1].tm_year < tms[0].tm_year) - swap = 1; - else if (tms[1].tm_year == tms[0].tm_year) - { - if (tms[1].tm_yday < tms[0].tm_yday) - swap = 1; - else if (tms[1].tm_yday == tms[0].tm_yday) - { - if (tms[1].tm_hour < tms[0].tm_hour) - swap = 1; - else if (tms[1].tm_hour == tms[0].tm_hour) - { - if (tms[1].tm_min < tms[0].tm_min) - swap = 1; - else if (tms[1].tm_min == tms[0].tm_min) - { - if (tms[1].tm_sec < tms[0].tm_sec) - swap = 1; - } - } - } - } - - if (swap) - temp = tms[0], tms[0] = tms[1], tms[1] = temp; - - seconds = 0.0; - if (tms[1].tm_year > tms[0].tm_year) - { - // Accumulate the time until t[0] catches up to t[1]'s year. - seconds = 60 - tms[0].tm_sec; - tms[0].tm_sec = 0; - tms[0].tm_min += 1; - seconds += 60 * (60 - tms[0].tm_min); - tms[0].tm_min = 0; - tms[0].tm_hour += 1; - seconds += 60*60 * (24 - tms[0].tm_hour); - tms[0].tm_hour = 0; - tms[0].tm_yday += 1; - -# define ISLEAPYEAR(y) ((y)&3u?0:(y)%25u?1:(y)/25u&12?0:1) - - if (ISLEAPYEAR(tms[0].tm_year)) - seconds += 60*60*24 * (366 - tms[0].tm_yday); - else - seconds += 60*60*24 * (365 - tms[0].tm_yday); - - tms[0].tm_yday = 0; - tms[0].tm_year += 1; - - while (tms[1].tm_year > tms[0].tm_year) - { - if (ISLEAPYEAR(tms[0].tm_year)) - seconds += 60*60*24 * 366; - else - seconds += 60*60*24 * 365; - - tms[0].tm_year += 1; - } - -# undef ISLEAPYEAR - - } - else - { - // Normalize - if (tms[1].tm_sec < tms[0].tm_sec) - { - if (tms[1].tm_min == 0) - { - if (tms[1].tm_hour == 0) - { - tms[1].tm_yday -= 1; - tms[1].tm_hour += 24; - } - tms[1].tm_hour -= 1; - tms[1].tm_min += 60; - } - tms[1].tm_min -= 1; - tms[1].tm_sec += 60; - } - tms[1].tm_sec -= tms[0].tm_sec; - - if (tms[1].tm_min < tms[0].tm_min) - { - if (tms[1].tm_hour == 0) - { - tms[1].tm_yday -= 1; - tms[1].tm_hour += 24; - } - tms[1].tm_hour -= 1; - tms[1].tm_min += 60; - } - tms[1].tm_min -= tms[0].tm_min; - - if (tms[1].tm_hour < tms[0].tm_hour) - { - tms[1].tm_yday -= 1; - tms[1].tm_hour += 24; - } - tms[1].tm_hour -= tms[0].tm_hour; - - tms[1].tm_yday -= tms[0].tm_yday; - } - - // accumulate the seconds - seconds += tms[1].tm_sec; - seconds += 60 * tms[1].tm_min; - seconds += 60*60 * tms[1].tm_hour; - seconds += 60*60*24 * tms[1].tm_yday; - - return seconds; -} -# endif /* ACE_LACKS_DIFFTIME */ - -# if defined (ACE_HAS_WINCE) -ACE_TCHAR * -ACE_OS::ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen) -{ - // buflen must be at least 26 wchar_t long. - if (buflen < 26) // Again, 26 is a magic number. - return 0; - // This is really stupid, converting FILETIME to timeval back and - // forth. It assumes FILETIME and DWORDLONG are the same structure - // internally. - ULARGE_INTEGER _100ns; - _100ns.QuadPart = (DWORDLONG) *clock * 10000 * 1000 - + ACE_Time_Value::FILETIME_to_timval_skew; - FILETIME file_time; - file_time.dwLowDateTime = _100ns.LowPart; - file_time.dwHighDateTime = _100ns.HighPart; - - FILETIME localtime; - SYSTEMTIME systime; - FileTimeToLocalFileTime (&file_time, &localtime); - FileTimeToSystemTime (&localtime, &systime); - ACE_OS::sprintf (buf, ACE_OS_CTIME_R_FMTSTR, - ACE_OS::day_of_week_name[systime.wDayOfWeek], - ACE_OS::month_name[systime.wMonth - 1], - systime.wDay, - systime.wHour, - systime.wMinute, - systime.wSecond, - systime.wYear); - return buf; -} -# endif /* ACE_HAS_WINCE */ - -# if !defined (ACE_HAS_WINCE) -time_t -ACE_OS::mktime (struct tm *t) -{ - ACE_TRACE ("ACE_OS::mktime"); -# if defined (ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME) - ACE_UNUSED_ARG (t); - ACE_NOTSUP_RETURN (-1); -# else -# if defined (ACE_HAS_THREADS) && !defined (ACE_HAS_MT_SAFE_MKTIME) - ACE_OS_GUARD -# endif /* ACE_HAS_THREADS && ! ACE_HAS_MT_SAFE_MKTIME */ - - ACE_OSCALL_RETURN (::mktime (t), time_t, (time_t) -1); -# endif /* ACE_PSOS && ! ACE_PSOS_HAS_TIME */ -} -# endif /* !ACE_HAS_WINCE */ - -# if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T) -int -ACE_OS::rwlock_init (ACE_rwlock_t *rw, - int type, - const ACE_TCHAR *name, - void *arg) -{ - // ACE_TRACE ("ACE_OS::rwlock_init"); -# if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T) - // NT, POSIX, and VxWorks don't support this natively. - ACE_UNUSED_ARG (name); - int result = -1; - - // Since we cannot use the user specified name for all three - // objects, we will create three completely new names. - ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN]; - ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN]; - ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN]; - ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN]; - - ACE_OS::unique_name ((const void *) &rw->lock_, - name1, - ACE_UNIQUE_NAME_LEN); - ACE_OS::unique_name ((const void *) &rw->waiting_readers_, - name2, - ACE_UNIQUE_NAME_LEN); - ACE_OS::unique_name ((const void *) &rw->waiting_writers_, - name3, - ACE_UNIQUE_NAME_LEN); - ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_, - name4, - ACE_UNIQUE_NAME_LEN); - - ACE_condattr_t attributes; - if (ACE_OS::condattr_init (attributes, type) == 0) - { - if (ACE_OS::mutex_init (&rw->lock_, type, name1, - (ACE_mutexattr_t *) arg) == 0 - && ACE_OS::cond_init (&rw->waiting_readers_, - attributes, name2, arg) == 0 - && ACE_OS::cond_init (&rw->waiting_writers_, - attributes, name3, arg) == 0 - && ACE_OS::cond_init (&rw->waiting_important_writer_, - attributes, name4, arg) == 0) - { - // Success! - rw->ref_count_ = 0; - rw->num_waiting_writers_ = 0; - rw->num_waiting_readers_ = 0; - rw->important_writer_ = 0; - result = 0; - } - ACE_OS::condattr_destroy (attributes); - } - - if (result == -1) - { - // Save/restore errno. - ACE_Errno_Guard error (errno); - ACE_OS::mutex_destroy (&rw->lock_); - ACE_OS::cond_destroy (&rw->waiting_readers_); - ACE_OS::cond_destroy (&rw->waiting_writers_); - ACE_OS::cond_destroy (&rw->waiting_important_writer_); - } - return result; -# else - ACE_UNUSED_ARG (rw); - ACE_UNUSED_ARG (type); - ACE_UNUSED_ARG (name); - ACE_UNUSED_ARG (arg); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} -# endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */ - -#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 -// to avoid use before definition if they were inline. - -int -ACE_OS::cond_destroy (ACE_cond_t *cv) -{ - ACE_TRACE ("ACE_OS::cond_destroy"); -# if defined (ACE_HAS_THREADS) -# if defined (ACE_HAS_WTHREADS) - ACE_OS::event_destroy (&cv->waiters_done_); -# elif defined (VXWORKS) || defined (ACE_PSOS) - ACE_OS::sema_destroy (&cv->waiters_done_); -# endif /* VXWORKS */ - ACE_OS::thread_mutex_destroy (&cv->waiters_lock_); - return ACE_OS::sema_destroy (&cv->sema_); -# else - ACE_UNUSED_ARG (cv); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -// @@ The following functions could be inlined if i could figure where -// to put it among the #ifdefs! -int -ACE_OS::condattr_init (ACE_condattr_t &attributes, - int type) -{ - attributes.type = type; - return 0; -} - -int -ACE_OS::condattr_destroy (ACE_condattr_t &) -{ - return 0; -} - -int -ACE_OS::cond_init (ACE_cond_t *cv, - ACE_condattr_t &attributes, - const ACE_TCHAR *name, void *arg) -{ - return ACE_OS::cond_init (cv, attributes.type, name, arg); -} - -int -ACE_OS::cond_init (ACE_cond_t *cv, short type, const ACE_TCHAR *name, void *arg) -{ -ACE_TRACE ("ACE_OS::cond_init"); -# if defined (ACE_HAS_THREADS) - cv->waiters_ = 0; - cv->was_broadcast_ = 0; - - int result = 0; - if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1) - result = -1; - else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1) - result = -1; -# if defined (VXWORKS) || defined (ACE_PSOS) - else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1) -# else - else if (ACE_OS::event_init (&cv->waiters_done_) == -1) -# endif /* VXWORKS */ - result = -1; - return result; -# else - ACE_UNUSED_ARG (cv); - ACE_UNUSED_ARG (type); - ACE_UNUSED_ARG (name); - ACE_UNUSED_ARG (arg); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::cond_signal (ACE_cond_t *cv) -{ -ACE_TRACE ("ACE_OS::cond_signal"); -# if defined (ACE_HAS_THREADS) - // If there aren't any waiters, then this is a no-op. Note that - // this function *must* be called with the <external_mutex> held - // since other wise there is a race condition that can lead to the - // lost wakeup bug... This is needed to ensure that the <waiters_> - // value is not in an inconsistent internal state while being - // updated by another thread. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - int have_waiters = cv->waiters_ > 0; - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - if (have_waiters != 0) - return ACE_OS::sema_post (&cv->sema_); - else - return 0; // No-op -# else - ACE_UNUSED_ARG (cv); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::cond_broadcast (ACE_cond_t *cv) -{ -ACE_TRACE ("ACE_OS::cond_broadcast"); -# if defined (ACE_HAS_THREADS) - // The <external_mutex> must be locked before this call is made. - - // This is needed to ensure that <waiters_> and <was_broadcast_> are - // consistent relative to each other. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - int have_waiters = 0; - - if (cv->waiters_ > 0) - { - // We are broadcasting, even if there is just one waiter... - // Record the fact that we are broadcasting. This helps the - // cond_wait() method know how to optimize itself. Be sure to - // set this with the <waiters_lock_> held. - cv->was_broadcast_ = 1; - have_waiters = 1; - } - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - int result = 0; - if (have_waiters) - { - // Wake up all the waiters. - if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1) - result = -1; - // Wait for all the awakened threads to acquire their part of - // the counting semaphore. -# if defined (VXWORKS) || defined (ACE_PSOS) - else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1) -# else - else if (ACE_OS::event_wait (&cv->waiters_done_) == -1) -# endif /* VXWORKS */ - result = -1; - // This is okay, even without the <waiters_lock_> held because - // no other waiter threads can wake up to access it. - cv->was_broadcast_ = 0; - } - return result; -# else - ACE_UNUSED_ARG (cv); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::cond_wait (ACE_cond_t *cv, - ACE_mutex_t *external_mutex) -{ - ACE_TRACE ("ACE_OS::cond_wait"); -# if defined (ACE_HAS_THREADS) - // Prevent race conditions on the <waiters_> count. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - cv->waiters_++; - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - int result = 0; - -# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) - if (external_mutex->type_ == USYNC_PROCESS) - // This call will automatically release the mutex and wait on the semaphore. - ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_, - cv->sema_, INFINITE, FALSE), - result), - int, -1, result); - else -# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ - { - // We keep the lock held just long enough to increment the count of - // waiters by one. Note that we can't keep it held across the call - // to ACE_OS::sema_wait() since that will deadlock other calls to - // ACE_OS::cond_signal(). - if (ACE_OS::mutex_unlock (external_mutex) != 0) - return -1; - - // Wait to be awakened by a ACE_OS::cond_signal() or - // ACE_OS::cond_broadcast(). - result = ACE_OS::sema_wait (&cv->sema_); - } - - // Reacquire lock to avoid race conditions on the <waiters_> count. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - - // We're ready to return, so there's one less waiter. - cv->waiters_--; - - int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; - - // Release the lock so that other collaborating threads can make - // progress. - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - if (result == -1) - // Bad things happened, so let's just return below. - /* NOOP */; -# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) - else if (external_mutex->type_ == USYNC_PROCESS) - { - if (last_waiter) - - // This call atomically signals the <waiters_done_> event and - // waits until it can acquire the mutex. This is important to - // prevent unfairness. - ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_, - external_mutex->proc_mutex_, - INFINITE, FALSE), - result), - int, -1, result); - else - // We must always regain the <external_mutex>, even when - // errors occur because that's the guarantee that we give to - // our callers. - ACE_OS::mutex_lock (external_mutex); - - return result; - /* NOTREACHED */ - } -# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ - // If we're the last waiter thread during this particular broadcast - // then let all the other threads proceed. - else if (last_waiter) -# if defined (VXWORKS) || defined (ACE_PSOS) - ACE_OS::sema_post (&cv->waiters_done_); -# else - ACE_OS::event_signal (&cv->waiters_done_); -# endif /* VXWORKS */ - - // We must always regain the <external_mutex>, even when errors - // occur because that's the guarantee that we give to our callers. - ACE_OS::mutex_lock (external_mutex); - - return result; -# else - ACE_UNUSED_ARG (cv); - ACE_UNUSED_ARG (external_mutex); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::cond_timedwait (ACE_cond_t *cv, - ACE_mutex_t *external_mutex, - ACE_Time_Value *timeout) -{ - ACE_TRACE ("ACE_OS::cond_timedwait"); -# if defined (ACE_HAS_THREADS) - // Handle the easy case first. - if (timeout == 0) - return ACE_OS::cond_wait (cv, external_mutex); -# if defined (ACE_HAS_WTHREADS) || defined (VXWORKS) || defined (ACE_PSOS) - - // Prevent race conditions on the <waiters_> count. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - cv->waiters_++; - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - int result = 0; - ACE_Errno_Guard error (errno, 0); - int msec_timeout; - - if (timeout->sec () == 0 && timeout->usec () == 0) - msec_timeout = 0; // Do a "poll." - else - { - // Note that we must convert between absolute time (which is - // passed as a parameter) and relative time (which is what - // WaitForSingleObjects() expects). - 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. - if (relative_time < ACE_Time_Value::zero) - msec_timeout = 0; - else - msec_timeout = relative_time.msec (); - } - -# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) - if (external_mutex->type_ == USYNC_PROCESS) - // This call will automatically release the mutex and wait on the - // semaphore. - result = ::SignalObjectAndWait (external_mutex->proc_mutex_, - cv->sema_, - msec_timeout, - FALSE); - else -# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ - { - // We keep the lock held just long enough to increment the count - // of waiters by one. Note that we can't keep it held across - // the call to WaitForSingleObject since that will deadlock - // other calls to ACE_OS::cond_signal(). - if (ACE_OS::mutex_unlock (external_mutex) != 0) - return -1; - - // Wait to be awakened by a ACE_OS::signal() or - // ACE_OS::broadcast(). -# if defined (ACE_WIN32) -# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) - result = ::WaitForSingleObject (cv->sema_, msec_timeout); -# else /* ACE_USES_WINCE_SEMA_SIMULATION */ - // Can't use Win32 API on our simulated semaphores. - result = ACE_OS::sema_wait (&cv->sema_, - ACE_Time_Value (0, msec_timeout * 1000)); -# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ -# elif defined (ACE_PSOS) - // Inline the call to ACE_OS::sema_wait () because it takes an - // ACE_Time_Value argument. Avoid the cost of that conversion . . . - u_long ticks = (KC_TICKS2SEC * msec_timeout) / ACE_ONE_SECOND_IN_MSECS; - //Tick set to 0 tells pSOS to wait forever is SM_WAIT is set. - if(ticks == 0) - result = ::sm_p (cv->sema_.sema_, SM_NOWAIT, ticks); //no timeout - else - result = ::sm_p (cv->sema_.sema_, SM_WAIT, ticks); -# elif defined (VXWORKS) - // Inline the call to ACE_OS::sema_wait () because it takes an - // ACE_Time_Value argument. Avoid the cost of that conversion . . . - int ticks_per_sec = ::sysClkRateGet (); - int ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS; - result = ::semTake (cv->sema_.sema_, ticks); -# endif /* ACE_WIN32 || VXWORKS */ - } - - // Reacquire lock to avoid race conditions. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - cv->waiters_--; - - int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; - - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - -# if defined (ACE_WIN32) - if (result != WAIT_OBJECT_0) - { - switch (result) - { - case WAIT_TIMEOUT: - error = ETIME; - break; - default: - error = ::GetLastError (); - break; - } - result = -1; - } -# elif defined (ACE_PSOS) - if (result != 0) - { - switch (result) - { - case ERR_TIMEOUT: // Timeout occured with SM_WAIT - case ERR_NOMSG: // Didn't acquire semaphore w/ SM_NOWAIT (ticks=0) - error = ETIME; - break; - default: - error = errno; - break; - } - result = -1; - } -# elif defined (VXWORKS) - if (result == ERROR) - { - switch (errno) - { - case S_objLib_OBJ_TIMEOUT: - error = ETIME; - break; - default: - error = errno; - break; - } - result = -1; - } -# endif /* ACE_WIN32 || VXWORKS */ -# if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT) - if (external_mutex->type_ == USYNC_PROCESS) - { - if (last_waiter) - // This call atomically signals the <waiters_done_> event and - // waits until it can acquire the mutex. This is important to - // prevent unfairness. - ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_, - external_mutex->proc_mutex_, - INFINITE, FALSE), - result), - int, -1, result); - else - // We must always regain the <external_Mutex>, even when - // errors occur because that's the guarantee that we give to - // our callers. - ACE_OS::mutex_lock (external_mutex); - - return result; - /* NOTREACHED */ - } -# endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */ - // Note that this *must* be an "if" statement rather than an "else - // if" statement since the caller may have timed out and hence the - // result would have been -1 above. - if (last_waiter) - // Release the signaler/broadcaster if we're the last waiter. -# if defined (ACE_WIN32) - ACE_OS::event_signal (&cv->waiters_done_); -# else - ACE_OS::sema_post (&cv->waiters_done_); -# endif /* ACE_WIN32 */ - - // We must always regain the <external_mutex>, even when errors - // occur because that's the guarantee that we give to our callers. - ACE_OS::mutex_lock (external_mutex); - - return result; -# endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS || ACE_PSOS */ -# else - ACE_UNUSED_ARG (cv); - ACE_UNUSED_ARG (external_mutex); - ACE_UNUSED_ARG (timeout); - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -# if defined (ACE_HAS_WTHREADS) -int -ACE_OS::cond_timedwait (ACE_cond_t *cv, - ACE_thread_mutex_t *external_mutex, - ACE_Time_Value *timeout) -{ - ACE_TRACE ("ACE_OS::cond_timedwait"); -# if defined (ACE_HAS_THREADS) - // Handle the easy case first. - if (timeout == 0) - return ACE_OS::cond_wait (cv, external_mutex); - - // Prevent race conditions on the <waiters_> count. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - cv->waiters_++; - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - int result = 0; - int error = 0; - int msec_timeout; - - if (timeout->sec () == 0 && timeout->usec () == 0) - msec_timeout = 0; // Do a "poll." - else - { - // Note that we must convert between absolute time (which is - // passed as a parameter) and relative time (which is what - // WaitForSingleObjects() expects). - 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. - if (relative_time < ACE_Time_Value::zero) - msec_timeout = 0; - else - msec_timeout = relative_time.msec (); - } - - // We keep the lock held just long enough to increment the count of - // waiters by one. Note that we can't keep it held across the call - // to WaitForSingleObject since that will deadlock other calls to - // ACE_OS::cond_signal(). - if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) - return -1; - - // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast(). -# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) - result = ::WaitForSingleObject (cv->sema_, msec_timeout); -# else - // Can't use Win32 API on simulated semaphores. - result = ACE_OS::sema_wait (&cv->sema_, - ACE_Time_Value (0, msec_timeout * 1000)); - - if (result != WAIT_OBJECT_0 && errno == ETIME) - result = WAIT_TIMEOUT; - -# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ - - // Reacquire lock to avoid race conditions. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - - cv->waiters_--; - - int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; - - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - if (result != WAIT_OBJECT_0) - { - switch (result) - { - case WAIT_TIMEOUT: - error = ETIME; - break; - default: - error = ::GetLastError (); - break; - } - result = -1; - } - - if (last_waiter) - // Release the signaler/broadcaster if we're the last waiter. - ACE_OS::event_signal (&cv->waiters_done_); - - // We must always regain the <external_mutex>, even when errors - // occur because that's the guarantee that we give to our callers. - ACE_OS::thread_mutex_lock (external_mutex); - errno = error; - return result; -# else - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} - -int -ACE_OS::cond_wait (ACE_cond_t *cv, - ACE_thread_mutex_t *external_mutex) -{ - ACE_TRACE ("ACE_OS::cond_wait"); -# if defined (ACE_HAS_THREADS) - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - cv->waiters_++; - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - int result = 0; - int error = 0; - - // We keep the lock held just long enough to increment the count of - // waiters by one. Note that we can't keep it held across the call - // to ACE_OS::sema_wait() since that will deadlock other calls to - // ACE_OS::cond_signal(). - if (ACE_OS::thread_mutex_unlock (external_mutex) != 0) - return -1; - - // Wait to be awakened by a ACE_OS::cond_signal() or - // ACE_OS::cond_broadcast(). -# if !defined (ACE_USES_WINCE_SEMA_SIMULATION) - result = ::WaitForSingleObject (cv->sema_, INFINITE); -# else - // Can't use Win32 API on simulated semaphores. - result = ACE_OS::sema_wait (&cv->sema_); - - if (result != WAIT_OBJECT_0 && errno == ETIME) - result = WAIT_TIMEOUT; - -# endif /* ACE_USES_WINCE_SEMA_SIMULATION */ - - // Reacquire lock to avoid race conditions. - ACE_OS::thread_mutex_lock (&cv->waiters_lock_); - - cv->waiters_--; - - int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0; - - ACE_OS::thread_mutex_unlock (&cv->waiters_lock_); - - if (result != WAIT_OBJECT_0) - { - switch (result) - { - case WAIT_TIMEOUT: - error = ETIME; - break; - default: - error = ::GetLastError (); - break; - } - } - else if (last_waiter) - // Release the signaler/broadcaster if we're the last waiter. - ACE_OS::event_signal (&cv->waiters_done_); - - // We must always regain the <external_mutex>, even when errors - // occur because that's the guarantee that we give to our callers. - ACE_OS::thread_mutex_lock (external_mutex); - - // Reset errno in case mutex_lock() also fails... - errno = error; - return result; -# else - ACE_NOTSUP_RETURN (-1); -# endif /* ACE_HAS_THREADS */ -} -# endif /* ACE_HAS_WTHREADS */ -#endif /* ACE_LACKS_COND_T */ - -void -ACE_OS::exit (int status) -{ - ACE_TRACE ("ACE_OS::exit"); - -#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER) - // Shut down the ACE_Object_Manager, if it had registered its exit_hook. - // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is - // instantiated on the main's stack. ::exit () doesn't destroy it. - if (exit_hook_) - (*exit_hook_) (); -#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */ - -#if !defined (ACE_HAS_WINCE) -# if defined (ACE_WIN32) - ::ExitProcess ((UINT) status); -# elif defined (ACE_PSOSIM) - ::u_exit (status); -# else - ::exit (status); -# endif /* ACE_WIN32 */ -#else - // @@ This is not exactly the same as ExitProcess. But this is the - // closest one I can get. - ::TerminateProcess (::GetCurrentProcess (), status); -#endif /* ACE_HAS_WINCE */ -} - -# if defined (ACE_PSOS) - -// bit masks and shifts for prying info out of the pSOS time encoding -const u_long ACE_PSOS_Time_t::year_mask = 0x0000FFFFul; -const u_long ACE_PSOS_Time_t::month_mask = 0x000000FFul; -const u_long ACE_PSOS_Time_t::day_mask = 0x000000FFul; -const u_long ACE_PSOS_Time_t::hour_mask = 0x0000FFFFul; -const u_long ACE_PSOS_Time_t::minute_mask = 0x000000FFul; -const u_long ACE_PSOS_Time_t::second_mask = 0x000000FFul; -const int ACE_PSOS_Time_t::year_shift = 16; -const int ACE_PSOS_Time_t::month_shift = 8; -const int ACE_PSOS_Time_t::hour_shift = 16; -const int ACE_PSOS_Time_t::minute_shift = 8; -const int ACE_PSOS_Time_t::year_origin = 1900; -const int ACE_PSOS_Time_t::month_origin = 1; - -// maximum number of clock ticks supported -const u_long ACE_PSOS_Time_t::max_ticks = ~0UL; - -ACE_PSOS_Time_t::ACE_PSOS_Time_t (void) - : date_ (0), - time_ (0), - ticks_ (0) -{ -} - -// default ctor: date, time, and ticks all zeroed - -ACE_PSOS_Time_t::ACE_PSOS_Time_t (const timespec_t& t) -{ - struct tm* tm_struct = ACE_OS::gmtime (&(t.tv_sec)); - - // Encode date values from tm struct into pSOS date bit array. - date_ = (ACE_PSOS_Time_t::year_mask & - ACE_static_cast (u_long, - tm_struct->tm_year + ACE_PSOS_Time_t::year_origin)) << - ACE_PSOS_Time_t::year_shift; - date_ |= (ACE_PSOS_Time_t::month_mask & - ACE_static_cast (u_long, - tm_struct->tm_mon + ACE_PSOS_Time_t::month_origin)) << - ACE_PSOS_Time_t::month_shift; - date_ |= ACE_PSOS_Time_t::day_mask & - ACE_static_cast (u_long, tm_struct->tm_mday); - // Encode time values from tm struct into pSOS time bit array. - time_ = (ACE_PSOS_Time_t::hour_mask & - ACE_static_cast (u_long, tm_struct->tm_hour)) << - ACE_PSOS_Time_t::hour_shift; - time_ |= (ACE_PSOS_Time_t::minute_mask & - ACE_static_cast (u_long, tm_struct->tm_min)) << - ACE_PSOS_Time_t::minute_shift; - time_ |= ACE_PSOS_Time_t::second_mask & - ACE_static_cast (u_int, tm_struct->tm_sec); - - // encode nanoseconds as system clock ticks - ticks_ = ACE_static_cast (u_long, - ((ACE_static_cast (double, t.tv_nsec) * - ACE_static_cast (double, KC_TICKS2SEC)) / - ACE_static_cast (double, 1000000000))); - -} - -// ctor from a timespec_t - -ACE_PSOS_Time_t::operator timespec_t (void) -{ - struct tm tm_struct; - - // Decode date and time bit arrays and fill in fields of tm_struct. - - tm_struct.tm_year = - ACE_static_cast (int, (ACE_PSOS_Time_t::year_mask & - (date_ >> ACE_PSOS_Time_t::year_shift))) - - ACE_PSOS_Time_t::year_origin; - tm_struct.tm_mon = - ACE_static_cast (int, (ACE_PSOS_Time_t::month_mask & - (date_ >> ACE_PSOS_Time_t::month_shift))) - - ACE_PSOS_Time_t::month_origin; - tm_struct.tm_mday = - ACE_static_cast (int, (ACE_PSOS_Time_t::day_mask & date_)); - tm_struct.tm_hour = - ACE_static_cast (int, (ACE_PSOS_Time_t::hour_mask & - (time_ >> ACE_PSOS_Time_t::hour_shift))); - tm_struct.tm_min = - ACE_static_cast (int, (ACE_PSOS_Time_t::minute_mask & - (time_ >> ACE_PSOS_Time_t::minute_shift))); - tm_struct.tm_sec = - ACE_static_cast (int, (ACE_PSOS_Time_t::second_mask & time_)); - - // Indicate values we don't know as negative numbers. - tm_struct.tm_wday = -1; - tm_struct.tm_yday = -1; - tm_struct.tm_isdst = -1; - - timespec_t t; - - // Convert calendar time to time struct. - t.tv_sec = ACE_OS::mktime (&tm_struct); - - // Encode nanoseconds as system clock ticks. - t.tv_nsec = ACE_static_cast (long, - ((ACE_static_cast (double, ticks_) * - ACE_static_cast (double, 1000000000)) / - ACE_static_cast (double, KC_TICKS2SEC))); - return t; -} - -// type cast operator (to a timespec_t) - -u_long -ACE_PSOS_Time_t::get_system_time (ACE_PSOS_Time_t& t) -{ - u_long ret_val = 0; - -# if defined (ACE_PSOSIM) // system time is broken in simulator. - timeval tv; - int result = 0; - ACE_OSCALL (::gettimeofday (&tv, 0), int, -1, result); - if (result == -1) - return 1; - - ACE_Time_Value atv (tv); - timespec ts = atv; - ACE_PSOS_Time_t pt (ts); - t.date_ = pt.date_; - t.time_ = pt.time_; - t.ticks_ = pt.ticks_; -# else - ret_val = tm_get (&(t.date_), &(t.time_), &(t.ticks_)); -# endif /* ACE_PSOSIM */ - return ret_val; -} - -// Static member function to get current system time. - -u_long -ACE_PSOS_Time_t::set_system_time (const ACE_PSOS_Time_t& t) -{ - return tm_set (t.date_, t.time_, t.ticks_); -} - -// Static member function to set current system time. - -# if defined (ACE_PSOSIM) - -u_long -ACE_PSOS_Time_t::init_simulator_time (void) -{ - // This is a hack using a direct UNIX system call, because the - // appropriate ACE_OS method ultimately uses the pSOS tm_get - // function, which would fail because the simulator's system time is - // uninitialized (chicken and egg). - timeval t; - int result = 0; - ACE_OSCALL (::gettimeofday (&t, 0), - int, - -1, - result); - - if (result == -1) - return 1; - else - { - ACE_Time_Value tv (t); - timespec ts = tv; - ACE_PSOS_Time_t pt (ts); - u_long ret_val = - ACE_PSOS_Time_t::set_system_time (pt); - return ret_val; - - } -} - -// Static member function to initialize system time, using UNIX calls. - -# endif /* ACE_PSOSIM */ -# endif /* ACE_PSOS && ! ACE_PSOS_DIAB_MIPS */ - -# if defined (__DGUX) && defined (ACE_HAS_THREADS) && defined (_POSIX4A_DRAFT10_SOURCE) -extern "C" int __d6_sigwait (sigset_t *set); - -extern "C" int __d10_sigwait (const sigset_t *set, int *sig) -{ - sigset_t unconst_set = *set; - int caught_sig = __d6_sigwait (&unconst_set); - - if (caught == -1) - return -1; - - *sig = caught_sig; - return 0; -} -# endif /* __DGUX && PTHREADS && _POSIX4A_DRAFT10_SOURCE */ - -# if defined (CHORUS) -extern "C" -void -ace_sysconf_dump (void) -{ - ACE_Time_Value time = ACE_OS::gettimeofday (); - - if (time == -1) - ACE_DEBUG ((LM_DEBUG, - ACE_TEXT ("Cannot get time\n"))); - else - time.dump (); - - ACE_DEBUG ((LM_DEBUG, - "ARG_MAX \t= \t%d\t" - "DELAYTIMER_MAX \t= \t%d\n" - "_MQ_OPEN_MAX \t= \t%d\t" - "_MQ_PRIO_MAX \t= \t%d\n" - "_MQ_DFL_MSGSIZE\t= \t%d\t" - "_MQ_DFL_MAXMSGNB\t= \t%d\n" - "_MQ_PATHMAX \t= \t%d\n" - "NGROUPS_MAX \t= \t%d\t" - "OPEN_MAX \t= \t%d\n" - "PAGESIZE \t= \t%d\n" - "PTHREAD_DESTRUCTOR_ITERATIONS \t= \t%d\n" - "PTHREAD_KEYS_MAX \t= \t%d\n" - "PTHREAD_STACK_MIN \t= \t%d\n" - "PTHREAD_THREADS_MAX \t= \t%d\n" - "SEM_VALUE_MAX \t= \t%d\n" - "SEM_PATHMAX \t= \t%d\n" - "TIMER_MAX \t= \t%d\n" - "TZNAME_MAX \t= \t%d\n" - "_POSIX_MESSAGE_PASSING \t= \t%d\n" - "_POSIX_SEMAPHORES \t= \t%d\n" - "_POSIX_SHARED_MEMORY_OBJECTS \t= \t%d\n" - "_POSIX_THREADS \t= \t%d\n" - "_POSIX_THREAD_ATTR_STACKADDR \t= \t%d\n" - "_POSIX_THREAD_ATTR_STACKSIZE \t= \t%d\n" - "_POSIX_THREAD_PRIORITY_SCHEDULING= \t%d\n" - "_POSIX_THREAD_PRIO_INHERIT \t= \t%d\n" - "_POSIX_THREAD_PRIO_PROTECT \t= \t%d\n" - "_POSIX_THREAD_PROCESS_SHARED \t= \t%d\n" - "_POSIX_THREAD_SAFE_FUNCTIONS \t= \t%d\n" - "_POSIX_TIMERS \t= \t%d\n" - "_POSIX_VERSION \t= \t%d\n", - ACE_OS::sysconf (_SC_ARG_MAX), - ACE_OS::sysconf (_SC_DELAYTIMER_MAX), - ACE_OS::sysconf (_SC_MQ_OPEN_MAX), - ACE_OS::sysconf (_SC_MQ_PRIO_MAX), - ACE_OS::sysconf (_SC_MQ_DFL_MSGSIZE), - ACE_OS::sysconf (_SC_MQ_DFL_MAXMSGNB), - ACE_OS::sysconf (_SC_MQ_PATHMAX), - ACE_OS::sysconf (_SC_NGROUPS_MAX), - ACE_OS::sysconf (_SC_OPEN_MAX), - ACE_OS::sysconf (_SC_PAGESIZE), - ACE_OS::sysconf (_SC_PTHREAD_DESTRUCTOR_ITERATIONS), - ACE_OS::sysconf (_SC_PTHREAD_KEYS_MAX), - ACE_OS::sysconf (_SC_PTHREAD_STACK_MIN), - ACE_OS::sysconf (_SC_PTHREAD_THREADS_MAX), - ACE_OS::sysconf (_SC_SEM_VALUE_MAX), - ACE_OS::sysconf (_SC_SHM_PATHMAX), - ACE_OS::sysconf (_SC_TIMER_MAX), - ACE_OS::sysconf (_SC_TZNAME_MAX), - ACE_OS::sysconf (_SC_MESSAGE_PASSING), - ACE_OS::sysconf (_SC_SEMAPHORES), - ACE_OS::sysconf (_SC_SHARED_MEMORY_OBJECTS), - ACE_OS::sysconf (_SC_THREADS), - ACE_OS::sysconf (_SC_THREAD_ATTR_STACKADDR), - ACE_OS::sysconf (_SC_THREAD_ATTR_STACKSIZE), - ACE_OS::sysconf (_SC_THREAD_PRIORITY_SCHEDULING), - ACE_OS::sysconf (_SC_THREAD_PRIO_INHERIT), - ACE_OS::sysconf (_SC_THREAD_PRIO_PROTECT), - ACE_OS::sysconf (_SC_THREAD_PROCESS_SHARED), - ACE_OS::sysconf (_SC_THREAD_SAFE_FUNCTIONS), - ACE_OS::sysconf (_SC_TIMERS), - ACE_OS::sysconf (_SC_VERSION))); -} -# endif /* CHORUS */ - -# define ACE_OS_PREALLOCATE_OBJECT(TYPE, ID)\ - {\ - TYPE *obj_p = 0;\ - ACE_NEW_RETURN (obj_p, TYPE, -1);\ - preallocated_object[ID] = (void *) obj_p;\ - } -# define ACE_OS_DELETE_PREALLOCATED_OBJECT(TYPE, ID)\ - delete (TYPE *) preallocated_object[ID];\ - preallocated_object[ID] = 0; - -ACE_Object_Manager_Base::ACE_Object_Manager_Base (void) - : object_manager_state_ (OBJ_MAN_UNINITIALIZED) - , dynamically_allocated_ (0) - , next_ (0) -{ -} - -ACE_Object_Manager_Base::~ACE_Object_Manager_Base (void) -{ -#if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) - // Clear the flag so that fini () doesn't delete again. - dynamically_allocated_ = 0; -#endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */ -} - -int -ACE_Object_Manager_Base::starting_up_i () -{ - return object_manager_state_ < OBJ_MAN_INITIALIZED; -} - -int -ACE_Object_Manager_Base::shutting_down_i () -{ - return object_manager_state_ > OBJ_MAN_INITIALIZED; -} - -extern "C" -void -ACE_OS_Object_Manager_Internal_Exit_Hook (void) -{ - if (ACE_OS_Object_Manager::instance_) - ACE_OS_Object_Manager::instance ()->fini (); -} - -ACE_OS_Object_Manager *ACE_OS_Object_Manager::instance_ = 0; - -void *ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_Object_Manager::ACE_OS_PREALLOCATED_OBJECTS] = { 0 }; - -ACE_OS_Object_Manager::ACE_OS_Object_Manager (void) - // default_mask_ isn't initialized, because it's defined by <init>. - : thread_hook_ (0), - exit_info_ () -{ - // If instance_ was not 0, then another ACE_OS_Object_Manager has - // already been instantiated (it is likely to be one initialized by - // way of library/DLL loading). Let this one go through - // construction in case there really is a good reason for it (like, - // ACE is a static/archive library, and this one is the non-static - // instance (with ACE_HAS_NONSTATIC_OBJECT_MANAGER, or the user has - // a good reason for creating a separate one) but the original one - // will be the one retrieved from calls to - // ACE_Object_Manager::instance(). - - // Be sure that no further instances are created via instance (). - if (instance_ == 0) - instance_ = this; - - init (); -} - -ACE_OS_Object_Manager::~ACE_OS_Object_Manager (void) -{ - dynamically_allocated_ = 0; // Don't delete this again in fini() - fini (); -} - -sigset_t * -ACE_OS_Object_Manager::default_mask (void) -{ - return ACE_OS_Object_Manager::instance ()->default_mask_; -} - -ACE_Thread_Hook * -ACE_OS_Object_Manager::thread_hook (void) -{ - return ACE_OS_Object_Manager::instance ()->thread_hook_; -} - -ACE_Thread_Hook * -ACE_OS_Object_Manager::thread_hook (ACE_Thread_Hook *new_thread_hook) -{ - ACE_OS_Object_Manager *os_om = ACE_OS_Object_Manager::instance (); - ACE_Thread_Hook *old_hook = os_om->thread_hook_; - os_om->thread_hook_ = new_thread_hook; - return old_hook; -} - -ACE_OS_Object_Manager * -ACE_OS_Object_Manager::instance (void) -{ - // This function should be called during construction of static - // instances, or before any other threads have been created in the - // process. So, it's not thread safe. - - if (instance_ == 0) - { - ACE_OS_Object_Manager *instance_pointer; - - ACE_NEW_RETURN (instance_pointer, - ACE_OS_Object_Manager, - 0); - ACE_ASSERT (instance_pointer == instance_); - - instance_pointer->dynamically_allocated_ = 1; - - } - - return instance_; -} - -int -ACE_OS_Object_Manager::init (void) -{ - if (starting_up_i ()) - { - // First, indicate that this ACE_OS_Object_Manager instance is being - // initialized. - object_manager_state_ = OBJ_MAN_INITIALIZING; - - if (this == instance_) - { -# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) -# if defined (ACE_HAS_WINCE_BROKEN_ERRNO) - ACE_CE_Errno::init (); -# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ - ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t, ACE_OS_MONITOR_LOCK) - if (ACE_OS::thread_mutex_init (ACE_reinterpret_cast ( - ACE_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_OS_MONITOR_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_OS_MONITOR_LOCK")); - ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t, - ACE_TSS_CLEANUP_LOCK) - if (ACE_OS::recursive_mutex_init (ACE_reinterpret_cast ( - ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_TSS_CLEANUP_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_TSS_CLEANUP_LOCK")); - ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t, - ACE_LOG_MSG_INSTANCE_LOCK) - if (ACE_OS::thread_mutex_init (ACE_reinterpret_cast ( - ACE_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_LOG_MSG_INSTANCE_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK")); -# if defined (ACE_HAS_TSS_EMULATION) - ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t, - ACE_TSS_KEY_LOCK) - if (ACE_OS::recursive_mutex_init (ACE_reinterpret_cast ( - ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_TSS_KEY_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_TSS_KEY_LOCK")); -# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) - ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t, - ACE_TSS_BASE_LOCK) - if (ACE_OS::recursive_mutex_init (ACE_reinterpret_cast ( - ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_TSS_BASE_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_TSS_BASE_LOCK")); -# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ -# endif /* ACE_HAS_TSS_EMULATION */ -# endif /* ACE_MT_SAFE */ - - // Open Winsock (no-op on other platforms). - ACE_OS::socket_init (ACE_WSOCK_VERSION); - - // Register the exit hook, for use by ACE_OS::exit (). - ACE_OS::set_exit_hook (&ACE_OS_Object_Manager_Internal_Exit_Hook); - } - - ACE_NEW_RETURN (default_mask_, sigset_t, -1); - ACE_OS::sigfillset (default_mask_); - - // Finally, indicate that the ACE_OS_Object_Manager instance has - // been initialized. - object_manager_state_ = OBJ_MAN_INITIALIZED; - -# if defined (ACE_WIN32) - ACE_OS::win32_versioninfo_.dwOSVersionInfoSize = - sizeof (OSVERSIONINFO); - ::GetVersionEx (&ACE_OS::win32_versioninfo_); -# endif /* ACE_WIN32 */ - return 0; - } else { - // Had already initialized. - return 1; - } -} - -// Clean up an ACE_OS_Object_Manager. There can be instances of this object -// other than The Instance. This can happen if a user creates one for some -// reason. All objects clean up their per-object information and managed -// objects, but only The Instance cleans up the static preallocated objects. -int -ACE_OS_Object_Manager::fini (void) -{ - if (instance_ == 0 || shutting_down_i ()) - // Too late. Or, maybe too early. Either fini () has already - // been called, or init () was never called. - return object_manager_state_ == OBJ_MAN_SHUT_DOWN ? 1 : -1; - - // No mutex here. Only the main thread should destroy the singleton - // ACE_OS_Object_Manager instance. - - // Indicate that the ACE_OS_Object_Manager instance is being shut - // down. This object manager should be the last one to be shut - // down. - object_manager_state_ = OBJ_MAN_SHUTTING_DOWN; - - // If another Object_Manager has registered for termination, do it. - if (next_) - { - next_->fini (); - next_ = 0; // Protect against recursive calls. - } - - // Call all registered cleanup hooks, in reverse order of - // registration. - exit_info_.call_hooks (); - - // Only clean up preallocated objects when the singleton Instance is being - // destroyed. - if (this == instance_) - { - // Close down Winsock (no-op on other platforms). - ACE_OS::socket_fini (); - -#if ! defined (ACE_HAS_STATIC_PREALLOCATION) - // Cleanup the dynamically preallocated objects. -# if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0) -# if !defined (__Lynx__) - // LynxOS 3.0.0 has problems with this after fork. - if (ACE_OS::thread_mutex_destroy (ACE_reinterpret_cast ( - ACE_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_OS_MONITOR_LOCK")); -# endif /* ! __Lynx__ */ - ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t, - ACE_OS_MONITOR_LOCK) -# if !defined (__Lynx__) - // LynxOS 3.0.0 has problems with this after fork. - if (ACE_OS::recursive_mutex_destroy (ACE_reinterpret_cast ( - ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_TSS_CLEANUP_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_TSS_CLEANUP_LOCK")); -# endif /* ! __Lynx__ */ - ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t, - ACE_TSS_CLEANUP_LOCK) -# if !defined (__Lynx__) - // LynxOS 3.0.0 has problems with this after fork. - if (ACE_OS::thread_mutex_destroy (ACE_reinterpret_cast ( - ACE_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object - [ACE_LOG_MSG_INSTANCE_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK ")); -# endif /* ! __Lynx__ */ - ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t, - ACE_LOG_MSG_INSTANCE_LOCK) -# if defined (ACE_HAS_TSS_EMULATION) -# if !defined (__Lynx__) - // LynxOS 3.0.0 has problems with this after fork. - if (ACE_OS::recursive_mutex_destroy (ACE_reinterpret_cast ( - ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_TSS_KEY_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_TSS_KEY_LOCK")); -# endif /* ! __Lynx__ */ - ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t, - ACE_TSS_KEY_LOCK) -# if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE) -# if !defined (__Lynx__) - // LynxOS 3.0.0 has problems with this after fork. - if (ACE_OS::recursive_mutex_destroy (ACE_reinterpret_cast ( - ACE_recursive_thread_mutex_t *, - ACE_OS_Object_Manager::preallocated_object[ - ACE_TSS_BASE_LOCK])) != 0) - ACE_OS_Object_Manager::print_error_message ( - __LINE__, ACE_TEXT ("ACE_TSS_BASE_LOCK")); -# endif /* ! __Lynx__ */ - ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t, - ACE_TSS_BASE_LOCK) -# endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */ -# endif /* ACE_HAS_TSS_EMULATION */ -# if defined (ACE_HAS_WINCE_BROKEN_ERRNO) - ACE_CE_Errno::fini (); -# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ -# endif /* ACE_MT_SAFE */ -#endif /* ! ACE_HAS_STATIC_PREALLOCATION */ - - ACE_Thread_Exit::is_constructed_ = 0; - // All TSS objects have been destroyed. Reset this flag so - // ACE_Thread_Exit singleton can be created again. - } - - delete default_mask_; - default_mask_ = 0; - - // Indicate that this ACE_OS_Object_Manager instance has been shut down. - object_manager_state_ = OBJ_MAN_SHUT_DOWN; - - if (dynamically_allocated_) - { - delete this; - } - - if (this == instance_) - instance_ = 0; - - return 0; -} - -int ace_exit_hook_marker = 0; - -int -ACE_OS_Object_Manager::at_exit (ACE_EXIT_HOOK func) -{ - return exit_info_.at_exit_i (&ace_exit_hook_marker, - ACE_reinterpret_cast (ACE_CLEANUP_FUNC, func), - 0); -} - -void -ACE_OS_Object_Manager::print_error_message (u_int line_number, - const ACE_TCHAR *message) -{ - // To avoid duplication of these const strings in OS.o. -#if !defined (ACE_HAS_WINCE) - fprintf (stderr, "ace/OS.cpp, line %u: %s ", - line_number, - message); - perror ("failed"); -#else - // @@ Need to use the following information. - ACE_UNUSED_ARG (line_number); - ACE_UNUSED_ARG (message); - - ACE_TCHAR *lpMsgBuf = 0; - ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER | - FORMAT_MESSAGE_FROM_SYSTEM, - NULL, - ::GetLastError (), - MAKELANGID (LANG_NEUTRAL, - SUBLANG_DEFAULT), - // Default language - (ACE_TCHAR *) &lpMsgBuf, - 0, - NULL); - ::MessageBox (NULL, - lpMsgBuf, - ACE_TEXT ("ACE_OS error"), - MB_OK); -#endif -} - -int -ACE_OS_Object_Manager::starting_up (void) -{ - return ACE_OS_Object_Manager::instance_ - ? instance_->starting_up_i () - : 1; -} - -int -ACE_OS_Object_Manager::shutting_down (void) -{ - return ACE_OS_Object_Manager::instance_ - ? instance_->shutting_down_i () - : 1; -} - -#if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) -class ACE_Export ACE_OS_Object_Manager_Manager - // = TITLE - // Ensure that the <ACE_OS_Object_Manager> gets initialized at - // program startup, and destroyed at program termination. - // - // = DESCRIPTION - // Without ACE_HAS_NONSTATIC_OBJECT_MANAGER, a static instance of this - // class is created. Therefore, it gets created before main () - // is called. And it gets destroyed after main () returns. -{ -public: - ACE_OS_Object_Manager_Manager (void); - ~ACE_OS_Object_Manager_Manager (void); - -private: - ACE_thread_t saved_main_thread_id_; - // Save the main thread ID, so that destruction can be suppressed. -}; - -ACE_OS_Object_Manager_Manager::ACE_OS_Object_Manager_Manager (void) - : saved_main_thread_id_ (ACE_OS::thr_self ()) -{ - // Ensure that the Object_Manager gets initialized before any - // application threads have been spawned. Because this will be called - // during construction of static objects, that should always be the - // case. - (void) ACE_OS_Object_Manager::instance (); -} - -ACE_OS_Object_Manager_Manager::~ACE_OS_Object_Manager_Manager (void) -{ - if (ACE_OS::thr_equal (ACE_OS::thr_self (), - saved_main_thread_id_)) - { - delete ACE_OS_Object_Manager::instance_; - ACE_OS_Object_Manager::instance_ = 0; - } - // else if this destructor is not called by the main thread, then do - // not delete the ACE_OS_Object_Manager. That causes problems, on - // WIN32 at least. -} - -static ACE_OS_Object_Manager_Manager ACE_OS_Object_Manager_Manager_instance; -#endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER */ - -# if defined (ACE_HAS_WINCE) -# if defined (ACE_HAS_WINCE_BROKEN_ERRNO) -ACE_CE_Errno *ACE_CE_Errno::instance_ = 0; -DWORD ACE_CE_Errno::errno_key_ = 0xffffffff; - -void -ACE_CE_Errno::init () -{ - ACE_CE_Errno::instance_ = new ACE_CE_Errno (); - ACE_CE_Errno::errno_key_ = TlsAlloc (); -} - -void -ACE_CE_Errno::fini () -{ - TlsFree (ACE_CE_Errno::errno_key_); - delete ACE_CE_Errno::instance_; - ACE_CE_Errno::instance_ = 0; -} -# endif /* ACE_HAS_WINCE_BROKEN_ERRNO */ - -ACE_CE_Bridge *ACE_CE_Bridge::default_text_bridge_ = 0; - -ACE_CE_Bridge::ACE_CE_Bridge (void) - : text_output_ (0), - notification_ (0), - idc_ (0) -{ -} - -ACE_CE_Bridge::ACE_CE_Bridge (HWND w, int n, int i) - : text_output_ (w), - notification_ (n), - idc_ (i) -{ -} - -void -ACE_CE_Bridge::set_window (HWND w, int n, int i) -{ - this->text_output_ = w; - this->notification_ = n; - this->idc_ = i; -} - -ACE_CE_Bridge::~ACE_CE_Bridge (void) -{ - // This method needs to be defined because there seems to be a bug - // in CE's compiler. -} - -void -ACE_CE_Bridge::set_self_default (void) -{ - ACE_CE_Bridge::default_text_bridge_ = this; -} - -int -ACE_CE_Bridge::notification (void) -{ - return this->notification_; -} - -int -ACE_CE_Bridge::idc (void) -{ - return this->idc_; -} - -HWND -ACE_CE_Bridge::window (void) -{ - return this->text_output_; -} - -ACE_CE_Bridge * -ACE_CE_Bridge::get_default_winbridge (void) -{ - return ACE_CE_Bridge::default_text_bridge_; -} - -int -ACE_CE_Bridge::write_msg (const ACE_TCHAR *str) -{ - ACE_TCHAR *s = ACE_OS::strdup (str); - return PostMessage (this->text_output_, - WM_COMMAND, - MAKEWORD (this->idc_, - this->notification_), - (long)((void *) s)); -} - -#if 0 -int -ACE_CE_Bridge::write_msg (CString *s) -{ - // Don't ask! - return PostMessage (this->text_output_, - WM_COMMAND, - MAKEWORD (this->idc_, - this->notification_), - (long)((void *) s)); -} -#endif /* 0 */ - -// **** Warning **** -// You should not use the following function under CE at all. This -// function is used to make Svc_Conf_l.cpp compile under WinCE. It -// might not do what it is expected to do under regular environments. -// **** Warning **** - -# if defined (UNDER_CE) && (UNDER_CE < 211) -void -exit (int status) -{ -# if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER) - // Shut down the ACE_Object_Manager, if it had registered its exit_hook. - // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is - // instantiated on the main's stack. ::exit () doesn't destroy it. - if (exit_hook_) - (*exit_hook_) (); -# endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */ - - ACE_OS::exit (status); -} -# endif /* UNDER_CE && UNDER_CE < 211 */ -# endif /* ACE_HAS_WINCE */ - -// You may be asking yourself, why are we doing this? Well, in winbase.h, -// MS didn't follow their normal Api_FunctionA and Api_FunctionW style, -// so we have to #undef their define to get access to the unicode version. -// And because we don't want to #undef this for the users code, we keep -// this method in the .cpp file. -#if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR) -#undef GetEnvironmentStrings -#endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */ - -ACE_TCHAR * -ACE_OS::getenvstrings (void) -{ -#if defined (ACE_WIN32) -# if defined (ACE_USES_WCHAR) - return ::GetEnvironmentStringsW (); -# else /* ACE_USES_WCHAR */ - return ::GetEnvironmentStrings (); -# endif /* ACE_USES_WCHAR */ -#else /* ACE_WIN32 */ - ACE_NOTSUP_RETURN (0); -#endif /* ACE_WIN32 */ -} - -#if defined (ACE_HAS_STRPTIME) -char * -ACE_OS::strptime (char *buf, const char *format, struct tm *tm) -{ -#if !defined (ACE_HAS_WINCE) -#if defined (ACE_LACKS_NATIVE_STRPTIME) - int bi = 0; - int fi = 0; - int percent = 0; - - if (!buf || !format) - return 0; - - while (format[fi] != '\0') - { - if (percent) - { - percent = 0; - switch (format[fi]) - { - case '%': // an escaped % - if (buf[bi] == '%') - { - fi++; bi++; - } - else - return buf + bi; - break; - - /* not supported yet: weekday via locale long/short names - case 'a': / * weekday via locale * / - / * FALL THROUGH * / - case 'A': / * long/short names * / - break; - */ - - /* not supported yet: - case 'b': / * month via locale * / - / * FALL THROUGH * / - case 'B': / * long/short names * / - / * FALL THROUGH * / - case 'h': - break; - */ - - /* not supported yet: - case 'c': / * %x %X * / - break; - */ - - /* not supported yet: - case 'C': / * date & time - * / - / * locale long format * / - break; - */ - - case 'd': /* day of month (1-31) */ - /* FALL THROUGH */ - case 'e': - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31)) - return buf + bi; - - break; - - case 'D': /* %m/%d/%y */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12)) - return buf + bi; - - fi--; - tm->tm_mon--; - - if (buf[bi] != '/') - return buf + bi; - - bi++; - - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31)) - return buf + bi; - - fi--; - if (buf[bi] != '/') - return buf + bi; - bi++; - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 99)) - return buf + bi; - if (tm->tm_year < 69) - tm->tm_year += 100; - break; - - case 'H': /* hour (0-23) */ - /* FALL THROUGH */ - case 'k': - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23)) - return buf + bi; - break; - - /* not supported yet: - case 'I': / * hour (0-12) * / - / * FALL THROUGH * / - case 'l': - break; - */ - - case 'j': /* day of year (0-366) */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_yday, &bi, &fi, 1, 366)) - return buf + bi; - - tm->tm_yday--; - break; - - case 'm': /* an escaped % */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12)) - return buf + bi; - - tm->tm_mon--; - break; - - case 'M': /* minute (0-59) */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59)) - return buf + bi; - - break; - - /* not supported yet: - case 'p': / * am or pm for locale * / - break; - */ - - /* not supported yet: - case 'r': / * %I:%M:%S %p * / - break; - */ - - case 'R': /* %H:%M */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23)) - return buf + bi; - - fi--; - if (buf[bi] != ':') - return buf + bi; - bi++; - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59)) - return buf + bi; - - break; - - case 'S': /* seconds (0-61) */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61)) - return buf + bi; - break; - - case 'T': /* %H:%M:%S */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23)) - return buf + bi; - - fi--; - if (buf[bi] != ':') - return buf + bi; - bi++; - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59)) - return buf + bi; - - fi--; - if (buf[bi] != ':') - return buf + bi; - bi++; - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61)) - return buf + bi; - - break; - - case 'w': /* day of week (0=Sun-6) */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_wday, &bi, &fi, 0, 6)) - return buf + bi; - - break; - - /* not supported yet: date, based on locale - case 'x': / * date, based on locale * / - break; - */ - - /* not supported yet: - case 'X': / * time, based on locale * / - break; - */ - - case 'y': /* the year - 1900 (0-99) */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 99)) - return buf + bi; - - if (tm->tm_year < 69) - tm->tm_year += 100; - break; - - case 'Y': /* the full year (1999) */ - if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 0)) - return buf + bi; - - tm->tm_year -= 1900; - break; - - default: /* unrecognised */ - return buf + bi; - } /* switch (format[fi]) */ - - } - else - { /* if (percent) */ - if (format[fi] == '%') - { - percent = 1; - fi++; - } - else - { - if (format[fi] == buf[bi]) - { - fi++; - bi++; - } - else - return buf + bi; - } - } /* if (percent) */ - } /* while (format[fi] */ - - return buf + bi; -#else /* ! ACE_LACKS_NATIVE_STRPTIME */ - return ::strptime (buf, - format, - tm); -#endif /* ! ACE_LACKS_NATIVE_STRPTIME */ -#else /* ! ACE_HAS_WINCE */ - ACE_UNUSED_ARG (buf); - ACE_UNUSED_ARG (format); - ACE_UNUSED_ARG (tm); - - ACE_NOTSUP_RETURN (0); -#endif /* ! ACE_HAS_WINCE */ -} - -# if defined (ACE_LACKS_NATIVE_STRPTIME) -int -ACE_OS::strptime_getnum (char *buf, - int *num, - int *bi, - int *fi, - int min, - int max) -{ - int i = 0, tmp = 0; - - while (isdigit (buf[i])) - { - tmp = (tmp * 10) + (buf[i] - '0'); - if (max && (tmp > max)) - return 0; - i++; - } - - if (tmp < min) - return 0; - else if (i) - { - *num = tmp; - (*fi)++; - *bi += i; - return 1; - } - else - return 0; -} -# endif /* ACE_LACKS_NATIVE_STRPTIME */ -#endif /* ACE_HAS_STRPTIME */ |