Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

OS.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // $Id: OS.cpp,v 1.1.1.4.2.5 2003/06/03 22:23:55 michel_j Exp $
00003 
00004 #include "ace/OS.h"
00005 #include "ace/Sched_Params.h"
00006 #include "ace/OS_Thread_Adapter.h"
00007 
00008 #if !defined (ACE_HAS_WINCE)
00009 #include "ace/OS_QoS.h"
00010 #endif  // ACE_HAS_WINCE
00011 
00012 #if defined (VXWORKS)
00013 #include <errnoLib.h>
00014 #endif
00015 
00016 
00017 // Perhaps we should *always* include ace/OS.i in order to make sure
00018 // we can always link against the OS symbols?
00019 #if !defined (ACE_HAS_INLINED_OSCALLS)
00020 # include "ace/OS.i"
00021 #endif /* ACE_HAS_INLINED_OS_CALLS */
00022 
00023 ACE_RCSID(ace, OS, "$Id: OS.cpp,v 1.1.1.4.2.5 2003/06/03 22:23:55 michel_j Exp $")
00024 
00025 #if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
00026 # if defined (ACE_HAS_WINCE)
00027 const wchar_t *ACE_OS::day_of_week_name[] = {ACE_LIB_TEXT ("Sun"), ACE_LIB_TEXT ("Mon"),
00028                                              ACE_LIB_TEXT ("Tue"), ACE_LIB_TEXT ("Wed"),
00029                                              ACE_LIB_TEXT ("Thu"), ACE_LIB_TEXT ("Fri"),
00030                                              ACE_LIB_TEXT ("Sat")};
00031 const wchar_t *ACE_OS::month_name[] = {ACE_LIB_TEXT ("Jan"), ACE_LIB_TEXT ("Feb"),
00032                                        ACE_LIB_TEXT ("Mar"), ACE_LIB_TEXT ("Apr"),
00033                                        ACE_LIB_TEXT ("May"), ACE_LIB_TEXT ("Jun"),
00034                                        ACE_LIB_TEXT ("Jul"), ACE_LIB_TEXT ("Aug"),
00035                                        ACE_LIB_TEXT ("Sep"), ACE_LIB_TEXT ("Oct"),
00036                                        ACE_LIB_TEXT ("Nov"), ACE_LIB_TEXT ("Dec") };
00037 
00038 static const ACE_TCHAR *ACE_OS_CTIME_R_FMTSTR = ACE_LIB_TEXT ("%3s %3s %02d %02d:%02d:%02d %04d\n");
00039 # endif /* ACE_HAS_WINCE */
00040 
00041 # if defined (ACE_WIN32)
00042 OSVERSIONINFO ACE_OS::win32_versioninfo_;
00043 // Cached win32 version information.
00044 
00045 HINSTANCE ACE_OS::win32_resource_module_;
00046 
00047 #  if defined (ACE_OS_HAS_DLL) && (ACE_OS_HAS_DLL == 1) && !defined (ACE_HAS_WINCE)
00048 // This function is called by the OS when the ACE DLL is loaded. We
00049 // use it to determine the default module containing ACE's resources.
00050 BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID)
00051 {
00052   if (reason == DLL_PROCESS_ATTACH)
00053     {
00054 #if defined (ACE_DISABLES_THREAD_LIBRARY_CALLS) && (ACE_DISABLES_THREAD_LIBRARY_CALLS == 1)
00055       ::DisableThreadLibraryCalls (instance);
00056 #endif /* ACE_DISABLES_THREAD_LIBRARY_CALLS */
00057       ACE_OS::set_win32_resource_module(instance);
00058     }
00059   return TRUE;
00060 }
00061 #  endif /* ACE_OS_HAS_DLL && ACE_OS_HAS_DLL == 1 */
00062 # endif /* ACE_WIN32 */
00063 
00064 /**
00065  * @class ACE_OS_Thread_Mutex_Guard
00066  *
00067  * This data structure is meant to be used within an ACE_OS
00068  * function.  It performs automatic aquisition and release of
00069  * an ACE_thread_mutex_t.
00070  *
00071  * For internal use only by ACE_OS.
00072  */
00073 class ACE_OS_Thread_Mutex_Guard
00074 {
00075 public:
00076   /// Implicitly and automatically acquire the lock.
00077   ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m);
00078 
00079   /// Implicitly release the lock.
00080   ~ACE_OS_Thread_Mutex_Guard (void);
00081 
00082   /// Explicitly acquire the lock.
00083   int acquire (void);
00084 
00085   /// Explicitly release the lock.
00086   int release (void);
00087 
00088 protected:
00089   /// Reference to the mutex.
00090   ACE_thread_mutex_t &lock_;
00091 
00092   /// Keeps track of whether we acquired the lock or failed.
00093   int owner_;
00094 
00095   // = Prevent assignment and initialization.
00096   ACE_OS_Thread_Mutex_Guard &operator= (const ACE_OS_Thread_Mutex_Guard &);
00097   ACE_OS_Thread_Mutex_Guard (const ACE_OS_Thread_Mutex_Guard &);
00098 };
00099 
00100 #if defined (ACE_IS_SPLITTING)
00101 # define ACE_SPECIAL_INLINE
00102 #else
00103 # define ACE_SPECIAL_INLINE inline
00104 #endif
00105 
00106 ACE_SPECIAL_INLINE
00107 int
00108 ACE_OS_Thread_Mutex_Guard::acquire (void)
00109 {
00110   return owner_ = ACE_OS::thread_mutex_lock (&lock_);
00111 }
00112 
00113 ACE_SPECIAL_INLINE
00114 int
00115 ACE_OS_Thread_Mutex_Guard::release (void)
00116 {
00117   if (owner_ == -1)
00118     return 0;
00119   else
00120     {
00121       owner_ = -1;
00122       return ACE_OS::thread_mutex_unlock (&lock_);
00123     }
00124 }
00125 
00126 ACE_SPECIAL_INLINE
00127 ACE_OS_Thread_Mutex_Guard::ACE_OS_Thread_Mutex_Guard (ACE_thread_mutex_t &m)
00128    : lock_ (m)
00129 {
00130   acquire ();
00131 }
00132 
00133 ACE_OS_Thread_Mutex_Guard::~ACE_OS_Thread_Mutex_Guard ()
00134 {
00135   release ();
00136 }
00137 
00138 /**
00139  * @class ACE_OS_Recursive_Thread_Mutex_Guard
00140  *
00141  * @brief For internal use only by ACE_OS.
00142  *
00143  * This data structure is meant to be used within an ACE_OS
00144  * function.  It performs automatic aquisition and release of
00145  * an ACE_recursive_thread_mutex_t.
00146  */
00147 class ACE_OS_Recursive_Thread_Mutex_Guard
00148 {
00149 public:
00150   /// Implicitly and automatically acquire the lock.
00151   ACE_OS_Recursive_Thread_Mutex_Guard (ACE_recursive_thread_mutex_t &m);
00152 
00153   /// Implicitly release the lock.
00154   ~ACE_OS_Recursive_Thread_Mutex_Guard (void);
00155 
00156   /// Explicitly acquire the lock.
00157   int acquire (void);
00158 
00159   /// Explicitly release the lock.
00160   int release (void);
00161 
00162 protected:
00163   /// Reference to the mutex.
00164   ACE_recursive_thread_mutex_t &lock_;
00165 
00166   /// Keeps track of whether we acquired the lock or failed.
00167   int owner_;
00168 
00169   // = Prevent assignment and initialization.
00170   ACE_OS_Recursive_Thread_Mutex_Guard &operator= (
00171     const ACE_OS_Recursive_Thread_Mutex_Guard &);
00172   ACE_OS_Recursive_Thread_Mutex_Guard (
00173     const ACE_OS_Recursive_Thread_Mutex_Guard &);
00174 };
00175 
00176 ACE_SPECIAL_INLINE
00177 int
00178 ACE_OS_Recursive_Thread_Mutex_Guard::acquire (void)
00179 {
00180   return owner_ = ACE_OS::recursive_mutex_lock (&lock_);
00181 }
00182 
00183 ACE_SPECIAL_INLINE
00184 int
00185 ACE_OS_Recursive_Thread_Mutex_Guard::release (void)
00186 {
00187   if (owner_ == -1)
00188     return 0;
00189   else
00190     {
00191       owner_ = -1;
00192       return ACE_OS::recursive_mutex_unlock (&lock_);
00193     }
00194 }
00195 
00196 ACE_SPECIAL_INLINE
00197 ACE_OS_Recursive_Thread_Mutex_Guard::ACE_OS_Recursive_Thread_Mutex_Guard (
00198   ACE_recursive_thread_mutex_t &m)
00199    : lock_ (m),
00200      owner_ (-1)
00201 {
00202   acquire ();
00203 }
00204 
00205 ACE_OS_Recursive_Thread_Mutex_Guard::~ACE_OS_Recursive_Thread_Mutex_Guard ()
00206 {
00207   release ();
00208 }
00209 
00210 #define ACE_OS_GUARD \
00211   ACE_OS_Thread_Mutex_Guard ace_os_guard__ (*(ACE_thread_mutex_t *) \
00212     ACE_OS_Object_Manager::preallocated_object[ \
00213       ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
00214 
00215 #define ACE_TSS_CLEANUP_GUARD \
00216   ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_cleanup_guard__ (*(ACE_recursive_thread_mutex_t *) \
00217     ACE_OS_Object_Manager::preallocated_object[ \
00218       ACE_OS_Object_Manager::ACE_TSS_CLEANUP_LOCK]);
00219 
00220 #define ACE_TSS_BASE_GUARD \
00221   ACE_OS_Recursive_Thread_Mutex_Guard ace_tss_base_guard__ (*(ACE_recursive_thread_mutex_t *) \
00222     ACE_OS_Object_Manager::preallocated_object[ \
00223       ACE_OS_Object_Manager::ACE_TSS_BASE_LOCK]);
00224 
00225 
00226 # if defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS)
00227 int
00228 ACE_OS::netdb_acquire (void)
00229 {
00230   return ACE_OS::thread_mutex_lock ((ACE_thread_mutex_t *)
00231     ACE_OS_Object_Manager::preallocated_object[
00232       ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
00233 }
00234 
00235 int
00236 ACE_OS::netdb_release (void)
00237 {
00238   return ACE_OS::thread_mutex_unlock ((ACE_thread_mutex_t *)
00239     ACE_OS_Object_Manager::preallocated_object[
00240       ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK]);
00241 }
00242 # endif /* defined (ACE_LACKS_NETDB_REENTRANT_FUNCTIONS) */
00243 #else  /* ! ACE_MT_SAFE */
00244 # define ACE_OS_GUARD
00245 # define ACE_TSS_CLEANUP_GUARD
00246 # define ACE_TSS_BASE_GUARD
00247 #endif /* ! ACE_MT_SAFE */
00248 
00249 ACE_EXIT_HOOK ACE_OS::exit_hook_ = 0;
00250 
00251 ACE_Cleanup_Info::ACE_Cleanup_Info (void)
00252   : object_ (0),
00253     cleanup_hook_ (0),
00254     param_ (0)
00255 {
00256 }
00257 
00258 int
00259 ACE_Cleanup_Info::operator== (const ACE_Cleanup_Info &o) const
00260 {
00261   return o.object_ == this->object_
00262     && o.cleanup_hook_ == this->cleanup_hook_
00263     && o.param_ == this->param_;
00264 }
00265 
00266 int
00267 ACE_Cleanup_Info::operator!= (const ACE_Cleanup_Info &o) const
00268 {
00269   return !(*this == o);
00270 }
00271 
00272 /**
00273  * @class ACE_Cleanup_Info_Node
00274  *
00275  * @brief For maintaining a list of ACE_Cleanup_Info items.
00276  *
00277  * For internal use by ACE_Object_Manager.
00278  */
00279 class ACE_Cleanup_Info_Node
00280 {
00281 public:
00282   ACE_Cleanup_Info_Node (void);
00283   ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info,
00284                          ACE_Cleanup_Info_Node *next);
00285   ~ACE_Cleanup_Info_Node (void);
00286   ACE_Cleanup_Info_Node *insert (const ACE_Cleanup_Info &);
00287 private:
00288   ACE_Cleanup_Info cleanup_info_;
00289   ACE_Cleanup_Info_Node *next_;
00290 
00291   friend class ACE_OS_Exit_Info;
00292 };
00293 
00294 ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (void)
00295   : cleanup_info_ (),
00296     next_ (0)
00297 {
00298 }
00299 
00300 ACE_Cleanup_Info_Node::ACE_Cleanup_Info_Node (const ACE_Cleanup_Info &new_info,
00301                                               ACE_Cleanup_Info_Node *next)
00302   : cleanup_info_ (new_info),
00303     next_ (next)
00304 {
00305 }
00306 
00307 ACE_Cleanup_Info_Node::~ACE_Cleanup_Info_Node (void)
00308 {
00309   delete next_;
00310 }
00311 
00312 ACE_Cleanup_Info_Node *
00313 ACE_Cleanup_Info_Node::insert (const ACE_Cleanup_Info &new_info)
00314 {
00315   ACE_Cleanup_Info_Node *new_node;
00316 
00317   ACE_NEW_RETURN (new_node,
00318                   ACE_Cleanup_Info_Node (new_info, this),
00319                   0);
00320 
00321   return new_node;
00322 }
00323 
00324 ACE_OS_Exit_Info::ACE_OS_Exit_Info (void)
00325 {
00326   ACE_NEW (registered_objects_, ACE_Cleanup_Info_Node);
00327 }
00328 
00329 ACE_OS_Exit_Info::~ACE_OS_Exit_Info (void)
00330 {
00331   delete registered_objects_;
00332   registered_objects_ = 0;
00333 }
00334 
00335 int
00336 ACE_OS_Exit_Info::at_exit_i (void *object,
00337                              ACE_CLEANUP_FUNC cleanup_hook,
00338                              void *param)
00339 {
00340   ACE_Cleanup_Info new_info;
00341   new_info.object_ = object;
00342   new_info.cleanup_hook_ = cleanup_hook;
00343   new_info.param_ = param;
00344 
00345   // Return -1 and sets errno if unable to allocate storage.  Enqueue
00346   // at the head and dequeue from the head to get LIFO ordering.
00347 
00348   ACE_Cleanup_Info_Node *new_node;
00349 
00350   if ((new_node = registered_objects_->insert (new_info)) == 0)
00351     return -1;
00352   else
00353     {
00354       registered_objects_ = new_node;
00355       return 0;
00356     }
00357 }
00358 
00359 int
00360 ACE_OS_Exit_Info::find (void *object)
00361 {
00362   // Check for already in queue, and return 1 if so.
00363   for (ACE_Cleanup_Info_Node *iter = registered_objects_;
00364        iter  &&  iter->next_ != 0;
00365        iter = iter->next_)
00366     {
00367       if (iter->cleanup_info_.object_ == object)
00368         {
00369           // The object has already been registered.
00370           return 1;
00371         }
00372     }
00373 
00374   return 0;
00375 }
00376 
00377 void
00378 ACE_OS_Exit_Info::call_hooks ()
00379 {
00380   // Call all registered cleanup hooks, in reverse order of
00381   // registration.
00382   for (ACE_Cleanup_Info_Node *iter = registered_objects_;
00383        iter  &&  iter->next_ != 0;
00384        iter = iter->next_)
00385     {
00386       ACE_Cleanup_Info &info = iter->cleanup_info_;
00387       if (info.cleanup_hook_ == ACE_reinterpret_cast (ACE_CLEANUP_FUNC,
00388                                                       ace_cleanup_destroyer))
00389         // The object is an ACE_Cleanup.
00390         ace_cleanup_destroyer (ACE_reinterpret_cast (ACE_Cleanup *,
00391                                                      info.object_),
00392                                info.param_);
00393       else if (info.object_ == &ace_exit_hook_marker)
00394         // The hook is an ACE_EXIT_HOOK.
00395         (* ACE_reinterpret_cast (ACE_EXIT_HOOK, info.cleanup_hook_)) ();
00396       else
00397         (*info.cleanup_hook_) (info.object_, info.param_);
00398     }
00399 }
00400 
00401 ACE_Countdown_Time::ACE_Countdown_Time (ACE_Time_Value *max_wait_time)
00402   : max_wait_time_ (max_wait_time),
00403     stopped_ (0)
00404 {
00405   this->start ();
00406 }
00407 
00408 ACE_Countdown_Time::~ACE_Countdown_Time (void)
00409 {
00410   this->stop ();
00411 }
00412 
00413 #if defined (ACE_HAS_POWERPC_TIMER) && defined (ghs)
00414 void
00415 ACE_OS::readPPCTimeBase (u_long &most, u_long &least)
00416 {
00417   ACE_OS_TRACE ("ACE_OS::readPPCTimeBase");
00418 
00419   // This function can't be inline because it depends on the arguments
00420   // being in particular registers (r3 and r4), in conformance with the
00421   // EABI standard.  It would be nice if we knew how to put the variable
00422   // names directly into the assembler instructions . . .
00423   asm("aclock:");
00424   asm("mftb  r5,TBU");
00425   asm("mftb  r6,TBL");
00426   asm("mftb  r7,TBU");
00427   asm("cmpw  r5,r7");
00428   asm("bne   aclock");
00429 
00430   asm("stw r5, 0(r3)");
00431   asm("stw r6, 0(r4)");
00432 }
00433 #elif defined (ACE_HAS_POWERPC_TIMER) && defined (__GNUG__)
00434 void
00435 ACE_OS::readPPCTimeBase (u_long &most, u_long &least)
00436 {
00437   ACE_OS_TRACE ("ACE_OS::readPPCTimeBase");
00438 
00439   // This function can't be inline because it defines a symbol,
00440   // aclock.  If there are multiple calls to the function in a
00441   // compilation unit, then that symbol would be multiply defined if
00442   // the function was inline.
00443   asm volatile ("aclock:\n"
00444                 "mftbu 5\n"     /* upper time base register */
00445                 "mftb 6\n"      /* lower time base register */
00446                 "mftbu 7\n"     /* upper time base register */
00447                 "cmpw 5,7\n" /* check for rollover of upper */
00448                 "bne aclock\n"
00449                 "stw 5,%0\n"                        /* most */
00450                 "stw 6,%1"                         /* least */
00451                 : "=m" (most), "=m" (least)      /* outputs */
00452                 :                              /* no inputs */
00453                 : "5", "6", "7", "memory"    /* constraints */);
00454 }
00455 #endif /* ACE_HAS_POWERPC_TIMER  &&  (ghs or __GNUG__) */
00456 
00457 #if defined (ACE_WIN32) || defined (VXWORKS) || defined (CHORUS) || defined (ACE_PSOS)
00458 // Don't inline on those platforms because this function contains
00459 // string literals, and some compilers, e.g., g++, don't handle those
00460 // efficiently in unused inline functions.
00461 int
00462 ACE_OS::uname (ACE_utsname *name)
00463 {
00464   ACE_OS_TRACE ("ACE_OS::uname");
00465 # if defined (ACE_WIN32)
00466   size_t maxnamelen = sizeof name->nodename;
00467   ACE_OS::strcpy (name->sysname,
00468                   ACE_LIB_TEXT ("Win32"));
00469 
00470   OSVERSIONINFO vinfo;
00471   vinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
00472   ::GetVersionEx (&vinfo);
00473 
00474   SYSTEM_INFO sinfo;
00475 #   if defined (ACE_HAS_PHARLAP)
00476   // PharLap doesn't do GetSystemInfo.  What's really wanted is the
00477   // CPU architecture, so we can get that with EtsGetSystemInfo. Fill
00478   // in what's wanted in the SYSTEM_INFO structure, and carry on. Note
00479   // that the CPU type values in EK_KERNELINFO have the same values
00480   // are the ones defined for SYSTEM_INFO.
00481   EK_KERNELINFO ets_kern;
00482   EK_SYSTEMINFO ets_sys;
00483   EtsGetSystemInfo (&ets_kern, &ets_sys);
00484   sinfo.wProcessorLevel = ACE_static_cast (WORD, ets_kern.CpuType);
00485   sinfo.wProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL;
00486   sinfo.dwProcessorType = ets_kern.CpuType * 100 + 86;
00487 #   else
00488   ::GetSystemInfo(&sinfo);
00489 
00490   ACE_OS::strcpy (name->sysname, ACE_LIB_TEXT ("Win32"));
00491 #   endif /* ACE_HAS_PHARLAP */
00492 
00493   const ACE_TCHAR* unknown = ACE_LIB_TEXT ("???");
00494 
00495   if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
00496     {
00497       // Get information from the two structures
00498       ACE_OS::sprintf (name->release,
00499 #   if defined (ACE_HAS_WINCE)
00500                        ACE_LIB_TEXT ("Windows CE %d.%d"),
00501 #   else
00502                        ACE_LIB_TEXT ("Windows NT %d.%d"),
00503 #   endif /* ACE_HAS_WINCE */
00504                        (int) vinfo.dwMajorVersion,
00505                        (int) vinfo.dwMinorVersion);
00506       ACE_OS::sprintf (name->version,
00507                        ACE_LIB_TEXT ("Build %d %s"),
00508                        (int) vinfo.dwBuildNumber,
00509                        vinfo.szCSDVersion);
00510 
00511       // We have to make sure that the size of (processor + subtype)
00512       // is not greater than the size of name->machine.  So we give
00513       // half the space to the processor and half the space to
00514       // subtype.  The -1 is necessary for because of the space
00515       // between processor and subtype in the machine name.
00516       const int bufsize = ((sizeof (name->machine) / sizeof (ACE_TCHAR)) / 2) - 1;
00517       ACE_TCHAR processor[bufsize] = ACE_LIB_TEXT ("Unknown");
00518       ACE_TCHAR subtype[bufsize] = ACE_LIB_TEXT ("Unknown");
00519 
00520 #   if defined (ghs)
00521     WORD arch = sinfo.u.s.wProcessorArchitecture;
00522 #   else
00523     WORD arch = sinfo.wProcessorArchitecture;
00524 #   endif
00525 
00526       switch (arch)
00527         {
00528         case PROCESSOR_ARCHITECTURE_INTEL:
00529           ACE_OS::strcpy (processor, ACE_LIB_TEXT ("Intel"));
00530           if (sinfo.wProcessorLevel == 3)
00531             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("80386"));
00532           else if (sinfo.wProcessorLevel == 4)
00533             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("80486"));
00534           else if (sinfo.wProcessorLevel == 5)
00535             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("Pentium"));
00536           else if (sinfo.wProcessorLevel == 6)
00537             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("Pentium Pro"));
00538           else if (sinfo.wProcessorLevel == 7)  // I'm guessing here
00539             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("Pentium II"));
00540           break;
00541         case PROCESSOR_ARCHITECTURE_MIPS:
00542           ACE_OS::strcpy (processor, ACE_LIB_TEXT ("MIPS"));
00543           ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("R4000"));
00544           break;
00545         case PROCESSOR_ARCHITECTURE_ALPHA:
00546           ACE_OS::strcpy (processor, ACE_LIB_TEXT ("Alpha"));
00547           ACE_OS::sprintf (subtype, ACE_LIB_TEXT ("%d"), sinfo.wProcessorLevel);
00548           break;
00549         case PROCESSOR_ARCHITECTURE_PPC:
00550           ACE_OS::strcpy (processor, ACE_LIB_TEXT ("PPC"));
00551           if (sinfo.wProcessorLevel == 1)
00552             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("601"));
00553           else if (sinfo.wProcessorLevel == 3)
00554             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("603"));
00555           else if (sinfo.wProcessorLevel == 4)
00556             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("604"));
00557           else if (sinfo.wProcessorLevel == 6)
00558             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("603+"));
00559           else if (sinfo.wProcessorLevel == 9)
00560             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("804+"));
00561           else if (sinfo.wProcessorLevel == 20)
00562             ACE_OS::strcpy (subtype, ACE_LIB_TEXT ("620"));
00563           break;
00564 #     if defined PROCESSOR_ARCHITECTURE_IA64
00565         case PROCESSOR_ARCHITECTURE_IA64:
00566           ACE_OS_String::strcpy (processor, ACE_LIB_TEXT ("Itanium"));
00567           ACE_OS::sprintf (subtype, ACE_LIB_TEXT ("%d"), sinfo.wProcessorLevel);
00568           break;
00569 #     endif
00570         case PROCESSOR_ARCHITECTURE_UNKNOWN:
00571         default:
00572           // @@ We could provide WinCE specific info here.  But let's
00573           //    defer that to some later point.
00574           ACE_OS::strcpy (processor, ACE_LIB_TEXT ("Unknown"));
00575           break;
00576         }
00577       ACE_OS::sprintf (name->machine,
00578                        ACE_LIB_TEXT ("%s %s"),
00579                        processor, subtype);
00580     }
00581   else if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
00582     {
00583       if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 0)
00584         {
00585           ACE_OS::strcpy (name->release, ACE_LIB_TEXT ("Windows 95"));
00586           if (vinfo.szCSDVersion[1] == 'C')
00587             ACE_OS::strcat (name->release, ACE_LIB_TEXT (" OSR2"));
00588         }
00589       else if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 10)
00590         {
00591           ACE_OS::strcpy (name->release, ACE_LIB_TEXT ("Windows 98"));
00592           if (vinfo.szCSDVersion[1] == 'A')
00593             ACE_OS::strcat (name->release, ACE_LIB_TEXT (" SE"));
00594         }
00595       else if (vinfo.dwMajorVersion == 4 && vinfo.dwMinorVersion == 90)
00596         {
00597           ACE_OS::strcpy (name->release, ACE_LIB_TEXT ("Windows Me"));
00598         }
00599       else
00600         {
00601           ACE_OS::strcpy (name->release, unknown);
00602         }
00603 
00604       ACE_OS::sprintf (name->version, ACE_LIB_TEXT ("%d"),
00605                        LOWORD (vinfo.dwBuildNumber));
00606       if (sinfo.dwProcessorType == PROCESSOR_INTEL_386)
00607         ACE_OS::strcpy (name->machine, ACE_LIB_TEXT ("Intel 80386"));
00608       else if (sinfo.dwProcessorType == PROCESSOR_INTEL_486)
00609         ACE_OS::strcpy (name->machine, ACE_LIB_TEXT ("Intel 80486"));
00610       else if (sinfo.dwProcessorType == PROCESSOR_INTEL_PENTIUM)
00611         ACE_OS::strcpy (name->machine, ACE_LIB_TEXT ("Intel Pentium"));
00612       else
00613         ACE_OS::strcpy (name->machine, unknown);
00614     }
00615   else
00616     {
00617       // We don't know what this is!
00618 
00619       ACE_OS::strcpy (name->release, unknown);
00620       ACE_OS::strcpy (name->version, unknown);
00621       ACE_OS::strcpy (name->machine, unknown);
00622     }
00623 
00624 # if defined (ACE_LACKS_HOSTNAME)
00625   return 0;
00626 # else /* ACE_LACKS_HOSTNAME */
00627   return ACE_OS::hostname (name->nodename, maxnamelen);
00628 # endif /* ACE_LACKS_HOSTNAME */
00629 
00630 # elif defined (VXWORKS)
00631   size_t maxnamelen = sizeof name->nodename;
00632   ACE_OS::strcpy (name->sysname, "VxWorks");
00633   ACE_OS::strcpy (name->release, "???");
00634   ACE_OS::strcpy (name->version, sysBspRev ());
00635   ACE_OS::strcpy (name->machine, sysModel ());
00636 
00637   return ACE_OS::hostname (name->nodename, maxnamelen);
00638 # elif defined (CHORUS)
00639   size_t maxnamelen = sizeof name->nodename;
00640   ACE_OS::strcpy (name->sysname, "CHORUS/ClassiX");
00641   ACE_OS::strcpy (name->release, "???");
00642   ACE_OS::strcpy (name->version, "???");
00643   ACE_OS::strcpy (name->machine, "???");
00644 
00645   return ACE_OS::hostname (name->nodename, maxnamelen);
00646 #elif defined (ACE_PSOS)
00647   const unsigned long buflen(64);
00648   char buf[buflen];
00649   unsigned long len;
00650   sys_info(PSOS_VERSION,(void *)buf,buflen,&len);
00651   ACE_OS::strcpy (name->sysname, "pSOS");
00652   ACE_OS::strcpy (name->release, "???");
00653   ACE_OS::strcpy (name->version, buf);
00654   ACE_OS::strcpy (name->machine, "PPC 405");  // a bit of a hack
00655 
00656 #endif /* ACE_WIN32 */
00657 }
00658 #endif /* ACE_WIN32 || VXWORKS */
00659 
00660 
00661 #if defined (VXWORKS)
00662 struct hostent *
00663 ACE_OS::gethostbyname (const char *name)
00664 {
00665   ACE_OS_TRACE ("ACE_OS::gethostbyname");
00666 
00667   // not thread safe!
00668   static hostent ret;
00669   static int first_addr;
00670   static char *hostaddr[2];
00671   static char *aliases[1];
00672 
00673   ACE_OSCALL (::hostGetByName ((char *) name), int, -1, first_addr);
00674   if (first_addr == -1)
00675     return 0;
00676 
00677   hostaddr[0] = (char *) &first_addr;
00678   hostaddr[1] = 0;
00679   aliases[0] = 0;
00680 
00681   // Might not be official: just echo input arg.
00682   ret.h_name = (char *) name;
00683   ret.h_addrtype = AF_INET;
00684   ret.h_length = 4;  // VxWorks 5.2/3 doesn't define IP_ADDR_LEN;
00685   ret.h_addr_list = hostaddr;
00686   ret.h_aliases = aliases;
00687 
00688   return &ret;
00689 }
00690 
00691 struct hostent *
00692 ACE_OS::gethostbyaddr (const char *addr, int length, int type)
00693 {
00694   ACE_OS_TRACE ("ACE_OS::gethostbyaddr");
00695 
00696   if (length != 4 || type != AF_INET)
00697     {
00698       errno = EINVAL;
00699       return 0;
00700     }
00701 
00702   // not thread safe!
00703   static hostent ret;
00704   static char name [MAXNAMELEN + 1];
00705   static char *hostaddr[2];
00706   static char *aliases[1];
00707 
00708   if (::hostGetByAddr (*(int *) addr, name) != 0)
00709     {
00710       // errno will have been set to S_hostLib_UNKNOWN_HOST.
00711       return 0;
00712     }
00713 
00714   // Might not be official: just echo input arg.
00715   hostaddr[0] = (char *) addr;
00716   hostaddr[1] = 0;
00717   aliases[0] = 0;
00718 
00719   ret.h_name = name;
00720   ret.h_addrtype = AF_INET;
00721   ret.h_length = 4;  // VxWorks 5.2/3 doesn't define IP_ADDR_LEN;
00722   ret.h_addr_list = hostaddr;
00723   ret.h_aliases = aliases;
00724 
00725   return &ret;
00726 }
00727 
00728 struct hostent *
00729 ACE_OS::gethostbyaddr_r (const char *addr, int length, int type,
00730                          hostent *result, ACE_HOSTENT_DATA buffer,
00731                          int *h_errnop)
00732 {
00733   ACE_OS_TRACE ("ACE_OS::gethostbyaddr_r");
00734   if (length != 4 || type != AF_INET)
00735     {
00736       errno = EINVAL;
00737       return 0;
00738     }
00739 
00740   if (ACE_OS::netdb_acquire ())
00741     return 0;
00742   else
00743     {
00744       // buffer layout:
00745       // buffer[0-3]: h_addr_list[0], the first (and only) addr.
00746       // buffer[4-7]: h_addr_list[1], the null terminator for the h_addr_list.
00747       // buffer[8]: the name of the host, null terminated.
00748 
00749       // Call ::hostGetByAddr (), which puts the (one) hostname into
00750       // buffer.
00751       if (::hostGetByAddr (*(int *) addr, &buffer[8]) == 0)
00752         {
00753           // Store the return values in result.
00754           result->h_name = &buffer[8];  // null-terminated host name
00755           result->h_addrtype = AF_INET;
00756           result->h_length = 4;  // VxWorks 5.2/3 doesn't define IP_ADDR_LEN.
00757 
00758           result->h_addr_list = (char **) buffer;
00759           // Might not be official: just echo input arg.
00760           result->h_addr_list[0] = (char *) addr;
00761           // Null-terminate the list of addresses.
00762           result->h_addr_list[1] = 0;
00763           // And no aliases, so null-terminate h_aliases.
00764           result->h_aliases = &result->h_addr_list[1];
00765         }
00766       else
00767         {
00768           // errno will have been set to S_hostLib_UNKNOWN_HOST.
00769           result = 0;
00770         }
00771     }
00772 
00773   ACE_OS::netdb_release ();
00774   *h_errnop = errno;
00775   return result;
00776 }
00777 
00778 struct hostent *
00779 ACE_OS::gethostbyname_r (const char *name, hostent *result,
00780                          ACE_HOSTENT_DATA buffer,
00781                          int *h_errnop)
00782 {
00783   ACE_OS_TRACE ("ACE_OS::gethostbyname_r");
00784 
00785   if (ACE_OS::netdb_acquire ())
00786     return 0;
00787   else
00788     {
00789       int addr;
00790       ACE_OSCALL (::hostGetByName ((char *) name), int, -1, addr);
00791 
00792       if (addr == -1)
00793         {
00794           // errno will have been set to S_hostLib_UNKNOWN_HOST
00795           result = 0;
00796         }
00797       else
00798         {
00799           // Might not be official: just echo input arg.
00800           result->h_name = (char *) name;
00801           result->h_addrtype = AF_INET;
00802           result->h_length = 4;  // VxWorks 5.2/3 doesn't define IP_ADDR_LEN;
00803 
00804           // buffer layout:
00805           // buffer[0-3]: h_addr_list[0], pointer to the addr.
00806           // buffer[4-7]: h_addr_list[1], null terminator for the h_addr_list.
00807           // buffer[8-11]: the first (and only) addr.
00808 
00809           // Store the address list in buffer.
00810           result->h_addr_list = (char **) buffer;
00811           // Store the actual address _after_ the address list.
00812           result->h_addr_list[0] = (char *) &result->h_addr_list[2];
00813           result->h_addr_list[2] = (char *) addr;
00814           // Null-terminate the list of addresses.
00815           result->h_addr_list[1] = 0;
00816           // And no aliases, so null-terminate h_aliases.
00817           result->h_aliases = &result->h_addr_list[1];
00818         }
00819     }
00820 
00821   ACE_OS::netdb_release ();
00822   *h_errnop = errno;
00823   return result;
00824 }
00825 
00826 // Leave this in the global scope to allow
00827 // users to adjust the delay value.
00828 int ACE_THR_JOIN_DELAY = 5;
00829 
00830 int
00831 ACE_OS::thr_join (ACE_hthread_t thr_handle,
00832                   ACE_THR_FUNC_RETURN *status)
00833 {
00834   // We can't get the status of the thread
00835   if (status != 0)
00836     {
00837       *status = 0;
00838     }
00839 
00840   // This method can not support joining all threads
00841   if (ACE_OS::thr_cmp (thr_handle, ACE_OS::NULL_hthread))
00842     {
00843       ACE_NOTSUP_RETURN (-1);
00844     }
00845 
00846   int retval = ESRCH;
00847   ACE_hthread_t current;
00848   ACE_OS::thr_self (current);
00849 
00850   // Make sure we are not joining ourself
00851   if (ACE_OS::thr_cmp (thr_handle, current))
00852     {
00853       retval = EDEADLK;
00854     }
00855   else
00856     {
00857       // Whether the task exists or not
00858       // we will return a successful value
00859       retval = 0;
00860 
00861       // Verify that the task id still exists
00862       while (taskIdVerify (thr_handle) == OK)
00863         {
00864           // Wait a bit to see if the task is still active.
00865           ACE_OS::sleep (ACE_THR_JOIN_DELAY);
00866         }
00867     }
00868 
00869   // Adapt the return value into errno and return value.
00870   // The ACE_ADAPT_RETVAL macro doesn't exactly do what
00871   // we need to do here, so we do it manually.
00872   if (retval != 0)
00873     {
00874       errno = retval;
00875       retval = -1;
00876     }
00877 
00878   return retval;
00879 }
00880 
00881 int
00882 ACE_OS::thr_join (ACE_thread_t waiter_id,
00883                   ACE_thread_t *thr_id,
00884                   ACE_THR_FUNC_RETURN *status)
00885 {
00886   thr_id = 0;
00887   return ACE_OS::thr_join (taskNameToId (waiter_id), status);
00888 }
00889 #endif /* VXWORKS */
00890 
00891 void
00892 ACE_OS::ace_flock_t::dump (void) const
00893 {
00894   ACE_OS_TRACE ("ACE_OS::ace_flock_t::dump");
00895 
00896 #if 0
00897   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
00898   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("handle_ = %u"), this->handle_));
00899 #if defined (ACE_WIN32)
00900   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nInternal = %d"), this->overlapped_.Internal));
00901   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nInternalHigh = %d"), this->overlapped_.InternalHigh));
00902   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nOffsetHigh = %d"), this->overlapped_.OffsetHigh));
00903   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nhEvent = %d"), this->overlapped_.hEvent));
00904 #elif !defined (CHORUS)
00905   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_whence = %d"), this->lock_.l_whence));
00906   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_start = %d"), this->lock_.l_start));
00907   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_len = %d"), this->lock_.l_len));
00908   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("\nl_type = %d"), this->lock_.l_type));
00909 #endif /* ACE_WIN32 */
00910   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
00911 #endif /* 0 */
00912 }
00913 
00914 void
00915 ACE_OS::mutex_lock_cleanup (void *mutex)
00916 {
00917   ACE_OS_TRACE ("ACE_OS::mutex_lock_cleanup");
00918 #if defined (ACE_HAS_THREADS)
00919 #  if defined (ACE_HAS_PTHREADS)
00920   ACE_mutex_t *p_lock = (ACE_mutex_t *) mutex;
00921   ACE_OS::mutex_unlock (p_lock);
00922 #  else
00923   ACE_UNUSED_ARG (mutex);
00924 #  endif /* ACE_HAS_PTHREADS */
00925 # else
00926   ACE_UNUSED_ARG (mutex);
00927 # endif /* ACE_HAS_THREADS */
00928 }
00929 
00930 #if defined (ACE_USES_WCHAR)
00931 void ACE_OS::checkUnicodeFormat (FILE* fp)
00932 {
00933     if (fp != 0)
00934     {
00935         // Due to the ACE_TCHAR definition, all default input files, such as
00936         // svc.conf, have to be in Unicode format (small endian) on WinCE
00937         // because ACE has all 'char' converted into ACE_TCHAR.
00938         // However, for TAO, ASCII files, such as IOR file, can still be read and
00939         // be written without any error since given buffers are all in 'char' type
00940         // instead of ACE_TCHAR.  Therefore, it is user's reponsibility to select
00941         // correct buffer type.
00942 
00943         // At this point, check if the file is Unicode or not.
00944         WORD first_two_bytes;
00945         int numRead = ACE_OS::fread(&first_two_bytes, sizeof(WORD), 1, fp);
00946 
00947         if (numRead == 1)
00948         {
00949             if ((first_two_bytes != 0xFFFE) &&  // not a small endian Unicode file
00950                 (first_two_bytes != 0xFEFF))    // not a big endian Unicode file
00951             {
00952                 ACE_OS::fseek(fp, 0, FILE_BEGIN);  // set file pointer back to the beginning
00953             }
00954         }
00955         // if it is a Unicode file, file pointer will be right next to the first two-bytes
00956     }
00957 }
00958 #endif  // ACE_USES_WCHAR
00959 
00960 #if defined (ACE_WIN32)
00961 FILE *
00962 ACE_OS::fopen (const ACE_TCHAR *filename,
00963                const ACE_TCHAR *mode)
00964 {
00965   ACE_OS_TRACE ("ACE_OS::fopen");
00966   int hmode = _O_TEXT;
00967 
00968   for (const ACE_TCHAR *mode_ptr = mode; *mode_ptr != 0; mode_ptr++)
00969     ACE_OS::fopen_mode_to_open_mode_converter (*mode_ptr, hmode);
00970 
00971   ACE_HANDLE handle = ACE_OS::open (filename, hmode);
00972   if (handle != ACE_INVALID_HANDLE)
00973     {
00974 # if defined (ACE_HAS_WINCE)
00975       FILE *fp = ::_wfdopen (handle, mode);
00976       if (fp != 0)
00977       {
00978         checkUnicodeFormat(fp);
00979         return fp;
00980       }
00981 # else
00982       hmode &= _O_TEXT | _O_RDONLY | _O_APPEND;
00983 #   if defined (ACE_WIN64)
00984       int fd = _open_osfhandle (intptr_t (handle), hmode);
00985 #   else
00986       int fd = _open_osfhandle (long (handle), hmode);
00987 #   endif /* ACE_WIN64 */
00988       if (fd != -1)
00989         {
00990 #   if defined (__BORLANDC__) && !defined (ACE_USES_WCHAR)
00991           FILE *fp = ::_fdopen (fd, ACE_const_cast (char *, mode));
00992 #   elif defined (__BORLANDC__) && defined (ACE_USES_WCHAR)
00993           FILE *fp = ::_wfdopen (fd, ACE_const_cast (wchar_t *, mode));
00994 #   elif defined (ACE_USES_WCHAR)
00995           FILE *fp = ::_wfdopen (fd, mode);
00996 #   else
00997           FILE *fp = ::fdopen (fd, mode);
00998 #   endif /* defined(__BORLANDC__) && !defined (ACE_USES_WCHAR)) */
00999           if (fp != 0)
01000           {
01001 #   if defined (ACE_USES_WCHAR)
01002             checkUnicodeFormat(fp);
01003 #   endif  // ACE_USES_WCHAR
01004             return fp;
01005           }
01006           _close (fd);
01007         }
01008 # endif  // ACE_HAS_WINCE
01009 
01010       ACE_OS::close (handle);
01011     }
01012   return 0;
01013 }
01014 #endif /* ACE_WIN32 */
01015 
01016 // The following *printf functions aren't inline because
01017 // they use varargs.
01018 
01019 int
01020 ACE_OS::fprintf (FILE *fp, const char *format, ...)
01021 {
01022   ACE_OS_TRACE ("ACE_OS::fprintf");
01023   int result = 0;
01024   va_list ap;
01025   va_start (ap, format);
01026   ACE_OSCALL (::vfprintf (fp, format, ap), int, -1, result);
01027   va_end (ap);
01028   return result;
01029 }
01030 
01031 #if defined (ACE_HAS_WCHAR)
01032 int
01033 ACE_OS::fprintf (FILE *fp, const wchar_t *format, ...)
01034 {
01035   ACE_OS_TRACE ("ACE_OS::fprintf");
01036 
01037 # if !defined (ACE_HAS_VFWPRINTF)
01038   ACE_UNUSED_ARG (fp);
01039   ACE_UNUSED_ARG (format);
01040   ACE_NOTSUP_RETURN (-1);
01041 
01042 # else
01043   int result = 0;
01044   va_list ap;
01045   va_start (ap, format);
01046   ACE_OSCALL (::vfwprintf (fp, format, ap), int, -1, result);
01047   va_end (ap);
01048   return result;
01049 
01050 # endif /* ACE_HAS_VFWPRINTF */
01051 }
01052 #endif /* ACE_HAS_WCHAR */
01053 
01054 int
01055 ACE_OS::printf (const char *format, ...)
01056 {
01057   ACE_OS_TRACE ("ACE_OS::printf");
01058   int result;
01059   va_list ap;
01060   va_start (ap, format);
01061   ACE_OSCALL (::vprintf (format, ap), int, -1, result);
01062   va_end (ap);
01063   return result;
01064 }
01065 
01066 int
01067 ACE_OS::sprintf (char *buf, const char *format, ...)
01068 {
01069   // ACE_OS_TRACE ("ACE_OS::sprintf");
01070 
01071   int result;
01072   va_list ap;
01073   va_start (ap, format);
01074   ACE_OSCALL (ACE_SPRINTF_ADAPTER (::vsprintf (buf, format, ap)), int, -1, result);
01075   va_end (ap);
01076   return result;
01077 }
01078 
01079 #if defined (ACE_HAS_WCHAR)
01080 int
01081 ACE_OS::sprintf (wchar_t *buf, const wchar_t *format, ...)
01082 {
01083   ACE_OS_TRACE ("ACE_OS::sprintf");
01084 
01085 # if defined (_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
01086 
01087   // The XPG4/UNIX98/C99 signature of the wide-char sprintf has a
01088   // maxlen argument. Since this method doesn't supply one, pass in
01089   // the max possible length. If this isn't ok, use ACE_OS::snprintf().
01090   int result;
01091   va_list ap;
01092   va_start (ap, format);
01093   ACE_OSCALL (::vswprintf (buf, ULONG_MAX, format, ap), int, -1, result);
01094   va_end (ap);
01095   return result;
01096 
01097 # elif defined (ACE_WIN32)
01098   // Windows has vswprintf, but the signature is from the older ISO C
01099   // standard. Also see ACE_OS::snprintf() for more info on this.
01100 
01101   int result;
01102   va_list ap;
01103   va_start (ap, format);
01104   ACE_OSCALL (::vswprintf (buf, format, ap), int, -1, result);
01105   va_end (ap);
01106   return result;
01107 
01108 # else
01109 
01110   ACE_UNUSED_ARG (buf);
01111   ACE_UNUSED_ARG (format);
01112   ACE_NOTSUP_RETURN (-1);
01113 
01114 # endif /* ACE_HAS_VSWPRINTF */
01115 }
01116 #endif /* ACE_HAS_WCHAR */
01117 
01118 int
01119 ACE_OS::snprintf (char *buf, size_t maxlen, const char *format, ...)
01120 {
01121   // ACE_OS_TRACE ("ACE_OS::snprintf");
01122 #if defined (ACE_HAS_SNPRINTF)
01123   int result;
01124   va_list ap;
01125   va_start (ap, format);
01126 #  if defined (ACE_WIN32)
01127   ACE_OSCALL (ACE_SPRINTF_ADAPTER (::_vsnprintf (buf, maxlen, format, ap)),
01128               int, -1, result);
01129   // Win32 doesn't 0-terminate the string if it overruns maxlen.
01130   if (result == -1)
01131     buf[maxlen-1] = '\0';
01132 #  else
01133   ACE_OSCALL (ACE_SPRINTF_ADAPTER (::vsnprintf (buf, maxlen, format, ap)),
01134               int, -1, result);
01135 #  endif /* ACE_WIN32 */
01136   va_end (ap);
01137   // In out-of-range conditions, C99 defines vsnprintf to return the number
01138   // of characters that would have been written if enough space was available.
01139   // Earlier variants of the vsnprintf() (e.g. UNIX98) defined it to return
01140   // -1. This method follows the C99 standard, but needs to guess at the
01141   // value; uses maxlen + 1.
01142   if (result == -1)
01143     result = ACE_static_cast (int, (maxlen + 1));
01144   return result;
01145 
01146 #else
01147   ACE_UNUSED_ARG (buf);
01148   ACE_UNUSED_ARG (maxlen);
01149   ACE_UNUSED_ARG (format);
01150   ACE_NOTSUP_RETURN (-1);
01151 #endif /* ACE_HAS_SNPRINTF */
01152 }
01153 
01154 #if defined (ACE_HAS_WCHAR)
01155 int
01156 ACE_OS::snprintf (wchar_t *buf, size_t maxlen, const wchar_t *format, ...)
01157 {
01158   // ACE_OS_TRACE ("ACE_OS::snprintf");
01159 #if (defined (_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)) || defined (ACE_WIN32)
01160   int result;
01161   va_list ap;
01162   va_start (ap, format);
01163 #  if defined (ACE_WIN32)
01164   // Microsoft's vswprintf() doesn't have the maxlen argument that
01165   // XPG4/UNIX98 define. They do, however, recommend use of _vsnwprintf()
01166   // as a substitute, which does have the same signature as the UNIX98 one.
01167   ACE_OSCALL (ACE_SPRINTF_ADAPTER (::_vsnwprintf (buf, maxlen, format, ap)),
01168               int, -1, result);
01169   // Win32 doesn't 0-terminate the string if it overruns maxlen.
01170   if (result == -1)
01171     buf[maxlen-1] = '\0';
01172 #  else
01173   ACE_OSCALL (ACE_SPRINTF_ADAPTER (::vswprintf (buf, maxlen, format, ap)),
01174               int, -1, result);
01175 #  endif /* ACE_WIN32 */
01176   va_end (ap);
01177   // In out-of-range conditions, C99 defines vsnprintf to return the number
01178   // of characters that would have been written if enough space was available.
01179   // Earlier variants of the vsnprintf() (e.g. UNIX98) defined it to return
01180   // -1. This method follows the C99 standard, but needs to guess at the
01181   // value; uses maxlen + 1.
01182   if (result == -1)
01183     result = ACE_static_cast (int, (maxlen + 1));
01184   return result;
01185 
01186 #else
01187   ACE_UNUSED_ARG (buf);
01188   ACE_UNUSED_ARG (maxlen);
01189   ACE_UNUSED_ARG (format);
01190   ACE_NOTSUP_RETURN (-1);
01191 #endif /* ACE_HAS_SNPRINTF */
01192 }
01193 #endif /* ACE_HAS_WCHAR */
01194 
01195 char *
01196 ACE_OS::gets (char *str, int n)
01197 {
01198   ACE_OS_TRACE ("ACE_OS::gets");
01199   int c;
01200   char *s = str;
01201 
01202   if (str == 0 || n < 0) n = 0;
01203   if (n == 0) str = 0;
01204   else n--;
01205 
01206   while ((c = getchar ()) != '\n')
01207     {
01208 
01209       if (c == EOF && errno == EINTR)
01210         {
01211 #   if defined (ACE_HAS_SIGNAL_SAFE_OS_CALLS)
01212           continue;
01213 #   else
01214           break;
01215 #   endif /* ACE_HAS_SIGNAL_SAFE_OS_CALLS */
01216         }
01217 
01218       if (c == EOF)
01219         break;
01220 
01221       if (n > 0)
01222         n--, *s++ = c;
01223     }
01224   if (s) *s = '\0';
01225 
01226   return (c == EOF) ? 0 : str;
01227 }
01228 
01229 int
01230 ACE_OS::execl (const char * /* path */, const char * /* arg0 */, ...)
01231 {
01232   ACE_OS_TRACE ("ACE_OS::execl");
01233 #if defined (ACE_WIN32) || defined (VXWORKS)
01234   ACE_NOTSUP_RETURN (-1);
01235 #else
01236   ACE_NOTSUP_RETURN (-1);
01237   // Need to write this code.
01238   // ACE_OSCALL_RETURN (::execv (path, argv), int, -1);
01239 #endif /* ACE_WIN32 */
01240 }
01241 
01242 int
01243 ACE_OS::execle (const char * /* path */, const char * /* arg0 */, ...)
01244 {
01245   ACE_OS_TRACE ("ACE_OS::execle");
01246 #if defined (ACE_WIN32) || defined (VXWORKS)
01247   ACE_NOTSUP_RETURN (-1);
01248 #else
01249   ACE_NOTSUP_RETURN (-1);
01250   // Need to write this code.
01251   //  ACE_OSCALL_RETURN (::execve (path, argv, envp), int, -1);
01252 #endif /* ACE_WIN32 */
01253 }
01254 
01255 int
01256 ACE_OS::execlp (const char * /* file */, const char * /* arg0 */, ...)
01257 {
01258   ACE_OS_TRACE ("ACE_OS::execlp");
01259 #if defined (ACE_WIN32) || defined (VXWORKS)
01260   ACE_NOTSUP_RETURN (-1);
01261 #else
01262   ACE_NOTSUP_RETURN (-1);
01263   // Need to write this code.
01264   //  ACE_OSCALL_RETURN (::execvp (file, argv), int, -1);
01265 #endif /* ACE_WIN32 */
01266 }
01267 
01268 int
01269 ACE_OS::scheduling_class (const char *class_name, ACE_id_t &id)
01270 {
01271 #if defined (ACE_HAS_PRIOCNTL)
01272   // Get the priority class ID.
01273   pcinfo_t pcinfo;
01274   // The following is just to avoid Purify warnings about unitialized
01275   // memory reads.
01276   ACE_OS::memset (&pcinfo, 0, sizeof pcinfo);
01277 
01278   ACE_OS::strcpy (pcinfo.pc_clname, class_name);
01279   if (ACE_OS::priority_control (P_ALL /* ignored */,
01280                                 P_MYID /* ignored */,
01281                                 PC_GETCID,
01282                                 (char *) &pcinfo) == -1)
01283     {
01284       return -1;
01285     }
01286   else
01287     {
01288       id = pcinfo.pc_cid;
01289       return 0;
01290     }
01291 #else  /* ! ACE_HAS_PRIOCNTL */
01292   ACE_UNUSED_ARG (class_name);
01293   ACE_UNUSED_ARG (id);
01294   ACE_NOTSUP_RETURN (-1);
01295 #endif /* ! ACE_HAS_PRIOCNTL */
01296 }
01297 
01298 int
01299 ACE_OS::set_scheduling_params (const ACE_Sched_Params &sched_params,
01300                                ACE_id_t id)
01301 {
01302 #if defined (ACE_HAS_PRIOCNTL)
01303   // Set priority class, priority, and quantum of this LWP or process as
01304   // specified in sched_params.
01305 
01306   // Get the priority class ID.
01307   ACE_id_t class_id;
01308   if (ACE_OS::scheduling_class (sched_params.policy() == ACE_SCHED_OTHER  ?
01309                                   "TS"  :
01310                                   "RT", class_id) == -1)
01311     {
01312       return -1;
01313     }
01314 
01315   pcparms_t pcparms;
01316   // The following is just to avoid Purify warnings about unitialized
01317   // memory reads.
01318   ACE_OS::memset (&pcparms, 0, sizeof pcparms);
01319 
01320   pcparms.pc_cid = class_id;
01321 
01322   if (sched_params.policy () == ACE_SCHED_OTHER  &&
01323       sched_params.quantum () == ACE_Time_Value::zero)
01324       // SunOS doesn't support non-zero quantums in time-sharing class:  use
01325       // real-time class instead.
01326     {
01327       tsparms_t tsparms;
01328       // The following is just to avoid Purify warnings about unitialized
01329       // memory reads.
01330       ACE_OS::memset (&tsparms, 0, sizeof tsparms);
01331 
01332       // Don't change ts_uprilim (user priority limit)
01333       tsparms.ts_uprilim = TS_NOCHANGE;
01334       tsparms.ts_upri = sched_params.priority ();
01335 
01336       // Package up the TS class ID and parameters for the
01337       // priority_control () call.
01338       ACE_OS::memcpy (pcparms.pc_clparms, &tsparms, sizeof tsparms);
01339     }
01340   else if (sched_params.policy () == ACE_SCHED_FIFO  ||
01341            (sched_params.policy () == ACE_SCHED_RR &&
01342             sched_params.quantum () != ACE_Time_Value::zero))
01343            // must have non-zero quantum for RR, to make it meaningful
01344            // A zero quantum with FIFO has special significance:  it actually
01345            // means infinite time quantum, i.e., run-to-completion.
01346     {
01347       rtparms_t rtparms;
01348       // The following is just to avoid Purify warnings about unitialized
01349       // memory reads.
01350       ACE_OS::memset (&rtparms, 0, sizeof rtparms);
01351 
01352       rtparms.rt_pri = sched_params.priority ();
01353 
01354       if (sched_params.quantum () == ACE_Time_Value::zero)
01355         {
01356           // rtparms.rt_tqsecs is ignored with RT_TQINF
01357           rtparms.rt_tqnsecs = RT_TQINF;
01358         }
01359       else
01360         {
01361           rtparms.rt_tqsecs = (ulong) sched_params.quantum ().sec ();
01362           rtparms.rt_tqnsecs = sched_params.quantum ().usec () * 1000;
01363         }
01364 
01365       // Package up the RT class ID and parameters for the
01366       // priority_control () call.
01367       ACE_OS::memcpy (pcparms.pc_clparms, &rtparms, sizeof rtparms);
01368     }
01369   else
01370     {
01371       errno = EINVAL;
01372       return -1;
01373     }
01374 
01375   if (ACE_OS::priority_control ((idtype_t) (sched_params.scope () == ACE_SCOPE_THREAD
01376                                             ? ACE_SCOPE_PROCESS
01377                                             : sched_params.scope ()),
01378                                 id,
01379                                 PC_SETPARMS,
01380                                 (char *) &pcparms) < 0)
01381     {
01382       return ACE_OS::last_error ();
01383     }
01384 
01385   return 0;
01386 #else  /* ! ACE_HAS_PRIOCNTL */
01387   ACE_UNUSED_ARG (sched_params);
01388   ACE_UNUSED_ARG (id);
01389   ACE_NOTSUP_RETURN (-1);
01390 #endif /* ! ACE_HAS_PRIOCNTL */
01391 }
01392 
01393 int
01394 ACE_OS::thr_setprio (const ACE_Sched_Priority prio)
01395 {
01396   // Set the thread priority on the current thread.
01397   ACE_hthread_t my_thread_id;
01398   ACE_OS::thr_self (my_thread_id);
01399 
01400   int status = ACE_OS::thr_setprio (my_thread_id, prio);
01401 
01402 # if defined (ACE_NEEDS_LWP_PRIO_SET)
01403   // If the thread is in the RT class, then set the priority on its
01404   // LWP.  (Instead of doing this if the thread is in the RT class, it
01405   // should be done for all bound threads.  But, there doesn't appear
01406   // to be an easy way to determine if the thread is bound.)
01407 
01408   if (status == 0)
01409     {
01410       // Find what scheduling class the thread's LWP is in.
01411       ACE_Sched_Params sched_params (ACE_SCHED_OTHER, 0);
01412       if (ACE_OS::lwp_getparams (sched_params) == -1)
01413         {
01414           return -1;
01415         }
01416       else if (sched_params.policy () == ACE_SCHED_FIFO  ||
01417                sched_params.policy () == ACE_SCHED_RR)
01418         {
01419           // This thread's LWP is in the RT class, so we need to set
01420           // its priority.
01421           sched_params.priority (prio);
01422           return ACE_OS::lwp_setparams (sched_params);
01423         }
01424       // else this is not an RT thread.  Nothing more needs to be
01425       // done.
01426     }
01427 # endif /* ACE_NEEDS_LWP_PRIO_SET */
01428 
01429   return status;
01430 }
01431 
01432 int
01433 ACE_OS::sched_params (const ACE_Sched_Params &sched_params,
01434                       ACE_id_t id)
01435 {
01436   ACE_OS_TRACE ("ACE_OS::sched_params");
01437 # if defined (CHORUS)
01438   ACE_UNUSED_ARG (id);
01439   int result;
01440   struct sched_param param;
01441   ACE_thread_t thr_id = ACE_OS::thr_self ();
01442 
01443   param.sched_priority = sched_params.priority ();
01444 
01445   ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
01446                                                                 sched_params.policy (),
01447                                                                 &param),
01448                                        result),
01449                      int, -1);
01450 # elif defined (ACE_HAS_STHREADS)
01451   return ACE_OS::set_scheduling_params (sched_params, id);
01452 # elif defined (ACE_HAS_PTHREADS) && !defined (ACE_LACKS_SETSCHED)
01453   ACE_UNUSED_ARG (id);
01454   if (sched_params.quantum () != ACE_Time_Value::zero)
01455     {
01456       // quantums not supported
01457       errno = EINVAL;
01458       return -1;
01459     }
01460 
01461   // Thanks to Thilo Kielmann <kielmann@informatik.uni-siegen.de> for
01462   // providing this code for 1003.1c PThreads.  Please note that this
01463   // has only been tested for POSIX 1003.1c threads, and may cause
01464   // problems with other PThreads flavors!
01465 
01466   struct sched_param param;
01467   param.sched_priority = sched_params.priority ();
01468 
01469   if (sched_params.scope () == ACE_SCOPE_PROCESS)
01470     {
01471       int result = ::sched_setscheduler (0, // this process
01472                                          sched_params.policy (),
01473                                          &param) == -1 ? -1 : 0;
01474 #   if defined (DIGITAL_UNIX)
01475       return result == 0
01476         ? // Use priocntl (2) to set the process in the RT class,
01477         // if using an RT policy.
01478         ACE_OS::set_scheduling_params (sched_params)
01479         : result;
01480 #   else  /* ! DIGITAL_UNIX */
01481       return result;
01482 #   endif /* ! DIGITAL_UNIX */
01483     }
01484   else if (sched_params.scope () == ACE_SCOPE_THREAD)
01485     {
01486       ACE_thread_t thr_id = ACE_OS::thr_self ();
01487 
01488 #   if defined (ACE_HAS_PTHREADS_DRAFT4)
01489       return (::pthread_setscheduler (thr_id,
01490                                       sched_params.policy (),
01491                                       sched_params.priority()) == -1 ? -1 : 0);
01492 #   else
01493       int result;
01494       ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (thr_id,
01495                                                                     sched_params.policy (),
01496                                                                     &param),
01497                                            result),
01498                          int, -1);
01499 #   endif  /* ACE_HAS_PTHREADS_DRAFT4 */
01500     }
01501 #   if defined (sun)
01502   // We need to be able to set LWP priorities on Suns, even without
01503   // ACE_HAS_STHREADS, to obtain preemption.
01504   else if (sched_params.scope () == ACE_SCOPE_LWP)
01505     return ACE_OS::set_scheduling_params (sched_params, id);
01506 #   endif /* sun */
01507   else // sched_params.scope () == ACE_SCOPE_LWP, which isn't POSIX
01508     {
01509       errno = EINVAL;
01510       return -1;
01511     }
01512 
01513 # elif defined (ACE_WIN32) && !defined (ACE_HAS_WINCE)
01514 
01515   // PharLap ETS can act on the current thread - it can set the
01516   // quantum also, unlike Win32. All this only works on the RT
01517   // version.
01518 #   if defined (ACE_HAS_PHARLAP_RT)
01519   if (id != ACE_SELF)
01520     ACE_NOTSUP_RETURN (-1);
01521 
01522   if (sched_params.quantum() != ACE_Time_Value::zero)
01523     EtsSetTimeSlice (sched_params.quantum().msec());
01524 
01525 #   else
01526   ACE_UNUSED_ARG (id);
01527 
01528   if (sched_params.scope () != ACE_SCOPE_PROCESS
01529       || sched_params.quantum () != ACE_Time_Value::zero)
01530     {
01531       // Win32 only allows setting priority class (therefore, policy)
01532       // at the process level.  I don't know of a way to set the
01533       // quantum.
01534       errno = EINVAL;
01535       return -1;
01536     }
01537 #ifndef ACE_DISABLE_WIN32_INCREASE_PRIORITY
01538   // Set the priority class of this process to the REALTIME process class
01539   // _if_ the policy is ACE_SCHED_FIFO.  Otherwise, set to NORMAL.
01540   if (!::SetPriorityClass (::GetCurrentProcess (),
01541                            sched_params.policy () == ACE_SCHED_FIFO
01542                            ? REALTIME_PRIORITY_CLASS
01543                            : NORMAL_PRIORITY_CLASS))
01544     {
01545       ACE_OS::set_errno_to_last_error ();
01546       return -1;
01547     }
01548 #endif
01549 #   endif /* ACE_HAS_PHARLAP_RT */
01550 
01551   // Set the thread priority on the current thread.
01552   return ACE_OS::thr_setprio (sched_params.priority ());
01553 
01554 # elif defined (VXWORKS) || defined (ACE_PSOS)
01555   ACE_UNUSED_ARG (id);
01556 
01557   // There is only one class of priorities on VxWorks, and no time
01558   // quanta.  So, just set the current thread's priority.
01559 
01560   if (sched_params.policy () != ACE_SCHED_FIFO
01561       || sched_params.scope () != ACE_SCOPE_PROCESS
01562       || sched_params.quantum () != ACE_Time_Value::zero)
01563     {
01564       errno = EINVAL;
01565       return -1;
01566     }
01567 
01568   // Set the thread priority on the current thread.
01569   return ACE_OS::thr_setprio (sched_params.priority ());
01570 # else
01571   ACE_UNUSED_ARG (sched_params);
01572   ACE_UNUSED_ARG (id);
01573   ACE_NOTSUP_RETURN (-1);
01574 # endif /* CHORUS */
01575 }
01576 
01577 // = Static initialization.
01578 
01579 // This is necessary to deal with POSIX pthreads insanity.  This
01580 // guarantees that we've got a "zero'd" thread id even when
01581 // ACE_thread_t, ACE_hthread_t, and ACE_thread_key_t are implemented
01582 // as structures...  Under no circumstances should these be given
01583 // initial values.
01584 // Note: these three objects require static construction.
01585 ACE_thread_t ACE_OS::NULL_thread;
01586 ACE_hthread_t ACE_OS::NULL_hthread;
01587 #if defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
01588   ACE_thread_key_t ACE_OS::NULL_key = ACE_static_cast (ACE_thread_key_t, -1);
01589 #else  /* ! ACE_HAS_TSS_EMULATION */
01590   ACE_thread_key_t ACE_OS::NULL_key;
01591 #endif /* ! ACE_HAS_TSS_EMULATION */
01592 
01593 #if defined (CHORUS)
01594 KnCap ACE_OS::actorcaps_[ACE_CHORUS_MAX_ACTORS];
01595 // This is used to map an actor's id into a KnCap for killing and
01596 // waiting actors.
01597 #endif /* CHORUS */
01598 
01599 #if defined (ACE_WIN32)
01600 
01601 // = Static initialization.
01602 
01603 // Keeps track of whether we've initialized the WinSock DLL.
01604 int ACE_OS::socket_initialized_;
01605 
01606 #endif /* WIN32 */
01607 
01608 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
01609 
01610 // Moved class ACE_TSS_Ref declaration to OS.h so it can be visible to
01611 // the single file of template instantiations.
01612 
01613 ACE_TSS_Ref::ACE_TSS_Ref (ACE_thread_t id)
01614   : tid_(id)
01615 {
01616   ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
01617 }
01618 
01619 ACE_TSS_Ref::ACE_TSS_Ref (void)
01620 {
01621   ACE_OS_TRACE ("ACE_TSS_Ref::ACE_TSS_Ref");
01622 }
01623 
01624 // Check for equality.
01625 int
01626 ACE_TSS_Ref::operator== (const ACE_TSS_Ref &info) const
01627 {
01628   ACE_OS_TRACE ("ACE_TSS_Ref::operator==");
01629 
01630   return this->tid_ == info.tid_;
01631 }
01632 
01633 // Check for inequality.
01634 ACE_SPECIAL_INLINE
01635 int
01636 ACE_TSS_Ref::operator != (const ACE_TSS_Ref &tss_ref) const
01637 {
01638   ACE_OS_TRACE ("ACE_TSS_Ref::operator !=");
01639 
01640   return !(*this == tss_ref);
01641 }
01642 
01643 // moved class ACE_TSS_Info declaration
01644 // to OS.h so it can be visible to the
01645 // single file of template instantiations
01646 
01647 ACE_TSS_Info::ACE_TSS_Info (ACE_thread_key_t key,
01648                             void (*dest)(void *),
01649                             void *tss_inst)
01650   : key_ (key),
01651     destructor_ (dest),
01652     tss_obj_ (tss_inst),
01653     thread_count_ (-1)
01654 {
01655   ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
01656 }
01657 
01658 ACE_TSS_Info::ACE_TSS_Info (void)
01659   : key_ (ACE_OS::NULL_key),
01660     destructor_ (0),
01661     tss_obj_ (0),
01662     thread_count_ (-1)
01663 {
01664   ACE_OS_TRACE ("ACE_TSS_Info::ACE_TSS_Info");
01665 }
01666 
01667 # if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
01668 static inline int operator== (const ACE_thread_key_t &lhs,
01669                               const ACE_thread_key_t &rhs)
01670 {
01671   return ! ACE_OS::memcmp (&lhs, &rhs, sizeof (ACE_thread_key_t));
01672 }
01673 
01674 static inline int operator!= (const ACE_thread_key_t &lhs,
01675                               const ACE_thread_key_t &rhs)
01676 {
01677   return ! (lhs == rhs);
01678 }
01679 # endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
01680 
01681 // Check for equality.
01682 int
01683 ACE_TSS_Info::operator== (const ACE_TSS_Info &info) const
01684 {
01685   ACE_OS_TRACE ("ACE_TSS_Info::operator==");
01686 
01687   return this->key_ == info.key_;
01688 }
01689 
01690 // Check for inequality.
01691 int
01692 ACE_TSS_Info::operator != (const ACE_TSS_Info &info) const
01693 {
01694   ACE_OS_TRACE ("ACE_TSS_Info::operator !=");
01695 
01696   return !(*this == info);
01697 }
01698 
01699 void
01700 ACE_TSS_Info::dump (void)
01701 {
01702   //  ACE_OS_TRACE ("ACE_TSS_Info::dump");
01703 
01704 #if 0
01705   ACE_DEBUG ((LM_DEBUG, ACE_BEGIN_DUMP, this));
01706   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("key_ = %u\n"), this->key_));
01707   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("destructor_ = %u\n"), this->destructor_));
01708   ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("tss_obj_ = %u\n"), this->tss_obj_));
01709   ACE_DEBUG ((LM_DEBUG, ACE_END_DUMP));
01710 #endif /* 0 */
01711 }
01712 
01713 // Moved class ACE_TSS_Keys declaration to OS.h so it can be visible
01714 // to the single file of template instantiations.
01715 
01716 ACE_TSS_Keys::ACE_TSS_Keys (void)
01717 {
01718   for (u_int i = 0; i < ACE_WORDS; ++i)
01719     {
01720       key_bit_words_[i] = 0;
01721     }
01722 }
01723 
01724 ACE_SPECIAL_INLINE
01725 void
01726 ACE_TSS_Keys::find (const u_int key, u_int &word, u_int &bit)
01727 {
01728   word = key / ACE_BITS_PER_WORD;
01729   bit = key % ACE_BITS_PER_WORD;
01730 }
01731 
01732 int
01733 ACE_TSS_Keys::test_and_set (const ACE_thread_key_t key)
01734 {
01735   ACE_KEY_INDEX (key_index, key);
01736   u_int word, bit;
01737   find (key_index, word, bit);
01738 
01739   if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
01740     {
01741       return 1;
01742     }
01743   else
01744     {
01745       ACE_SET_BITS (key_bit_words_[word], 1 << bit);
01746       return 0;
01747     }
01748 }
01749 
01750 int
01751 ACE_TSS_Keys::test_and_clear (const ACE_thread_key_t key)
01752 {
01753   ACE_KEY_INDEX (key_index, key);
01754   u_int word, bit;
01755   find (key_index, word, bit);
01756 
01757   if (ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit))
01758     {
01759       ACE_CLR_BITS (key_bit_words_[word], 1 << bit);
01760       return 0;
01761     }
01762   else
01763     {
01764       return 1;
01765     }
01766 }
01767 
01768 int
01769 ACE_TSS_Keys::is_set (const ACE_thread_key_t key) const
01770 {
01771   ACE_KEY_INDEX (key_index, key);
01772   u_int word, bit;
01773   find (key_index, word, bit);
01774 
01775   return ACE_BIT_ENABLED (key_bit_words_[word], 1 << bit);
01776 }
01777 
01778 
01779 /**
01780  * @class ACE_TSS_Cleanup
01781  *
01782  * @brief Singleton that knows how to clean up all the thread-specific
01783  * resources for Win32.
01784  *
01785  * All this nonsense is required since Win32 doesn't
01786  * automatically cleanup thread-specific storage on thread exit,
01787  * unlike real operating systems... ;-)
01788  */
01789 class ACE_TSS_Cleanup
01790 {
01791 public:
01792   static ACE_TSS_Cleanup *instance (void);
01793 
01794   ~ACE_TSS_Cleanup (void);
01795 
01796   /// Cleanup the thread-specific objects.  Does _NOT_ exit the thread.
01797   void exit (void *status);
01798 
01799   /// Insert a <key, destructor> tuple into the table.
01800   int insert (ACE_thread_key_t key, void (*destructor)(void *), void *inst);
01801 
01802   /// Remove a <key, destructor> tuple from the table.
01803   int remove (ACE_thread_key_t key);
01804 
01805   /// Detaches a tss_instance from its key.
01806   int detach (void *inst);
01807 
01808   /// Mark a key as being used by this thread.
01809   void key_used (ACE_thread_key_t key);
01810 
01811   /// Free all keys left in the table before destruction.
01812   int free_all_keys_left (void);
01813 
01814   /// Indication of whether the ACE_TSS_CLEANUP_LOCK is usable, and
01815   /// therefore whether we are in static constructor/destructor phase
01816   /// or not.
01817   static int lockable () { return instance_ != 0; }
01818 
01819 protected:
01820   void dump (void);
01821 
01822   /// Ensure singleton.
01823   ACE_TSS_Cleanup (void);
01824 
01825 private:
01826   // Array of <ACE_TSS_Info> objects.
01827   typedef ACE_TSS_Info ACE_TSS_TABLE[ACE_DEFAULT_THREAD_KEYS];
01828   typedef ACE_TSS_Info *ACE_TSS_TABLE_ITERATOR;
01829 
01830   /// Table of <ACE_TSS_Info>'s.
01831   ACE_TSS_TABLE table_;
01832 
01833   /// Key for the thread-specific array of whether each TSS key is in use.
01834   ACE_thread_key_t in_use_;
01835 
01836   /// Accessor for this threads ACE_TSS_Keys instance.
01837   ACE_TSS_Keys *tss_keys ();
01838 
01839 #if defined (ACE_HAS_TSS_EMULATION)
01840   /// Key that is used by in_use_.  We save this key so that we know
01841   /// not to call its destructor in free_all_keys_left ().
01842   ACE_thread_key_t in_use_key_;
01843 #endif /* ACE_HAS_TSS_EMULATION */
01844 
01845   // = Static data.
01846   /// Pointer to the singleton instance.
01847   static ACE_TSS_Cleanup *instance_;
01848 };
01849 
01850 // = Static object initialization.
01851 
01852 // Pointer to the singleton instance.
01853 ACE_TSS_Cleanup *ACE_TSS_Cleanup::instance_ = 0;
01854 
01855 ACE_TSS_Cleanup::~ACE_TSS_Cleanup (void)
01856 {
01857   // Zero out the instance pointer to support lockable () accessor.
01858   ACE_TSS_Cleanup::instance_ = 0;
01859 }
01860 
01861 void
01862 ACE_TSS_Cleanup::exit (void * /* status */)
01863 {
01864   ACE_OS_TRACE ("ACE_TSS_Cleanup::exit");
01865 
01866   ACE_TSS_TABLE_ITERATOR key_info = table_;
01867   ACE_TSS_Info info_arr[ACE_DEFAULT_THREAD_KEYS];
01868   int info_ix = 0;
01869 
01870   // While holding the lock, we only collect the ACE_TSS_Info objects
01871   // in an array without invoking the according destructors.
01872   {
01873     ACE_TSS_CLEANUP_GUARD
01874 
01875     // Iterate through all the thread-specific items and free them all
01876     // up.
01877 
01878     for (unsigned int i = 0;
01879          i < ACE_DEFAULT_THREAD_KEYS;
01880          ++key_info, ++i)
01881       {
01882         if (key_info->key_ == ACE_OS::NULL_key  ||
01883             ! key_info->key_in_use ()) continue;
01884 
01885         // If the key's ACE_TSS_Info in-use bit for this thread was set,
01886         // unset it and decrement the key's thread_count_.
01887         if (! tss_keys ()->test_and_clear (key_info->key_))
01888           {
01889             --key_info->thread_count_;
01890           }
01891 
01892         void *tss_info = 0;
01893 
01894         if (key_info->destructor_
01895             && ACE_OS::thr_getspecific (key_info->key_, &tss_info) == 0
01896             && tss_info)
01897           {
01898             info_arr[info_ix].key_ = key_info->key_;
01899             info_arr[info_ix].destructor_ = key_info->destructor_;
01900             info_arr[info_ix++].tss_obj_ = key_info->tss_obj_;
01901           }
01902       }
01903   }
01904 
01905   // Now we have given up the ACE_TSS_Cleanup::lock_ and we start
01906   // invoking destructors, in the reverse order of creation.
01907   for (int i = info_ix - 1; i >= 0; --i)
01908     {
01909       void *tss_info = 0;
01910 
01911       ACE_OS::thr_getspecific (info_arr[i].key_, &tss_info);
01912 
01913       if (tss_info != 0)
01914         {
01915           // Only call the destructor if the value is non-zero for this
01916           // thread.
01917           (*info_arr[i].destructor_)(tss_info);
01918         }
01919     }
01920 
01921   // Acquire the ACE_TSS_CLEANUP_LOCK, then free TLS keys and remove
01922   // entries from ACE_TSS_Info table.
01923   {
01924     ACE_TSS_CLEANUP_GUARD
01925 
01926 # if 0
01927     // We shouldn't free the key and remove it from the table here
01928     // because if we do and some thread ends before other threads
01929     // even get started (or their TSS object haven't been created yet,)
01930     // it's entry will be removed from the table and we are in big chaos.
01931     // For TSS object, these have been done in ACE_TSS_Cleanup::detach.
01932     // Two other use cases will be user managed TSS'es and system wide
01933     // TSS, ones are users responsibilities and the others should be
01934     // persistant system wide.
01935     for (int i = 0; i < index; i++)
01936       {
01937 # if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
01938         // Calling thr_keyfree here ensure the key
01939         // gets removed appropriately.  Notice that
01940         // a key should be removed before freeing it.
01941         ACE_OS::thr_keyfree (key_info->key_);
01942 # else
01943         // don't bother to free the key
01944         this->remove (key_info->key_);
01945 # endif /* ACE_WIN32 */
01946       }
01947 # endif /* 0 */
01948   }
01949 }
01950 
01951 int
01952 ACE_TSS_Cleanup::free_all_keys_left (void)
01953   // This is called from ACE_OS::cleanup_tss ().  When this gets
01954   // called, all threads should have exited except the main thread.
01955   // No key should be freed from this routine.  It there's any,
01956   // something might be wrong.
01957 {
01958   ACE_thread_key_t key_arr[ACE_DEFAULT_THREAD_KEYS];
01959   ACE_TSS_TABLE_ITERATOR key_info = table_;
01960   unsigned int idx = 0;
01961   unsigned int i;
01962 
01963   for (i = 0;
01964        i < ACE_DEFAULT_THREAD_KEYS;
01965        ++key_info, ++i)
01966 #if defined (ACE_HAS_TSS_EMULATION)
01967     if (key_info->key_ != in_use_key_)
01968 #endif /* ACE_HAS_TSS_EMULATION */
01969       // Don't call ACE_OS::thr_keyfree () on ACE_TSS_Cleanup's own
01970       // key.  See the comments in ACE_OS::thr_key_detach ():  the key
01971       // doesn't get detached, so it will be in the table here.
01972       // However, there's no resource associated with it, so we don't
01973       // need to keyfree it.  The dynamic memory associated with it
01974       // was already deleted by ACE_TSS_Cleanup::exit (), so we don't
01975       // want to access it again.
01976       key_arr [idx++] = key_info->key_;
01977 
01978   for (i = 0; i < idx; i++)
01979     if (key_arr[i] != ACE_OS::NULL_key)
01980 #if defined (ACE_HAS_TSS_EMULATION)
01981       ACE_OS::thr_keyfree (key_arr[i]);
01982 #elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
01983       // Don't call ACE_OS::thr_keyfree here.  It will try to use
01984       // <in_use_> which has already been cleaned up here.
01985       ::tsd_delete (key_arr[i]);
01986 #else /* ACE_WIN32 */
01987       // Don't call ACE_OS::thr_keyfree here.  It will try to use
01988       // <in_use_> which has already been cleaned up here.
01989       TlsFree (key_arr[i]);
01990 #endif /* ACE_HAS_TSS_EMULATION */
01991 
01992   return 0;
01993 }
01994 
01995 extern "C" void
01996 ACE_TSS_Cleanup_keys_destroyer (void *tss_keys)
01997 {
01998   delete ACE_reinterpret_cast (ACE_TSS_Keys *, tss_keys);
01999 }
02000 
02001 ACE_TSS_Cleanup::ACE_TSS_Cleanup (void)
02002   : in_use_ (ACE_OS::NULL_key)
02003 #if defined (ACE_HAS_TSS_EMULATION)
02004     // ACE_TSS_Emulation::total_keys () provides the value of the next
02005     // key to be created.
02006   , in_use_key_ (ACE_TSS_Emulation::total_keys ())
02007 #endif /* ACE_HAS_TSS_EMULATION */
02008 {
02009   ACE_OS_TRACE ("ACE_TSS_Cleanup::ACE_TSS_Cleanup");
02010 }
02011 
02012 ACE_TSS_Cleanup *
02013 ACE_TSS_Cleanup::instance (void)
02014 {
02015   ACE_OS_TRACE ("ACE_TSS_Cleanup::instance");
02016 
02017   // Create and initialize thread-specific key.
02018   if (ACE_TSS_Cleanup::instance_ == 0)
02019     {
02020       // Insure that we are serialized!
02021       ACE_TSS_CLEANUP_GUARD
02022 
02023       // Now, use the Double-Checked Locking pattern to make sure we
02024       // only create the ACE_TSS_Cleanup instance once.
02025       if (ACE_TSS_Cleanup::instance_ == 0)
02026         ACE_NEW_RETURN (ACE_TSS_Cleanup::instance_,
02027                         ACE_TSS_Cleanup,
02028                         0);
02029     }
02030 
02031   return ACE_TSS_Cleanup::instance_;
02032 }
02033 
02034 int
02035 ACE_TSS_Cleanup::insert (ACE_thread_key_t key,
02036                          void (*destructor)(void *),
02037                          void *inst)
02038 {
02039   ACE_OS_TRACE ("ACE_TSS_Cleanup::insert");
02040   ACE_TSS_CLEANUP_GUARD
02041 
02042   ACE_KEY_INDEX (key_index, key);
02043   if (key_index < ACE_DEFAULT_THREAD_KEYS)
02044     {
02045       table_[key_index] = ACE_TSS_Info (key, destructor, inst);
02046       return 0;
02047     }
02048   else
02049     {
02050       return -1;
02051     }
02052 }
02053 
02054 int
02055 ACE_TSS_Cleanup::remove (ACE_thread_key_t key)
02056 {
02057   ACE_OS_TRACE ("ACE_TSS_Cleanup::remove");
02058   ACE_TSS_CLEANUP_GUARD
02059 
02060   ACE_KEY_INDEX (key_index, key);
02061   if (key_index < ACE_DEFAULT_THREAD_KEYS)
02062     {
02063       // "Remove" the TSS_Info table entry by zeroing out its key_ and
02064       // destructor_ fields.  Also, keep track of the number threads
02065       // using the key.
02066       ACE_TSS_Info &info = this->table_ [key_index];
02067 
02068       // Don't bother to test/clear the in "use bit" if the program is
02069       // shutting down.  Doing so will cause a new ACE_TSS object to be
02070       // created again.
02071       if (!ACE_OS_Object_Manager::shutting_down ())
02072         tss_keys ()->test_and_clear (info.key_);
02073       info.key_in_use (0);
02074       info.key_ = ACE_OS::NULL_key;
02075       info.destructor_ = 0;
02076       return 0;
02077     }
02078   else
02079     return -1;
02080 }
02081 
02082 int
02083 ACE_TSS_Cleanup::detach (void *inst)
02084 {
02085   ACE_TSS_CLEANUP_GUARD
02086 
02087   ACE_TSS_TABLE_ITERATOR key_info = table_;
02088   int success = 0;
02089   int ref_cnt = 0;
02090 
02091   // Mark the key as detached in the TSS_Info table.
02092   // It only works for the first key that "inst" owns.
02093   // I don't know why.
02094   for (unsigned int i = 0;
02095        i < ACE_DEFAULT_THREAD_KEYS;
02096        ++key_info, ++i)
02097     {
02098       if (key_info->tss_obj_ == inst)
02099         {
02100           key_info->tss_obj_ = 0;
02101           ref_cnt = --key_info->thread_count_;
02102           success = 1;
02103           break;
02104         }
02105     }
02106 
02107   if (success == 0)
02108     return -1;
02109   else if (ref_cnt == 0)
02110     {
02111       // Mark the key as no longer being used.
02112       key_info->key_in_use (0);
02113 # if defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
02114       ACE_thread_key_t temp_key = key_info->key_;
02115 # endif /* ACE_WIN32 */
02116       int retv = this->remove (key_info->key_);
02117 
02118 # if defined (ACE_WIN32)
02119       ::TlsFree (temp_key);
02120 # elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
02121       ::tsd_delete (temp_key);
02122 # endif /* ACE_WIN32 */
02123       return retv;
02124     }
02125 
02126   return 0;
02127 }
02128 
02129 void
02130 ACE_TSS_Cleanup::key_used (ACE_thread_key_t key)
02131 {
02132   // If the key's ACE_TSS_Info in-use bit for this thread is not set,
02133   // set it and increment the key's thread_count_.
02134   if (! tss_keys ()->test_and_set (key))
02135     {
02136       ACE_TSS_CLEANUP_GUARD
02137 
02138       // Retrieve the key's ACE_TSS_Info and increment its thread_count_.
02139       ACE_KEY_INDEX (key_index, key);
02140       ACE_TSS_Info &key_info = this->table_ [key_index];
02141       if (!key_info.key_in_use ())
02142         key_info.key_in_use (1);
02143       else
02144         ++key_info.thread_count_;
02145     }
02146 }
02147 
02148 void
02149 ACE_TSS_Cleanup::dump (void)
02150 {
02151   // Iterate through all the thread-specific items and dump them all.
02152 
02153   ACE_TSS_TABLE_ITERATOR key_info = table_;
02154   for (unsigned int i = 0;
02155        i < ACE_DEFAULT_THREAD_KEYS;
02156        ++key_info, ++i)
02157     key_info->dump ();
02158 }
02159 
02160 ACE_TSS_Keys *
02161 ACE_TSS_Cleanup::tss_keys ()
02162 {
02163   if (in_use_ == ACE_OS::NULL_key)
02164     {
02165       ACE_TSS_CLEANUP_GUARD
02166       // Double-check;
02167       if (in_use_ == ACE_OS::NULL_key)
02168         {
02169           // Initialize in_use_ with a new key.
02170           if (ACE_OS::thr_keycreate (&in_use_,
02171                                      &ACE_TSS_Cleanup_keys_destroyer))
02172             return 0; // Major problems, this should *never* happen!
02173         }
02174     }
02175 
02176   ACE_TSS_Keys *ts_keys = 0;
02177   if (ACE_OS::thr_getspecific (in_use_,
02178         ACE_reinterpret_cast (void **, &ts_keys)) == -1)
02179     return 0; // This should not happen!
02180 
02181   if (ts_keys == 0)
02182     {
02183       ACE_NEW_RETURN (ts_keys,
02184                       ACE_TSS_Keys,
02185                       0);
02186       // Store the dynamically allocated pointer in thread-specific
02187       // storage.
02188       if (ACE_OS::thr_setspecific (in_use_,
02189             ACE_reinterpret_cast (void *,
02190                                   ts_keys)) == -1)
02191         {
02192           delete ts_keys;
02193           return 0; // Major problems, this should *never* happen!
02194         }
02195     }
02196 
02197   return ts_keys;
02198 }
02199 
02200 # if defined (ACE_HAS_TSS_EMULATION)
02201 u_int ACE_TSS_Emulation::total_keys_ = 0;
02202 
02203 ACE_TSS_Keys ACE_TSS_Emulation::tss_keys_used_;
02204 
02205 ACE_TSS_Emulation::ACE_TSS_DESTRUCTOR
02206 ACE_TSS_Emulation::tss_destructor_[ACE_TSS_Emulation::ACE_TSS_THREAD_KEYS_MAX]
02207  = { 0 };
02208 
02209 #   if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
02210 
02211 int ACE_TSS_Emulation::key_created_ = 0;
02212 
02213 ACE_OS_thread_key_t ACE_TSS_Emulation::native_tss_key_;
02214 
02215 /* static */
02216 #     if defined (ACE_HAS_THR_C_FUNC)
02217 extern "C"
02218 void
02219 ACE_TSS_Emulation_cleanup (void *ptr)
02220 {
02221    ACE_UNUSED_ARG (ptr);
02222    // Really this must be used for ACE_TSS_Emulation code to make the TSS
02223    // cleanup
02224 }
02225 #else
02226 void
02227 ACE_TSS_Emulation_cleanup (void *ptr)
02228 {
02229    ACE_UNUSED_ARG (ptr);
02230    // Really this must be used for ACE_TSS_Emulation code to make the TSS
02231    // cleanup
02232 }
02233 #     endif /* ACE_HAS_THR_C_FUNC */
02234 
02235 void **
02236 ACE_TSS_Emulation::tss_base (void* ts_storage[], u_int *ts_created)
02237 {
02238   // TSS Singleton implementation.
02239 
02240   // Create the one native TSS key, if necessary.
02241   if (key_created_ == 0)
02242     {
02243       // Double-checked lock . . .
02244       ACE_TSS_BASE_GUARD
02245 
02246       if (key_created_ == 0)
02247         {
02248           ACE_NO_HEAP_CHECK;
02249           if (ACE_OS::thr_keycreate (&native_tss_key_,
02250                                      &ACE_TSS_Emulation_cleanup) != 0)
02251             {
02252               return 0; // Major problems, this should *never* happen!
02253             }
02254           key_created_ = 1;
02255         }
02256     }
02257 
02258   void **old_ts_storage = 0;
02259 
02260   // Get the tss_storage from thread-OS specific storage.
02261   if (ACE_OS::thr_getspecific (native_tss_key_,
02262                                (void **) &old_ts_storage) == -1)
02263     return 0; // This should not happen!
02264 
02265   // Check to see if this is the first time in for this thread.
02266   // This block can also be entered after a fork () in the child process,
02267   // at least on Pthreads Draft 4 platforms.
02268   if (old_ts_storage == 0)
02269     {
02270       if (ts_created)
02271         *ts_created = 1u;
02272 
02273       // Use the ts_storage passed as argument, if non-zero.  It is
02274       // possible that this has been implemented in the stack. At the
02275       // moment, this is unknown.  The cleanup must not do nothing.
02276       // If ts_storage is zero, allocate (and eventually leak) the
02277       // storage array.
02278       if (ts_storage == 0)
02279         {
02280           ACE_NO_HEAP_CHECK;
02281 
02282           ACE_NEW_RETURN (ts_storage,
02283                           void*[ACE_TSS_THREAD_KEYS_MAX],
02284                           0);
02285 
02286           // Zero the entire TSS array.  Do it manually instead of
02287           // using memset, for optimum speed.  Though, memset may be
02288           // faster :-)
02289           void **tss_base_p = ts_storage;
02290 
02291           for (u_int i = 0;
02292                i < ACE_TSS_THREAD_KEYS_MAX;
02293                ++i)
02294             *tss_base_p++ = 0;
02295         }
02296 
02297        // Store the pointer in thread-specific storage.  It gets
02298        // deleted via the ACE_TSS_Emulation_cleanup function when the
02299        // thread terminates.
02300        if (ACE_OS::thr_setspecific (native_tss_key_,
02301                                     (void *) ts_storage) != 0)
02302           return 0; // Major problems, this should *never* happen!
02303     }
02304   else
02305     if (ts_created)
02306       ts_created = 0;
02307 
02308   return ts_storage  ?  ts_storage  :  old_ts_storage;
02309 }
02310 #   endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
02311 
02312 u_int
02313 ACE_TSS_Emulation::total_keys ()
02314 {
02315   ACE_OS_Recursive_Thread_Mutex_Guard (
02316     *ACE_static_cast (ACE_recursive_thread_mutex_t *,
02317                       ACE_OS_Object_Manager::preallocated_object[
02318                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
02319 
02320   return total_keys_;
02321 }
02322 
02323 int
02324 ACE_TSS_Emulation::next_key (ACE_thread_key_t &key)
02325 {
02326   ACE_OS_Recursive_Thread_Mutex_Guard (
02327     *ACE_static_cast (ACE_recursive_thread_mutex_t *,
02328                       ACE_OS_Object_Manager::preallocated_object[
02329                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
02330 
02331   if (total_keys_ < ACE_TSS_THREAD_KEYS_MAX)
02332     {
02333        u_int counter = 0;
02334        // Loop through all possible keys and check whether a key is free
02335        for ( ;counter < ACE_TSS_THREAD_KEYS_MAX; counter++)
02336          {
02337             ACE_thread_key_t localkey;
02338 #   if defined (ACE_HAS_NONSCALAR_THREAD_KEY_T)
02339               ACE_OS::memset (&localkey, 0, sizeof (ACE_thread_key_t));
02340               ACE_OS::memcpy (&localkey, &counter_, sizeof (u_int));
02341 #   else
02342               localkey = counter;
02343 #   endif /* ACE_HAS_NONSCALAR_THREAD_KEY_T */
02344             // If the key is not set as used, we can give out this key, if not
02345             // we have to search further
02346             if (tss_keys_used_.is_set(localkey) == 0)
02347             {
02348                tss_keys_used_.test_and_set(localkey);
02349                key = localkey;
02350                break;
02351             }
02352          }
02353 
02354       ++total_keys_;
02355       return 0;
02356     }
02357   else
02358     {
02359       key = ACE_OS::NULL_key;
02360       return -1;
02361     }
02362 }
02363 
02364 int
02365 ACE_TSS_Emulation::release_key (ACE_thread_key_t key)
02366 {
02367   ACE_OS_Recursive_Thread_Mutex_Guard (
02368     *ACE_static_cast (ACE_recursive_thread_mutex_t *,
02369                       ACE_OS_Object_Manager::preallocated_object[
02370                         ACE_OS_Object_Manager::ACE_TSS_KEY_LOCK]));
02371 
02372   if (tss_keys_used_.test_and_clear (key) == 0)
02373   {
02374     --total_keys_;
02375     return 0;
02376   }
02377   return 1;
02378 }
02379 
02380 void *
02381 ACE_TSS_Emulation::tss_open (void *ts_storage[ACE_TSS_THREAD_KEYS_MAX])
02382 {
02383 #   if defined (ACE_PSOS)
02384   u_long tss_base;
02385 
02386   // Use the supplied array for this thread's TSS.
02387   tss_base = (u_long) ts_storage;
02388   t_setreg (0, PSOS_TASK_REG_TSS, tss_base);
02389 
02390   // Zero the entire TSS array.
02391   void **tss_base_p = ts_storage;
02392   for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
02393     {
02394       *tss_base_p = 0;
02395     }
02396 
02397   return (void *) tss_base;
02398 #   else  /* ! ACE_PSOS */
02399 #     if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
02400         // On VxWorks, in particular, don't check to see if the field
02401         // is 0.  It isn't always, specifically, when a program is run
02402         // directly by the shell (without spawning a new task) after
02403         // another program has been run.
02404 
02405   u_int ts_created = 0;
02406   tss_base (ts_storage, &ts_created);
02407   if (ts_created)
02408     {
02409 #     else  /* ! ACE_HAS_THREAD_SPECIFIC_STORAGE */
02410       tss_base () = ts_storage;
02411 #     endif
02412 
02413       // Zero the entire TSS array.  Do it manually instead of using
02414       // memset, for optimum speed.  Though, memset may be faster :-)
02415       void **tss_base_p = tss_base ();
02416       for (u_int i = 0; i < ACE_TSS_THREAD_KEYS_MAX; ++i, ++tss_base_p)
02417         {
02418           *tss_base_p = 0;
02419         }
02420 
02421       return tss_base ();
02422 #     if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
02423     }
02424   else
02425     {
02426       return 0;
02427     }
02428 #     endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
02429 #   endif /* ! ACE_PSOS */
02430 }
02431 
02432 void
02433 ACE_TSS_Emulation::tss_close ()
02434 {
02435 #if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
02436   // Free native_tss_key_ here.
02437 #endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
02438 }
02439 
02440 # endif /* ACE_HAS_TSS_EMULATION */
02441 
02442 #endif /* WIN32 || ACE_HAS_TSS_EMULATION */
02443 
02444 void
02445 ACE_OS::cleanup_tss (const u_int main_thread)
02446 {
02447 #if defined (ACE_HAS_TSS_EMULATION) || defined (ACE_WIN32) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
02448   // Call TSS destructors for current thread.
02449   ACE_TSS_Cleanup::instance ()->exit (0);
02450 #endif /* ACE_HAS_TSS_EMULATION || ACE_WIN32 || ACE_PSOS_HAS_TSS */
02451 
02452   if (main_thread)
02453     {
02454 #if !defined (ACE_HAS_TSS_EMULATION)  &&  !defined (ACE_HAS_MINIMAL_ACE_OS)
02455       // Just close the ACE_Log_Msg for the current (which should be
02456       // main) thread.  We don't have TSS emulation; if there's native
02457       // TSS, it should call its destructors when the main thread
02458       // exits.
02459       ACE_Base_Thread_Adapter::close_log_msg ();
02460 #endif /* ! ACE_HAS_TSS_EMULATION  &&  ! ACE_HAS_MINIMAL_ACE_OS */
02461 
02462 #if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
02463 #if ! defined (ACE_HAS_TSS_EMULATION)
02464       // Don't do this with TSS_Emulation, because the the
02465       // ACE_TSS_Cleanup::instance () has already exited ().  We can't
02466       // safely access the TSS values that were created by the main
02467       // thread.
02468 
02469       // Remove all TSS_Info table entries.
02470       ACE_TSS_Cleanup::instance ()->free_all_keys_left ();
02471 #endif /* ! ACE_HAS_TSS_EMULATION */
02472 
02473       // Finally, free up the ACE_TSS_Cleanup instance.  This method gets
02474       // called by the ACE_Object_Manager.
02475       delete ACE_TSS_Cleanup::instance ();
02476 #endif /* WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */
02477 
02478 #if defined (ACE_HAS_TSS_EMULATION)
02479       ACE_TSS_Emulation::tss_close ();
02480 #endif /* ACE_HAS_TSS_EMULATION */
02481     }
02482 }
02483 
02484 #if !defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
02485 #define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
02486        (*THR_ID = ::_beginthreadex ((void(_Optlink*)(void*))ENTRY_POINT, STACK, STACKSIZE, ARGS), *THR_ID)
02487 #elif defined(ACE_WIN32) && defined (__IBMCPP__) && (__IBMCPP__ >= 400)
02488 
02489 struct __IBMCPP__thread_params {
02490   __IBMCPP__thread_params(ACE_THR_C_FUNC e, LPVOID a)
02491     :entry_point(e),args(a) {}
02492   ACE_THR_C_FUNC entry_point;
02493   LPVOID args;
02494 };
02495 
02496 #pragma handler(initThread)
02497 extern "C" DWORD __stdcall __IBMCPP__initThread(void *arg)
02498 {
02499   // Must reset 387 since using CreateThread
02500   _fpreset();
02501 
02502   // Dispatch user function...
02503   auto_ptr<__IBMCPP__thread_params> parms((__IBMCPP__thread_params *)arg);
02504   (*parms->entry_point)(parms->args);
02505   _endthread();
02506   return 0;
02507 }
02508 
02509 HANDLE WINAPI __IBMCPP__beginthreadex(void *stack,
02510                                       DWORD stacksize,
02511                                       ACE_THR_C_FUNC entry_point,
02512                                       LPVOID args,
02513                                       DWORD flags,
02514                                       LPDWORD thr_id)
02515 {
02516   return  CreateThread(0,
02517                        stacksize,
02518                        (LPTHREAD_START_ROUTINE)__IBMCPP__initThread,
02519                        new __IBMCPP__thread_params(entry_point, args),
02520                        flags,
02521                        thr_id);
02522 }
02523 
02524 #define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
02525              __IBMCPP__beginthreadex(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID)
02526 
02527 #elif defined (ACE_HAS_WINCE) && defined (UNDER_CE) && (UNDER_CE >= 211)
02528 #define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
02529       CreateThread (0, STACKSIZE, (unsigned long (__stdcall *) (void *)) ENTRY_POINT, ARGS, (FLAGS) & CREATE_SUSPENDED, (unsigned long *) THR_ID)
02530 #elif defined(ACE_HAS_WTHREADS)
02531   // Green Hills compiler gets confused when __stdcall is imbedded in
02532   // parameter list, so we define the type ACE_WIN32THRFUNC_T and use it
02533   // instead.
02534   typedef unsigned (__stdcall *ACE_WIN32THRFUNC_T)(void*);
02535 #define ACE_BEGINTHREADEX(STACK, STACKSIZE, ENTRY_POINT, ARGS, FLAGS, THR_ID) \
02536       ::_beginthreadex (STACK, STACKSIZE, (ACE_WIN32THRFUNC_T) ENTRY_POINT, ARGS, FLAGS, (unsigned int *) THR_ID)
02537 #endif /* defined (__IBMCPP__) && (__IBMCPP__ >= 400) */
02538 
02539 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
02540 int ACE_SEH_Default_Exception_Selector (void *)
02541 {
02542 #if 0
02543   ACE_DEBUG ((LM_DEBUG,
02544               ACE_LIB_TEXT ("(%t) Win32 structured exception exiting thread\n")));
02545 #endif /* 0 */
02546   return (DWORD) ACE_SEH_DEFAULT_EXCEPTION_HANDLING_ACTION;
02547 }
02548 
02549 int ACE_SEH_Default_Exception_Handler (void *)
02550 {
02551   return 0;
02552 }
02553 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
02554 
02555 extern "C" void
02556 ace_cleanup_destroyer (ACE_Cleanup *object, void *param)
02557 {
02558   object->cleanup (param);
02559 }
02560 
02561 int
02562 ACE_OS::thr_create (ACE_THR_FUNC func,
02563                     void *args,
02564                     long flags,
02565                     ACE_thread_t *thr_id,
02566                     ACE_hthread_t *thr_handle,
02567                     long priority,
02568                     void *stack,
02569                     size_t stacksize,
02570                     ACE_Base_Thread_Adapter *thread_adapter)
02571 {
02572   ACE_OS_TRACE ("ACE_OS::thr_create");
02573 
02574   if (ACE_BIT_DISABLED (flags, THR_DETACHED) &&
02575       ACE_BIT_DISABLED (flags, THR_JOINABLE))
02576     ACE_SET_BITS (flags, THR_JOINABLE);
02577 
02578 # if defined (ACE_NO_THREAD_ADAPTER)
02579 #   define  ACE_THREAD_FUNCTION  func
02580 #   define  ACE_THREAD_ARGUMENT  args
02581 # else /* ! defined (ACE_NO_THREAD_ADAPTER) */
02582 #   if defined (ACE_PSOS)
02583 #     define  ACE_THREAD_FUNCTION (PSOS_TASK_ENTRY_POINT) thread_args->entry_point ()
02584 #   else
02585 #     define  ACE_THREAD_FUNCTION  thread_args->entry_point ()
02586 #   endif /* defined (ACE_PSOS) */
02587 #   define  ACE_THREAD_ARGUMENT  thread_args
02588 # endif /* ! defined (ACE_NO_THREAD_ADAPTER) */
02589 
02590 
02591   ACE_Base_Thread_Adapter *thread_args;
02592   if (thread_adapter == 0)
02593 
02594 # if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
02595     ACE_NEW_RETURN (thread_args,
02596                     ACE_OS_Thread_Adapter (func, args,
02597                                            (ACE_THR_C_FUNC) ace_thread_adapter,
02598                                            ACE_OS_Object_Manager::seh_except_selector(),
02599                                            ACE_OS_Object_Manager::seh_except_handler()),
02600                     -1);
02601 # else
02602   ACE_NEW_RETURN (thread_args,
02603                   ACE_OS_Thread_Adapter (func, args,
02604                                          (ACE_THR_C_FUNC) ace_thread_adapter),
02605                   -1);
02606 
02607 # endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
02608   else
02609     thread_args = thread_adapter;
02610 
02611 # if defined (ACE_HAS_THREADS)
02612 
02613   // *** Set Stack Size
02614 #   if defined (ACE_NEEDS_HUGE_THREAD_STACKSIZE)
02615   if (stacksize < ACE_NEEDS_HUGE_THREAD_STACKSIZE)
02616     stacksize = ACE_NEEDS_HUGE_THREAD_STACKSIZE;
02617 #   endif /* ACE_NEEDS_HUGE_THREAD_STACKSIZE */
02618 
02619 #   if !defined (VXWORKS)
02620   // On VxWorks, the OS will provide a task name if the user doesn't.
02621   // So, we don't need to create a tmp_thr.  If the caller of this
02622   // member function is the Thread_Manager, than thr_id will be non-zero
02623   // anyways.
02624   ACE_thread_t tmp_thr;
02625 
02626   if (thr_id == 0)
02627     thr_id = &tmp_thr;
02628 #   endif /* ! VXWORKS */
02629 
02630   ACE_hthread_t tmp_handle;
02631   if (thr_handle == 0)
02632     thr_handle = &tmp_handle;
02633 
02634 #   if defined (ACE_HAS_PTHREADS)
02635 
02636   int result;
02637   pthread_attr_t attr;
02638 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
02639   if (::pthread_attr_create (&attr) != 0)
02640 #     else /* ACE_HAS_PTHREADS_DRAFT4 */
02641     if (::pthread_attr_init (&attr) != 0)
02642 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
02643       return -1;
02644 
02645 #     if defined (CHORUS)
02646   // If it is a super actor, we can't set stacksize.  But for the time
02647   // being we are all non-super actors.  Should be fixed to take care
02648   // of super actors!!!
02649   if (stacksize == 0)
02650     stacksize = ACE_CHORUS_DEFAULT_MIN_STACK_SIZE;
02651   else if (stacksize < ACE_CHORUS_DEFAULT_MIN_STACK_SIZE)
02652     stacksize = ACE_CHORUS_DEFAULT_MIN_STACK_SIZE;
02653 #     endif /*CHORUS */
02654 
02655 # if defined (ACE_HAS_PTHREAD_SETSTACK)
02656   if ((stacksize != 0) && (stack != 0))
02657 # else
02658   if (stacksize != 0)
02659 # endif /* ACE_HAS_PTHREAD_SETSTACK */
02660     {
02661       size_t size = stacksize;
02662 
02663 #     if defined (PTHREAD_STACK_MIN)
02664       if (size < ACE_static_cast (size_t, PTHREAD_STACK_MIN))
02665         size = PTHREAD_STACK_MIN;
02666 #     endif /* PTHREAD_STACK_MIN */
02667 
02668 #     if !defined (ACE_LACKS_THREAD_STACK_SIZE)      // JCEJ 12/17/96
02669 #       if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
02670       if (::pthread_attr_setstacksize (&attr, size) != 0)
02671 #       else
02672 #         if defined (ACE_HAS_PTHREAD_SETSTACK)
02673         if (ACE_ADAPT_RETVAL(pthread_attr_setstack (&attr, stack, size), result) == -1)
02674 #         else
02675         if (ACE_ADAPT_RETVAL(pthread_attr_setstacksize (&attr, size), result) == -1)
02676 #         endif /* ACE_HAS_PTHREAD_SETSTACK */
02677 #       endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */
02678           {
02679 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02680             ::pthread_attr_delete (&attr);
02681 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02682             ::pthread_attr_destroy (&attr);
02683 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02684             return -1;
02685           }
02686 #     else
02687       ACE_UNUSED_ARG (size);
02688 #     endif /* !ACE_LACKS_THREAD_STACK_SIZE */
02689     }
02690 
02691   // *** Set Stack Address
02692 #     if !defined (ACE_HAS_PTHREAD_SETSTACK)
02693 #     if !defined (ACE_LACKS_THREAD_STACK_ADDR)
02694   if (stack != 0)
02695     {
02696       if (::pthread_attr_setstackaddr (&attr, stack) != 0)
02697         {
02698 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02699           ::pthread_attr_delete (&attr);
02700 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02701           ::pthread_attr_destroy (&attr);
02702 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02703           return -1;
02704         }
02705     }
02706 #     else
02707   ACE_UNUSED_ARG (stack);
02708 #     endif /* !ACE_LACKS_THREAD_STACK_ADDR */
02709 #     endif /* ACE_HAS_PTHREAD_SETSTACK */
02710 
02711   // *** Deal with various attributes
02712   if (flags != 0)
02713     {
02714       // *** Set Detach state
02715 #     if !defined (ACE_LACKS_SETDETACH)
02716       if (ACE_BIT_ENABLED (flags, THR_DETACHED)
02717           || ACE_BIT_ENABLED (flags, THR_JOINABLE))
02718         {
02719           int dstate = PTHREAD_CREATE_JOINABLE;
02720 
02721           if (ACE_BIT_ENABLED (flags, THR_DETACHED))
02722             dstate = PTHREAD_CREATE_DETACHED;
02723 
02724 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02725           if (::pthread_attr_setdetach_np (&attr, dstate) != 0)
02726 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02727 #         if defined (ACE_HAS_PTHREADS_DRAFT6)
02728             if (::pthread_attr_setdetachstate (&attr, &dstate) != 0)
02729 #         else
02730               if (ACE_ADAPT_RETVAL(::pthread_attr_setdetachstate (&attr, dstate),
02731                                    result) != 0)
02732 #         endif /* ACE_HAS_PTHREADS_DRAFT6 */
02733 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02734                 {
02735 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02736                   ::pthread_attr_delete (&attr);
02737 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02738                   ::pthread_attr_destroy (&attr);
02739 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02740                   return -1;
02741                 }
02742         }
02743 
02744       // Note: if ACE_LACKS_SETDETACH and THR_DETACHED is enabled, we
02745       // call ::pthread_detach () below.  If THR_DETACHED is not
02746       // enabled, we call ::pthread_detach () in the Thread_Manager,
02747       // after joining with the thread.
02748 #     endif /* ACE_LACKS_SETDETACH */
02749 
02750       // *** Set Policy
02751 #     if !defined (ACE_LACKS_SETSCHED)
02752       // If we wish to set the priority explicitly, we have to enable
02753       // explicit scheduling, and a policy, too.
02754       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
02755         {
02756           ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
02757           if (ACE_BIT_DISABLED (flags, THR_SCHED_FIFO)
02758               && ACE_BIT_DISABLED (flags, THR_SCHED_RR)
02759               && ACE_BIT_DISABLED (flags, THR_SCHED_DEFAULT))
02760             ACE_SET_BITS (flags, THR_SCHED_DEFAULT);
02761         }
02762 
02763       if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
02764           || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
02765           || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
02766         {
02767           int spolicy;
02768 
02769 #       if defined (ACE_HAS_ONLY_SCHED_OTHER)
02770           // SunOS, thru version 5.6, only supports SCHED_OTHER.
02771           spolicy = SCHED_OTHER;
02772 #       else
02773           // Make sure to enable explicit scheduling, in case we didn't
02774           // enable it above (for non-default priority).
02775           ACE_SET_BITS (flags, THR_EXPLICIT_SCHED);
02776 
02777           if (ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
02778             spolicy = SCHED_OTHER;
02779           else if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
02780             spolicy = SCHED_FIFO;
02781 #         if defined (SCHED_IO)
02782           else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
02783             spolicy = SCHED_IO;
02784 #         else
02785           else if (ACE_BIT_ENABLED (flags, THR_SCHED_IO))
02786             {
02787               errno = ENOSYS;
02788               return -1;
02789             }
02790 #         endif /* SCHED_IO */
02791           else
02792             spolicy = SCHED_RR;
02793 
02794 #         if defined (ACE_HAS_FSU_PTHREADS)
02795           int ret;
02796           switch (spolicy)
02797             {
02798             case SCHED_FIFO:
02799             case SCHED_RR:
02800               ret = 0;
02801               break;
02802             default:
02803               ret = 22;
02804               break;
02805             }
02806           if (ret != 0)
02807             {
02808               ::pthread_attr_destroy (&attr);
02809               return -1;
02810             }
02811 #         endif    /*  ACE_HAS_FSU_PTHREADS */
02812 
02813 #       endif /* ACE_HAS_ONLY_SCHED_OTHER */
02814 
02815 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02816           result = ::pthread_attr_setsched (&attr, spolicy);
02817 #       elif defined (ACE_HAS_PTHREADS_DRAFT6)
02818           result = ::pthread_attr_setschedpolicy (&attr, spolicy);
02819 #       else  /* draft 7 or std */
02820           ACE_ADAPT_RETVAL(::pthread_attr_setschedpolicy (&attr, spolicy),
02821                            result);
02822 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02823           if (result != 0)
02824             {
02825 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02826               ::pthread_attr_delete (&attr);
02827 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02828               ::pthread_attr_destroy (&attr);
02829 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02830               return -1;
02831             }
02832         }
02833 
02834       // *** Set Priority (use reasonable default priorities)
02835 #       if defined(ACE_HAS_PTHREADS_STD)
02836       // If we wish to explicitly set a scheduling policy, we also
02837       // have to specify a priority.  We choose a "middle" priority as
02838       // default.  Maybe this is also necessary on other POSIX'ish
02839       // implementations?
02840       if ((ACE_BIT_ENABLED (flags, THR_SCHED_FIFO)
02841            || ACE_BIT_ENABLED (flags, THR_SCHED_RR)
02842            || ACE_BIT_ENABLED (flags, THR_SCHED_DEFAULT))
02843           && priority == ACE_DEFAULT_THREAD_PRIORITY)
02844         {
02845           if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
02846             priority = ACE_THR_PRI_FIFO_DEF;
02847           else if (ACE_BIT_ENABLED (flags, THR_SCHED_RR))
02848             priority = ACE_THR_PRI_RR_DEF;
02849           else // THR_SCHED_DEFAULT
02850             priority = ACE_THR_PRI_OTHER_DEF;
02851         }
02852 #       endif /* ACE_HAS_PTHREADS_STD */
02853       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
02854         {
02855           struct sched_param sparam;
02856           ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
02857 
02858 #       if defined (ACE_HAS_IRIX62_THREADS)
02859           sparam.sched_priority = ACE_MIN (priority,
02860                                            (long) PTHREAD_MAX_PRIORITY);
02861 #       elif defined (PTHREAD_MAX_PRIORITY) && !defined(ACE_HAS_PTHREADS_STD)
02862           /* For MIT pthreads... */
02863           sparam.prio = ACE_MIN (priority, PTHREAD_MAX_PRIORITY);
02864 #       elif defined(ACE_HAS_PTHREADS_STD) && !defined (ACE_HAS_STHREADS)
02865           // The following code forces priority into range.
02866           if (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO))
02867             sparam.sched_priority =
02868               ACE_MIN (ACE_THR_PRI_FIFO_MAX,
02869                        ACE_MAX (ACE_THR_PRI_FIFO_MIN, priority));
02870           else if (ACE_BIT_ENABLED(flags, THR_SCHED_RR))
02871             sparam.sched_priority =
02872               ACE_MIN (ACE_THR_PRI_RR_MAX,
02873                        ACE_MAX (ACE_THR_PRI_RR_MIN, priority));
02874           else // Default policy, whether set or not
02875             sparam.sched_priority =
02876               ACE_MIN (ACE_THR_PRI_OTHER_MAX,
02877                        ACE_MAX (ACE_THR_PRI_OTHER_MIN, priority));
02878 #       elif defined (PRIORITY_MAX)
02879           sparam.sched_priority = ACE_MIN (priority,
02880                                            (long) PRIORITY_MAX);
02881 #       else
02882           sparam.sched_priority = priority;
02883 #       endif /* ACE_HAS_IRIX62_THREADS */
02884 
02885 #       if defined (ACE_HAS_FSU_PTHREADS)
02886           if (sparam.sched_priority >= PTHREAD_MIN_PRIORITY
02887               && sparam.sched_priority <= PTHREAD_MAX_PRIORITY)
02888             attr.prio = sparam.sched_priority;
02889           else
02890             {
02891               pthread_attr_destroy (&attr);
02892               errno = EINVAL;
02893               return -1;
02894             }
02895 #       else
02896           {
02897 #         if defined (sun)  &&  defined (ACE_HAS_ONLY_SCHED_OTHER)
02898             // SunOS, through 5.6, POSIX only allows priorities > 0 to
02899             // ::pthread_attr_setschedparam.  If a priority of 0 was
02900             // requested, set the thread priority after creating it, below.
02901             if (priority > 0)
02902 #         endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
02903               {
02904 #         if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
02905                 result = ::pthread_attr_setprio (&attr,
02906                                                  sparam.sched_priority);
02907 #         else /* this is draft 7 or std */
02908                 ACE_ADAPT_RETVAL(::pthread_attr_setschedparam (&attr, &sparam),
02909                                  result);
02910 #         endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */
02911                 if (result != 0)
02912                   {
02913 #         if defined (ACE_HAS_PTHREADS_DRAFT4)
02914                     ::pthread_attr_delete (&attr);
02915 #         else /* ACE_HAS_PTHREADS_DRAFT4 */
02916                     ::pthread_attr_destroy (&attr);
02917 #         endif /* ACE_HAS_PTHREADS_DRAFT4 */
02918                     return -1;
02919                   }
02920               }
02921           }
02922 #       endif    /* ACE_HAS_FSU_PTHREADS */
02923         }
02924 
02925       // *** Set scheduling explicit or inherited
02926       if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED)
02927           || ACE_BIT_ENABLED (flags, THR_EXPLICIT_SCHED))
02928         {
02929 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02930           int sched = PTHREAD_DEFAULT_SCHED;
02931 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02932           int sched = PTHREAD_EXPLICIT_SCHED;
02933 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02934           if (ACE_BIT_ENABLED (flags, THR_INHERIT_SCHED))
02935             sched = PTHREAD_INHERIT_SCHED;
02936           if (::pthread_attr_setinheritsched (&attr, sched) != 0)
02937             {
02938 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02939               ::pthread_attr_delete (&attr);
02940 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02941               ::pthread_attr_destroy (&attr);
02942 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02943               return -1;
02944             }
02945         }
02946 #     else /* ACE_LACKS_SETSCHED */
02947       ACE_UNUSED_ARG (priority);
02948 #     endif /* ACE_LACKS_SETSCHED */
02949 
02950       // *** Set Scope
02951 #     if !defined (ACE_LACKS_THREAD_PROCESS_SCOPING)
02952       if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM)
02953           || ACE_BIT_ENABLED (flags, THR_SCOPE_PROCESS))
02954         {
02955 #         if defined (ACE_CONFIG_LINUX_H) || defined (HPUX)
02956           // LinuxThreads do not have support for PTHREAD_SCOPE_PROCESS.
02957           // Neither does HPUX (up to HP-UX 11.00, as far as I know).
02958           int scope = PTHREAD_SCOPE_SYSTEM;
02959 #         else /* ACE_CONFIG_LINUX_H */
02960           int scope = PTHREAD_SCOPE_PROCESS;
02961 #         endif /* ACE_CONFIG_LINUX_H */
02962           if (ACE_BIT_ENABLED (flags, THR_SCOPE_SYSTEM))
02963             scope = PTHREAD_SCOPE_SYSTEM;
02964 
02965           if (::pthread_attr_setscope (&attr, scope) != 0)
02966             {
02967 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
02968               ::pthread_attr_delete (&attr);
02969 #       else /* ACE_HAS_PTHREADS_DRAFT4 */
02970               ::pthread_attr_destroy (&attr);
02971 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
02972               return -1;
02973             }
02974         }
02975 #     endif /* !ACE_LACKS_THREAD_PROCESS_SCOPING */
02976 
02977       if (ACE_BIT_ENABLED (flags, THR_NEW_LWP))
02978         {
02979           // Increment the number of LWPs by one to emulate the
02980           // SunOS semantics.
02981           int lwps = ACE_OS::thr_getconcurrency ();
02982           if (lwps == -1)
02983             {
02984               if (errno == ENOTSUP)
02985                 // Suppress the ENOTSUP because it's harmless.
02986                 errno = 0;
02987               else
02988                 // This should never happen on SunOS:
02989                 // ::thr_getconcurrency () should always succeed.
02990                 return -1;
02991             }
02992           else if (ACE_OS::thr_setconcurrency (lwps + 1) == -1)
02993             {
02994               if (errno == ENOTSUP)
02995                 {
02996                   // Unlikely:  ::thr_getconcurrency () is supported but
02997                   // ::thr_setconcurrency () is not?
02998                 }
02999               else
03000                 return -1;
03001             }
03002         }
03003     }
03004 
03005 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
03006   ACE_OSCALL (::pthread_create (thr_id, attr,
03007                                 thread_args->entry_point (),
03008                                 thread_args),
03009               int, -1, result);
03010 
03011 #       if defined (ACE_LACKS_SETDETACH)
03012   if (ACE_BIT_ENABLED (flags, THR_DETACHED))
03013     {
03014 #         if defined (HPUX_10)
03015       // HP-UX DCE threads' pthread_detach will smash thr_id if it's
03016       // just given as an argument.  This will cause
03017       // ACE_Thread_Manager (if it's doing this create) to lose track
03018       // of the new thread since the ID will be passed back equal to
03019       // 0.  So give pthread_detach a junker to scribble on.
03020       ACE_thread_t  junker;
03021       cma_handle_assign(thr_id, &junker);
03022       ::pthread_detach (&junker);
03023 #         else
03024       ::pthread_detach (thr_id);
03025 #         endif /* HPUX_10 */
03026     }
03027 #       endif /* ACE_LACKS_SETDETACH */
03028 
03029   ::pthread_attr_delete (&attr);
03030 
03031 #     elif defined (ACE_HAS_PTHREADS_DRAFT6)
03032   ACE_OSCALL (::pthread_create (thr_id, &attr,
03033                                 thread_args->entry_point (),
03034                                 thread_args),
03035               int, -1, result);
03036   ::pthread_attr_destroy (&attr);
03037 
03038 #     else /* this is draft 7 or std */
03039   ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_create (thr_id,
03040                                                   &attr,
03041                                                   thread_args->entry_point (),
03042                                                   thread_args),
03043                                 result),
03044               int, -1, result);
03045   ::pthread_attr_destroy (&attr);
03046 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
03047 
03048   // This is a SunOS or POSIX implementation of pthreads, where we
03049   // assume that ACE_thread_t and ACE_hthread_t are the same.  If this
03050   // *isn't* correct on some platform, please let us know.
03051   if (result != -1)
03052     *thr_handle = *thr_id;
03053 
03054 #     if defined (sun)  &&  defined (ACE_HAS_ONLY_SCHED_OTHER)
03055   // SunOS prior to 5.7:
03056 
03057   // If the priority is 0, then we might have to set it now because we
03058   // couldn't set it with ::pthread_attr_setschedparam, as noted
03059   // above.  This doesn't provide strictly correct behavior, because
03060   // the thread was created (above) with the priority of its parent.
03061   // (That applies regardless of the inherit_sched attribute: if it
03062   // was PTHREAD_INHERIT_SCHED, then it certainly inherited its
03063   // parent's priority.  If it was PTHREAD_EXPLICIT_SCHED, then "attr"
03064   // was initialized by the SunOS ::pthread_attr_init () to contain
03065   // NULL for the priority, which indicated to SunOS ::pthread_create
03066   // () to inherit the parent priority.)
03067   if (priority == 0)
03068     {
03069       // Check the priority of this thread, which is the parent
03070       // of the newly created thread.  If it is 0, then the
03071       // newly created thread will have inherited the priority
03072       // of 0, so there's no need to explicitly set it.
03073       struct sched_param sparam;
03074       int policy = 0;
03075       ACE_OSCALL (ACE_ADAPT_RETVAL (::pthread_getschedparam (thr_self (),
03076                                                              &policy,
03077                                                              &sparam),
03078                                     result), int,
03079                   -1, result);
03080 
03081       // The only policy supported by by SunOS, thru version 5.6,
03082       // is SCHED_OTHER, so that's hard-coded here.
03083       policy = ACE_SCHED_OTHER;
03084 
03085       if (sparam.sched_priority != 0)
03086         {
03087           ACE_OS::memset ((void *) &sparam, 0, sizeof sparam);
03088           // The memset to 0 sets the priority to 0, so we don't need
03089           // to explicitly set sparam.sched_priority.
03090 
03091           ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setschedparam (*thr_id,
03092                                                                         policy,
03093                                                                         &sparam),
03094                                                result),
03095                              int, -1);
03096         }
03097     }
03098 
03099 #       if defined (ACE_NEEDS_LWP_PRIO_SET)
03100 #         if 0
03101   // It would be useful if we could make this work.  But, it requires
03102   // a mechanism for determining the ID of an LWP to which another
03103   // thread is bound.  Is there a way to do that?  Instead, just rely
03104   // on the code in ACE_Thread_Adapter::invoke () to set the LWP
03105   // priority.
03106 
03107   // If the thread is bound, then set the priority on its LWP.
03108   if (ACE_BIT_ENABLED (flags, THR_BOUND))
03109     {
03110       ACE_Sched_Params sched_params (ACE_BIT_ENABLED (flags, THR_SCHED_FIFO) ||
03111                                      ACE_BIT_ENABLED (flags, THR_SCHED_RR)  ?
03112                                      ACE_SCHED_FIFO  :
03113                                      ACE_SCHED_OTHER,
03114                                      priority);
03115       result = ACE_OS::lwp_setparams (sched_params,
03116                                       /* ? How do we find the ID of the LWP
03117                                          to which *thr_id is bound? */);
03118     }
03119 #         endif /* 0 */
03120 #       endif /* ACE_NEEDS_LWP_PRIO_SET */
03121 
03122 #     endif /* sun && ACE_HAS_ONLY_SCHED_OTHER */
03123   return result;
03124 #   elif defined (ACE_HAS_STHREADS)
03125   int result;
03126   int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
03127 
03128   if (priority != ACE_DEFAULT_THREAD_PRIORITY)
03129     // If we need to set the priority, then we need to start the
03130     // thread in a suspended mode.
03131     ACE_SET_BITS (flags, THR_SUSPENDED);
03132 
03133   ACE_OSCALL (ACE_ADAPT_RETVAL (::thr_create (stack, stacksize,
03134                                               thread_args->entry_point (),
03135                                               thread_args,
03136                                               flags, thr_id), result),
03137               int, -1, result);
03138 
03139   if (result != -1)
03140     {
03141       // With SunOS threads, ACE_thread_t and ACE_hthread_t are the same.
03142       *thr_handle = *thr_id;
03143 
03144       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
03145         {
03146           // Set the priority of the new thread and then let it
03147           // continue, but only if the user didn't start it suspended
03148           // in the first place!
03149           if ((result = ACE_OS::thr_setprio (*thr_id, priority)) != 0)
03150             {
03151               errno = result;
03152               return -1;
03153             }
03154 
03155           if (start_suspended == 0)
03156             {
03157               if ((result = ACE_OS::thr_continue (*thr_id)) != 0)
03158                 {
03159                   errno = result;
03160                   return -1;
03161                 }
03162             }
03163         }
03164     }
03165   return result;
03166 #   elif defined (ACE_HAS_WTHREADS)
03167   ACE_UNUSED_ARG (stack);
03168 #     if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
03169   if (ACE_BIT_ENABLED (flags, THR_USE_AFX))
03170     {
03171       CWinThread *cwin_thread =
03172         ::AfxBeginThread ((AFX_THREADPROC) thread_args->entry_point (),
03173                           thread_args,
03174                           priority,
03175                           0,
03176                           flags | THR_SUSPENDED);
03177       // Have to duplicate the handle because
03178       // CWinThread::~CWinThread() closes the original handle.
03179 #       if !defined (ACE_HAS_WINCE)
03180       (void) ::DuplicateHandle (::GetCurrentProcess (),
03181                                 cwin_thread->m_hThread,
03182                                 ::GetCurrentProcess (),
03183                                 thr_handle,
03184                                 0,
03185                                 TRUE,
03186                                 DUPLICATE_SAME_ACCESS);
03187 #       endif /* ! ACE_HAS_WINCE */
03188       *thr_id = cwin_thread->m_nThreadID;
03189 
03190       if (ACE_BIT_ENABLED (flags, THR_SUSPENDED) == 0)
03191         cwin_thread->ResumeThread ();
03192       // cwin_thread will be deleted in AfxThreadExit()
03193       // Warning: If AfxThreadExit() is called from within the
03194       // thread, ACE_TSS_Cleanup->exit() never gets called !
03195     }
03196   else
03197 #     endif /* ACE_HAS_MFC */
03198     {
03199       int start_suspended = ACE_BIT_ENABLED (flags, THR_SUSPENDED);
03200 
03201       if (priority != ACE_DEFAULT_THREAD_PRIORITY)
03202         // If we need to set the priority, then we need to start the
03203         // thread in a suspended mode.
03204         ACE_SET_BITS (flags, THR_SUSPENDED);
03205 
03206       *thr_handle = (void *) ACE_BEGINTHREADEX (0,
03207                                                 ACE_static_cast
03208                                                    (u_int, stacksize),
03209                                                 thread_args->entry_point (),
03210                                                 thread_args,
03211                                                 flags,
03212                                                 thr_id);
03213 
03214       if (priority != ACE_DEFAULT_THREAD_PRIORITY && *thr_handle != 0)
03215         {
03216           // Set the priority of the new thread and then let it
03217           // continue, but only if the user didn't start it suspended
03218           // in the first place!
03219           ACE_OS::thr_setprio (*thr_handle, priority);
03220 
03221           if (start_suspended == 0)
03222             ACE_OS::thr_continue (*thr_handle);
03223         }
03224     }
03225 #     if 0
03226   *thr_handle = ::CreateThread
03227     (0,
03228      stacksize,
03229      LPTHREAD_START_ROUTINE (thread_args->entry_point ()),
03230      thread_args,
03231      flags,
03232      thr_id);
03233 #     endif /* 0 */
03234 
03235   // Close down the handle if no one wants to use it.
03236   if (thr_handle == &tmp_handle)
03237     ::CloseHandle (tmp_handle);
03238 
03239   if (*thr_handle != 0)
03240     return 0;
03241   else
03242     ACE_FAIL_RETURN (-1);
03243   /* NOTREACHED */
03244 
03245 #   elif defined (ACE_PSOS)
03246 
03247   // stack is created in the task's memory region 0
03248   ACE_UNUSED_ARG (stack);
03249 
03250   // task creation and start flags are fixed
03251   ACE_UNUSED_ARG (flags);
03252 
03253   // lowest priority is reserved for the IDLE pSOS+ system daemon,
03254   // highest are reserved for high priority pSOS+ system daemons
03255   if (priority < PSOS_TASK_MIN_PRIORITY)
03256     {
03257       priority = PSOS_TASK_MIN_PRIORITY;
03258     }
03259   else if (priority > PSOS_TASK_MAX_PRIORITY)
03260     {
03261       priority = PSOS_TASK_MAX_PRIORITY;
03262     }
03263 
03264   // set the stacksize to a default value if no size is specified
03265   if (stacksize == 0)
03266     stacksize = ACE_PSOS_DEFAULT_STACK_SIZE;
03267 
03268   ACE_hthread_t tid;
03269   *thr_handle = 0;
03270 
03271   // create the thread
03272   if (t_create ((char *) thr_id, // task name
03273                 priority,        // (possibly adjusted) task priority
03274                 stacksize,       // passed stack size is used for supervisor stack
03275                 0,               // no user stack: tasks run strictly in supervisor mode
03276                 T_LOCAL,         // local to the pSOS+ node (does not support pSOS+m)
03277                 &tid)            // receives task id
03278       != 0)
03279     {
03280       return -1;
03281     }
03282 
03283   // pSOS tasks are passed an array of 4 u_longs
03284   u_long targs[4];
03285   targs[0] = (u_long) ACE_THREAD_ARGUMENT;
03286   targs[1] = 0;
03287   targs[2] = 0;
03288   targs[3] = 0;
03289 
03290   // start the thread
03291   if (t_start (tid,
03292                T_PREEMPT |            // Task can be preempted
03293                //             T_NOTSLICE |           // Task is not timesliced with other tasks at same priority
03294                T_TSLICE |             // Task is timesliced with other tasks at same priority
03295                T_NOASR |              // Task level signals disabled
03296                T_SUPV |               // Task runs strictly in supervisor mode
03297                T_ISR,                 // Hardware interrupts are enabled
03298                ACE_THREAD_FUNCTION,   // Task entry point
03299                targs)                 // Task argument(s)
03300       != 0)
03301     {
03302       return -1;
03303     }
03304 
03305   // store the task id in the handle and return success
03306   *thr_handle = tid;
03307   return 0;
03308 
03309 #   elif defined (VXWORKS)
03310   // The hard-coded values below are what ::sp () would use.  (::sp ()
03311   // hardcodes priority to 100, flags to VX_FP_TASK, and stacksize to
03312   // 20,000.)  stacksize should be an even integer.  If a stack is not
03313   // specified, ::taskSpawn () is used so that we can set the
03314   // priority, flags, and stacksize.  If a stack is specified,
03315   // ::taskInit ()/::taskActivate() are used.
03316 
03317   // If called with thr_create() defaults, use same default values as ::sp ():
03318   if (priority == ACE_DEFAULT_THREAD_PRIORITY) priority = 100;
03319   // Assumes that there is a floating point coprocessor.  As noted
03320   // above, ::sp () hardcodes this, so we should be safe with it.
03321   if (flags == 0) flags = VX_FP_TASK;
03322   if (stacksize == 0) stacksize = 20000;
03323 
03324   const u_int thr_id_provided =
03325     thr_id  &&  *thr_id  &&  (*thr_id)[0] != ACE_THR_ID_ALLOCATED;
03326 
03327   ACE_hthread_t tid;
03328 #     if 0 /* Don't support setting of stack, because it doesn't seem to work. */
03329   if (stack == 0)
03330     {
03331 #     else
03332       ACE_UNUSED_ARG (stack);
03333 #     endif /* 0 */
03334       // The call below to ::taskSpawn () causes VxWorks to assign a
03335       // unique task name of the form: "t" + an integer, because the
03336       // first argument is 0.
03337       tid = ::taskSpawn (thr_id_provided  ?  *thr_id  :  0,
03338                          priority,
03339                          (int) flags,
03340                          (int) stacksize,
03341                          thread_args->entry_point (),
03342                          (int) thread_args,
03343                          0, 0, 0, 0, 0, 0, 0, 0, 0);
03344 #     if 0 /* Don't support setting of stack, because it doesn't seem to work. */
03345     }
03346   else
03347     {
03348       // If a task name (thr_id) was not supplied, then the task will
03349       // not have a unique name.  That's VxWorks' behavior.
03350 
03351       // Carve out a TCB at the beginning of the stack space.  The TCB
03352       // occupies 400 bytes with VxWorks 5.3.1/I386.
03353       WIND_TCB *tcb = (WIND_TCB *) stack;
03354 
03355       // The TID is defined to be the address of the TCB.
03356       int status = ::taskInit (tcb,
03357                                thr_id_provided  ?  *thr_id  :  0,
03358                                priority,
03359                                (int) flags,
03360                                (char *) stack + sizeof (WIND_TCB),
03361                                (int) (stacksize - sizeof (WIND_TCB)),
03362                                thread_args->entry_point (),
03363                                (int) thread_args,
03364                                0, 0, 0, 0, 0, 0, 0, 0, 0);
03365 
03366       if (status == OK)
03367         {
03368           // The task was successfully initialized, now activate it.
03369           status = ::taskActivate ((ACE_hthread_t) tcb);
03370         }
03371 
03372       tid = status == OK  ?  (ACE_hthread_t) tcb  :  ERROR;
03373     }
03374 #     endif /* 0 */
03375 
03376   if (tid == ERROR)
03377     return -1;
03378   else
03379     {
03380       if (! thr_id_provided  &&  thr_id)
03381         {
03382           if (*thr_id  &&  (*thr_id)[0] == ACE_THR_ID_ALLOCATED)
03383             // *thr_id was allocated by the Thread_Manager.  ::taskTcb
03384             // (int tid) returns the address of the WIND_TCB (task
03385             // control block).  According to the ::taskSpawn()
03386             // documentation, the name of the new task is stored at
03387             // pStackBase, but is that of the current task?  If so, it
03388             // might be a bit quicker than this extraction of the tcb
03389             // . . .
03390             ACE_OS::strsncpy (*thr_id + 1, ::taskTcb (tid)->name, 10);
03391           else
03392             // *thr_id was not allocated by the Thread_Manager.
03393             // Pass back the task name in the location pointed to
03394             // by thr_id.
03395             *thr_id = ::taskTcb (tid)->name;
03396         }
03397       // else if the thr_id was provided, there's no need to overwrite
03398       // it with the same value (string).  If thr_id is 0, then we can't
03399       // pass the task name back.
03400 
03401       if (thr_handle)
03402         *thr_handle = tid;
03403 
03404       return 0;
03405     }
03406 
03407 #   endif /* ACE_HAS_STHREADS */
03408 # else
03409   ACE_UNUSED_ARG (func);
03410   ACE_UNUSED_ARG (args);
03411   ACE_UNUSED_ARG (flags);
03412   ACE_UNUSED_ARG (thr_id);
03413   ACE_UNUSED_ARG (thr_handle);
03414   ACE_UNUSED_ARG (priority);
03415   ACE_UNUSED_ARG (stack);
03416   ACE_UNUSED_ARG (stacksize);
03417   ACE_NOTSUP_RETURN (-1);
03418 # endif /* ACE_HAS_THREADS */
03419 }
03420 
03421 void
03422 ACE_OS::thr_exit (ACE_THR_FUNC_RETURN status)
03423 {
03424   ACE_OS_TRACE ("ACE_OS::thr_exit");
03425 #if defined (ACE_HAS_THREADS)
03426 #   if defined (ACE_HAS_PTHREADS)
03427     ::pthread_exit (status);
03428 #   elif defined (ACE_HAS_STHREADS)
03429     ::thr_exit (status);
03430 #   elif defined (ACE_HAS_WTHREADS)
03431     // Can't call it here because on NT, the thread is exited
03432     // directly by ACE_Thread_Adapter::invoke ().
03433     //   ACE_TSS_Cleanup::instance ()->exit (status);
03434 
03435 #     if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
03436     int using_afx = -1;
03437     // An ACE_Thread_Descriptor really is an ACE_OS_Thread_Descriptor.
03438     // But without #including ace/Thread_Manager.h, we don't know that.
03439     ACE_OS_Thread_Descriptor *td =
03440       ACE_Base_Thread_Adapter::thr_desc_log_msg ();
03441     if (td)
03442       using_afx = ACE_BIT_ENABLED (td->flags (), THR_USE_AFX);
03443 #     endif /* ACE_HAS_MFC && (ACE_HAS_MFC != 0) */
03444 
03445     // Call TSS destructors.
03446     ACE_OS::cleanup_tss (0 /* not main thread */);
03447 
03448     // Exit the thread.
03449     // Allow CWinThread-destructor to be invoked from AfxEndThread.
03450     // _endthreadex will be called from AfxEndThread so don't exit the
03451     // thread now if we are running an MFC thread.
03452 #     if defined (ACE_HAS_MFC) && (ACE_HAS_MFC != 0)
03453     if (using_afx != -1)
03454       {
03455         if (using_afx)
03456           ::AfxEndThread (status);
03457         else
03458           ACE_ENDTHREADEX (status);
03459       }
03460     else
03461       {
03462         // Not spawned by ACE_Thread_Manager, use the old buggy
03463         // version.  You should seriously consider using
03464         // ACE_Thread_Manager to spawn threads.  The following code is
03465         // know to cause some problem.
03466         CWinThread *pThread = ::AfxGetThread ();
03467         if (!pThread || pThread->m_nThreadID != ACE_OS::thr_self ())
03468           ACE_ENDTHREADEX (status);
03469         else
03470           ::AfxEndThread (status);
03471       }
03472 #     else
03473     ACE_ENDTHREADEX (status);
03474 #     endif /* ACE_HAS_MFC && ACE_HAS_MFS != 0*/
03475 
03476 #   elif defined (VXWORKS)
03477     ACE_hthread_t tid;
03478     ACE_OS::thr_self (tid);
03479     *((int *) status) = ::taskDelete (tid);
03480 #   elif defined (ACE_PSOS)
03481     ACE_hthread_t tid;
03482     ACE_OS::thr_self (tid);
03483 
03484 #     if defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
03485     // Call TSS destructors.
03486     ACE_OS::cleanup_tss (0 /* not main thread */);
03487 #     endif /* ACE_PSOS && ACE_PSOS_HAS_TSS */
03488 
03489     *((u_long *) status) = ::t_delete (tid);
03490 #   endif /* ACE_HAS_PTHREADS */
03491 # else
03492   ACE_UNUSED_ARG (status);
03493 # endif /* ACE_HAS_THREADS */
03494 }
03495 
03496 int
03497 ACE_OS::lwp_getparams (ACE_Sched_Params &sched_params)
03498 {
03499 # if defined (ACE_HAS_STHREADS) || defined (sun)
03500   // Get the class TS and RT class IDs.
03501   ACE_id_t rt_id;
03502   ACE_id_t ts_id;
03503   if (ACE_OS::scheduling_class ("RT", rt_id) == -1
03504       || ACE_OS::scheduling_class ("TS", ts_id) == -1)
03505     return -1;
03506 
03507   // Get this LWP's scheduling parameters.
03508   pcparms_t pcparms;
03509   // The following is just to avoid Purify warnings about unitialized
03510   // memory reads.
03511   ACE_OS::memset (&pcparms, 0, sizeof pcparms);
03512   pcparms.pc_cid = PC_CLNULL;
03513 
03514   if (ACE_OS::priority_control (P_LWPID,
03515                                 P_MYID,
03516                                 PC_GETPARMS,
03517                                 (char *) &pcparms) == -1)
03518     return -1;
03519   else if (pcparms.pc_cid == rt_id)
03520     {
03521       // RT class.
03522       rtparms_t rtparms;
03523       ACE_OS::memcpy (&rtparms, pcparms.pc_clparms, sizeof rtparms);
03524 
03525       sched_params.policy (ACE_SCHED_FIFO);
03526       sched_params.priority (rtparms.rt_pri);
03527       sched_params.scope (ACE_SCOPE_THREAD);
03528       ACE_Time_Value quantum (rtparms.rt_tqsecs,
03529                               rtparms.rt_tqnsecs == RT_TQINF
03530                               ? 0 : rtparms.rt_tqnsecs * 1000);
03531       sched_params.quantum (quantum);
03532       return 0;
03533     }
03534   else if (pcparms.pc_cid == ts_id)
03535     {
03536       /* TS class */
03537       tsparms_t tsparms;
03538       ACE_OS::memcpy (&tsparms, pcparms.pc_clparms, sizeof tsparms);
03539 
03540       sched_params.policy (ACE_SCHED_OTHER);
03541       sched_params.priority (tsparms.ts_upri);
03542       sched_params.scope (ACE_SCOPE_THREAD);
03543       return 0;
03544     }
03545   else
03546     return -1;
03547 
03548 # else  /* ! ACE_HAS_STHREADS && ! sun */
03549   ACE_UNUSED_ARG (sched_params);
03550   ACE_NOTSUP_RETURN (-1);
03551 # endif /* ! ACE_HAS_STHREADS && ! sun */
03552 }
03553 
03554 int
03555 ACE_OS::lwp_setparams (const ACE_Sched_Params &sched_params)
03556 {
03557 # if defined (ACE_HAS_STHREADS) || defined (sun)
03558   ACE_Sched_Params lwp_params (sched_params);
03559   lwp_params.scope (ACE_SCOPE_LWP);
03560   return ACE_OS::sched_params (lwp_params);
03561 # else  /* ! ACE_HAS_STHREADS && ! sun */
03562   ACE_UNUSED_ARG (sched_params);
03563   ACE_NOTSUP_RETURN (-1);
03564 # endif /* ! ACE_HAS_STHREADS && ! sun */
03565 }
03566 
03567 # if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
03568 int
03569 ACE_OS::thr_setspecific (ACE_OS_thread_key_t key, void *data)
03570 {
03571   // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
03572 #   if defined (ACE_HAS_THREADS)
03573 #     if defined (ACE_HAS_PTHREADS)
03574 #       if defined (ACE_HAS_FSU_PTHREADS)
03575       // Call pthread_init() here to initialize threads package.  FSU
03576       // threads need an initialization before the first thread constructor.
03577       // This seems to be the one; however, a segmentation fault may
03578       // indicate that another pthread_init() is necessary, perhaps in
03579       // Synch.cpp or Synch_T.cpp.  FSU threads will not reinit if called
03580       // more than once, so another call to pthread_init will not adversely
03581       // affect existing threads.
03582       pthread_init ();
03583 #       endif /*  ACE_HAS_FSU_PTHREADS */
03584     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setspecific (key, data), ace_result_), int, -1);
03585 #     elif defined (ACE_HAS_STHREADS)
03586     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), ace_result_), int, -1);
03587 #     elif defined (ACE_HAS_WTHREADS)
03588     ::TlsSetValue (key, data);
03589     return 0;
03590 #     endif /* ACE_HAS_STHREADS */
03591 #   else
03592   ACE_UNUSED_ARG (key);
03593   ACE_UNUSED_ARG (data);
03594   ACE_NOTSUP_RETURN (-1);
03595 #   endif /* ACE_HAS_THREADS */
03596 }
03597 # endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */
03598 
03599 int
03600 ACE_OS::thr_setspecific (ACE_thread_key_t key, void *data)
03601 {
03602   // ACE_OS_TRACE ("ACE_OS::thr_setspecific");
03603 #if defined (ACE_HAS_THREADS)
03604 #   if defined (ACE_HAS_TSS_EMULATION)
03605     ACE_KEY_INDEX (key_index, key);
03606 
03607     if (key_index >= ACE_TSS_Emulation::total_keys ())
03608       {
03609         errno = EINVAL;
03610         data = 0;
03611         return -1;
03612       }
03613     else
03614       {
03615         ACE_TSS_Emulation::ts_object (key) = data;
03616         ACE_TSS_Cleanup::instance ()->key_used (key);
03617 
03618         return 0;
03619       }
03620 #   elif defined (ACE_HAS_PTHREADS)
03621 #     if defined (ACE_HAS_FSU_PTHREADS)
03622       // Call pthread_init() here to initialize threads package.  FSU
03623       // threads need an initialization before the first thread constructor.
03624       // This seems to be the one; however, a segmentation fault may
03625       // indicate that another pthread_init() is necessary, perhaps in
03626       // Synch.cpp or Synch_T.cpp.  FSU threads will not reinit if called
03627       // more than once, so another call to pthread_init will not adversely
03628       // affect existing threads.
03629       pthread_init ();
03630 #     endif /*  ACE_HAS_FSU_PTHREADS */
03631 
03632 #     if defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
03633     ACE_OSCALL_RETURN (::pthread_setspecific (key, data), int, -1);
03634 #     else
03635     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_setspecific (key, data),
03636                                          ace_result_),
03637                        int, -1);
03638 #     endif /* ACE_HAS_PTHREADS_DRAFT4, 6 */
03639 
03640 #   elif defined (ACE_HAS_STHREADS)
03641     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_setspecific (key, data), ace_result_), int, -1);
03642 #   elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
03643     ACE_hthread_t tid;
03644     ACE_OS::thr_self (tid);
03645     if (::tsd_setval (key, tid, data) != 0)
03646      return -1;
03647     ACE_TSS_Cleanup::instance ()->key_used (key);
03648     return 0;
03649 #   elif defined (ACE_HAS_WTHREADS)
03650     ::TlsSetValue (key, data);
03651     ACE_TSS_Cleanup::instance ()->key_used (key);
03652     return 0;
03653 #   else
03654     ACE_UNUSED_ARG (key);
03655     ACE_UNUSED_ARG (data);
03656     ACE_NOTSUP_RETURN (-1);
03657 #   endif /* ACE_HAS_STHREADS */
03658 # else
03659   ACE_UNUSED_ARG (key);
03660   ACE_UNUSED_ARG (data);
03661   ACE_NOTSUP_RETURN (-1);
03662 # endif /* ACE_HAS_THREADS */
03663 }
03664 
03665 int
03666 ACE_OS::thr_keyfree (ACE_thread_key_t key)
03667 {
03668   ACE_OS_TRACE ("ACE_OS::thr_keyfree");
03669 # if defined (ACE_HAS_THREADS)
03670 #   if defined (ACE_HAS_TSS_EMULATION)
03671     // Release the key in the TSS_Emulation administration
03672     ACE_TSS_Emulation::release_key (key);
03673     return ACE_TSS_Cleanup::instance ()->remove (key);
03674 #   elif defined (ACE_HAS_PTHREADS_DRAFT4) || defined (ACE_HAS_PTHREADS_DRAFT6)
03675     ACE_UNUSED_ARG (key);
03676     ACE_NOTSUP_RETURN (-1);
03677 #   elif defined (ACE_HAS_PTHREADS)
03678     return ::pthread_key_delete (key);
03679 #   elif defined (ACE_HAS_THR_KEYDELETE)
03680     return ::thr_keydelete (key);
03681 #   elif defined (ACE_HAS_STHREADS)
03682     ACE_UNUSED_ARG (key);
03683     ACE_NOTSUP_RETURN (-1);
03684 #   elif defined (ACE_HAS_WTHREADS)
03685     // Extract out the thread-specific table instance and free up
03686     // the key and destructor.
03687     ACE_TSS_Cleanup::instance ()->remove (key);
03688     ACE_WIN32CALL_RETURN (ACE_ADAPT_RETVAL (::TlsFree (key), ace_result_), int, -1);
03689 #   elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
03690     // Extract out the thread-specific table instance and free up
03691     // the key and destructor.
03692     ACE_TSS_Cleanup::instance ()->remove (key);
03693     return (::tsd_delete (key) == 0) ? 0 : -1;
03694 #   else
03695     ACE_UNUSED_ARG (key);
03696     ACE_NOTSUP_RETURN (-1);
03697 #   endif /* ACE_HAS_TSS_EMULATION */
03698 # else
03699   ACE_UNUSED_ARG (key);
03700   ACE_NOTSUP_RETURN (-1);
03701 # endif /* ACE_HAS_THREADS */
03702 }
03703 
03704 # if defined (ACE_HAS_TSS_EMULATION) && defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
03705 int
03706 ACE_OS::thr_keycreate (ACE_OS_thread_key_t *key,
03707 #   if defined (ACE_HAS_THR_C_DEST)
03708                        ACE_THR_C_DEST dest,
03709 #   else
03710                        ACE_THR_DEST dest,
03711 #   endif /* ACE_HAS_THR_C_DEST */
03712                        void *inst)
03713 {
03714   // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
03715 #   if defined (ACE_HAS_THREADS)
03716 #     if defined (ACE_HAS_PTHREADS)
03717     ACE_UNUSED_ARG (inst);
03718 
03719 
03720 #       if defined (ACE_HAS_PTHREADS_DRAFT4)
03721 #         if defined (ACE_HAS_STDARG_THR_DEST)
03722     ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1);
03723 #         else  /* ! ACE_HAS_STDARG_THR_DEST */
03724     ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1);
03725 #         endif /* ! ACE_HAS_STDARG_THR_DEST */
03726 #       elif defined (ACE_HAS_PTHREADS_DRAFT6)
03727     ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1);
03728 #       else
03729     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
03730                                          ace_result_),
03731                        int, -1);
03732 #       endif /* ACE_HAS_PTHREADS_DRAFT4 */
03733 #     elif defined (ACE_HAS_STHREADS)
03734     ACE_UNUSED_ARG (inst);
03735     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
03736                                          ace_result_),
03737                        int, -1);
03738 #     elif defined (ACE_HAS_WTHREADS)
03739     *key = ::TlsAlloc ();
03740 
03741     if (*key != ACE_SYSCALL_FAILED)
03742       {
03743         // Extract out the thread-specific table instance and stash away
03744         // the key and destructor so that we can free it up later on...
03745         return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst);
03746       }
03747     else
03748       ACE_FAIL_RETURN (-1);
03749       /* NOTREACHED */
03750 #     endif /* ACE_HAS_STHREADS */
03751 #   else
03752   ACE_UNUSED_ARG (key);
03753   ACE_UNUSED_ARG (dest);
03754   ACE_UNUSED_ARG (inst);
03755   ACE_NOTSUP_RETURN (-1);
03756 #   endif /* ACE_HAS_THREADS */
03757 }
03758 # endif /* ACE_HAS_TSS_EMULATION && ACE_HAS_THREAD_SPECIFIC_STORAGE */
03759 
03760 int
03761 ACE_OS::thr_keycreate (ACE_thread_key_t *key,
03762 # if defined (ACE_HAS_THR_C_DEST)
03763                        ACE_THR_C_DEST dest,
03764 # else
03765                        ACE_THR_DEST dest,
03766 # endif /* ACE_HAS_THR_C_DEST */
03767                        void *inst)
03768 {
03769   // ACE_OS_TRACE ("ACE_OS::thr_keycreate");
03770 #if defined (ACE_HAS_THREADS)
03771 #   if defined (ACE_HAS_TSS_EMULATION)
03772     if (ACE_TSS_Emulation::next_key (*key) == 0)
03773       {
03774         ACE_TSS_Emulation::tss_destructor (*key, dest);
03775 
03776         // Extract out the thread-specific table instance and stash away
03777         // the key and destructor so that we can free it up later on...
03778         return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst);
03779       }
03780     else
03781       {
03782         errno = EAGAIN;
03783         return -1;
03784       }
03785 #   elif defined (ACE_HAS_PTHREADS)
03786     ACE_UNUSED_ARG (inst);
03787 
03788 #     if defined (ACE_HAS_PTHREADS_DRAFT4)
03789 #       if defined (ACE_HAS_STDARG_THR_DEST)
03790     ACE_OSCALL_RETURN (::pthread_keycreate (key, (void (*)(...)) dest), int, -1);
03791 #       else  /* ! ACE_HAS_STDARG_THR_DEST */
03792     ACE_OSCALL_RETURN (::pthread_keycreate (key, dest), int, -1);
03793 #       endif /* ! ACE_HAS_STDARG_THR_DEST */
03794 #     elif defined (ACE_HAS_PTHREADS_DRAFT6)
03795     ACE_OSCALL_RETURN (::pthread_key_create (key, dest), int, -1);
03796 #     else
03797     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::pthread_key_create (key, dest),
03798                                          ace_result_),
03799                        int, -1);
03800 #     endif /* ACE_HAS_PTHREADS_DRAFT4 */
03801 
03802 #   elif defined (ACE_HAS_STHREADS)
03803     ACE_UNUSED_ARG (inst);
03804     ACE_OSCALL_RETURN (ACE_ADAPT_RETVAL (::thr_keycreate (key, dest),
03805                                          ace_result_),
03806                        int, -1);
03807 #     elif defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS)
03808 
03809     static u_long unique_name = 0;
03810     void *tsdanchor;
03811 
03812     ++unique_name;
03813     if (::tsd_create (ACE_reinterpret_cast (char *, &unique_name),
03814                       0,
03815                       TSD_NOALLOC,
03816                       (void ****) &tsdanchor,
03817                       key) != 0)
03818       {
03819         return -1;
03820       }
03821 
03822     return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst);
03823 #   elif defined (ACE_HAS_WTHREADS)
03824     *key = ::TlsAlloc ();
03825 
03826     if (*key != ACE_SYSCALL_FAILED)
03827       {
03828         // Extract out the thread-specific table instance and stash away
03829         // the key and destructor so that we can free it up later on...
03830         return ACE_TSS_Cleanup::instance ()->insert (*key, dest, inst);
03831       }
03832     else
03833       ACE_FAIL_RETURN (-1);
03834       /* NOTREACHED */
03835 #   else
03836     ACE_UNUSED_ARG (key);
03837     ACE_UNUSED_ARG (dest);
03838     ACE_UNUSED_ARG (inst);
03839     ACE_NOTSUP_RETURN (-1);
03840 #   endif /* ACE_HAS_TSS_EMULATION */
03841 # else
03842   ACE_UNUSED_ARG (key);
03843   ACE_UNUSED_ARG (dest);
03844   ACE_UNUSED_ARG (inst);
03845   ACE_NOTSUP_RETURN (-1);
03846 # endif /* ACE_HAS_THREADS */
03847 }
03848 
03849 int
03850 ACE_OS::thr_key_used (ACE_thread_key_t key)
03851 {
03852 # if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
03853   ACE_TSS_Cleanup::instance ()->key_used (key);
03854   return 0;
03855 # else
03856   ACE_UNUSED_ARG (key);
03857   ACE_NOTSUP_RETURN (-1);
03858 # endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION || ACE_PSOS_HAS_TSS */
03859 }
03860 
03861 int
03862 ACE_OS::thr_key_detach (void *inst)
03863 {
03864 # if defined (ACE_WIN32) || defined (ACE_HAS_TSS_EMULATION) || (defined (ACE_PSOS) && defined (ACE_PSOS_HAS_TSS))
03865   if (ACE_TSS_Cleanup::lockable ())
03866     return ACE_TSS_Cleanup::instance()->detach (inst);
03867   else
03868     // We're in static constructor/destructor phase.  Don't
03869     // try to use the ACE_TSS_Cleanup instance because its lock
03870     // might not have been constructed yet, or might have been
03871     // destroyed already.  Just leak the key . . .
03872     return -1;
03873 # else
03874   ACE_UNUSED_ARG (inst);
03875   ACE_NOTSUP_RETURN (-1);
03876 # endif /* ACE_WIN32 || ACE_HAS_TSS_EMULATION */
03877 }
03878 
03879 void
03880 ACE_OS::unique_name (const void *object,
03881                      ACE_TCHAR *name,
03882                      size_t length)
03883 {
03884   // The process ID will provide uniqueness between processes on the
03885   // same machine. The "this" pointer of the <object> will provide
03886   // uniqueness between other "live" objects in the same process. The
03887   // uniqueness of this name is therefore only valid for the life of
03888   // <object>.
03889   ACE_TCHAR temp_name[ACE_UNIQUE_NAME_LEN];
03890   ACE_OS::sprintf (temp_name,
03891                    ACE_LIB_TEXT ("%p%d"),
03892                    object,
03893                    ACE_static_cast (int, ACE_OS::getpid ()));
03894   ACE_OS::strsncpy (name,
03895                     temp_name,
03896                     length);
03897 }
03898 
03899 int
03900 ACE_OS::argv_to_string (ACE_TCHAR **argv,
03901                         ACE_TCHAR *&buf,
03902                         int substitute_env_args)
03903 {
03904   if (argv == 0 || argv[0] == 0)
03905     return 0;
03906 
03907   size_t buf_len = 0;
03908 
03909   // Determine the length of the buffer.
03910 
03911   for (int i = 0; argv[i] != 0; i++)
03912     {
03913       ACE_TCHAR *temp = 0;
03914 
03915 #if !defined (ACE_LACKS_ENV)
03916       // Account for environment variables.
03917       if (substitute_env_args
03918           && (argv[i][0] == '$'
03919               && (temp = ACE_OS::getenv (&argv[i][1])) != 0))
03920         buf_len += ACE_OS_String::strlen (temp);
03921       else
03922 #endif /* ACE_LACKS_ENV */
03923         buf_len += ACE_OS_String::strlen (argv[i]);
03924 
03925       // Add one for the extra space between each string.
03926       buf_len++;
03927     }
03928 
03929   // Step through all argv params and copy each one into buf; separate
03930   // each param with white space.
03931 
03932   ACE_NEW_RETURN (buf,
03933                   ACE_TCHAR[buf_len + 1],
03934                   0);
03935 
03936   // Initial null charater to make it a null string.
03937   buf[0] = '\0';
03938   ACE_TCHAR *end = buf;
03939   int j;
03940 
03941   for (j = 0; argv[j] != 0; j++)
03942     {
03943       ACE_TCHAR *temp = 0;
03944 
03945 # if !defined (ACE_LACKS_ENV)
03946       // Account for environment variables.
03947       if (substitute_env_args
03948       && (argv[j][0] == '$'
03949               && (temp = ACE_OS::getenv (&argv[j][1])) != 0))
03950         end = ACE_OS::strecpy (end, temp);
03951       else
03952 #endif /* ACE_LACKS_ENV */
03953         end = ACE_OS::strecpy (end, argv[j]);
03954 
03955       // Replace the null char that strecpy put there with white
03956       // space.
03957       end[-1] = ' ';
03958     }
03959 
03960   // Null terminate the string.
03961   *end = '\0';
03962   // The number of arguments.
03963   return j;
03964 }
03965 
03966 int
03967 ACE_OS::string_to_argv (ACE_TCHAR *buf,
03968                         int &argc,
03969                         ACE_TCHAR **&argv,
03970                         int substitute_env_args)
03971 {
03972   // Reset the number of arguments
03973   argc = 0;
03974 
03975   if (buf == 0)
03976     return -1;
03977 
03978   ACE_TCHAR *cp = buf;
03979 
03980   // First pass: count arguments.
03981 
03982   // '#' is the start-comment token..
03983   while (*cp != '\0' && *cp != '#')
03984     {
03985       // Skip whitespace..
03986       while (ACE_OS::ace_isspace (*cp))
03987         cp++;
03988 
03989       // Increment count and move to next whitespace..
03990       if (*cp != '\0')
03991         argc++;
03992 
03993       while (*cp != '\0' && !ACE_OS::ace_isspace (*cp))
03994         {
03995           // Grok quotes....
03996           if (*cp == '\'' || *cp == '"')
03997             {
03998               ACE_TCHAR quote = *cp;
03999 
04000               // Scan past the string..
04001               for (cp++; *cp != '\0' && *cp != quote; cp++)
04002                 continue;
04003 
04004               // '\0' implies unmatched quote..
04005               if (*cp == '\0')
04006                 {
04007                   argc--;
04008                   break;
04009                 }
04010               else
04011                 cp++;
04012             }
04013           else
04014             cp++;
04015         }
04016     }
04017 
04018   // Second pass: copy arguments.
04019   ACE_TCHAR arg[ACE_DEFAULT_ARGV_BUFSIZ];
04020   ACE_TCHAR *argp = arg;
04021 
04022   // Make sure that the buffer we're copying into is always large
04023   // enough.
04024   if (cp - buf >= ACE_DEFAULT_ARGV_BUFSIZ)
04025     ACE_NEW_RETURN (argp,
04026                     ACE_TCHAR[cp - buf + 1],
04027                     -1);
04028 
04029   // Make a new argv vector of argc + 1 elements.
04030   ACE_NEW_RETURN (argv,
04031                   ACE_TCHAR *[argc + 1],
04032                   -1);
04033 
04034   ACE_TCHAR *ptr = buf;
04035 
04036   for (int i = 0; i < argc; i++)
04037     {
04038       // Skip whitespace..
04039       while (ACE_OS::ace_isspace (*ptr))
04040         ptr++;
04041 
04042       // Copy next argument and move to next whitespace..
04043       cp = argp;
04044       while (*ptr != '\0' && !ACE_OS::ace_isspace (*ptr))
04045         if (*ptr == '\'' || *ptr == '"')
04046           {
04047             ACE_TCHAR quote = *ptr++;
04048 
04049             while (*ptr != '\0' && *ptr != quote)
04050               *cp++ = *ptr++;
04051 
04052             if (*ptr == quote)
04053               ptr++;
04054           }
04055         else
04056           *cp++ = *ptr++;
04057 
04058       *cp = '\0';
04059 
04060 #if !defined (ACE_LACKS_ENV)
04061       // Check for environment variable substitution here.
04062       if (substitute_env_args) {
04063           argv[i] = ACE_OS::strenvdup(argp);
04064 
04065           if (argv[i] == 0)
04066             {
04067               if (argp != arg)
04068                 delete [] argp;
04069               errno = ENOMEM;
04070               return -1;
04071             }
04072       }
04073       else
04074 #endif /* ACE_LACKS_ENV */
04075         {
04076           argv[i] = ACE_OS::strdup(argp);
04077 
04078           if (argv[i] == 0)
04079             {
04080               if (argp != arg)
04081                 delete [] argp;
04082               errno = ENOMEM;
04083               return -1;
04084             }
04085       }
04086   }
04087 
04088   if (argp != arg)
04089     delete [] argp;
04090 
04091   argv[argc] = 0;
04092   return 0;
04093 }
04094 
04095 // Create a contiguous command-line argument buffer with each arg
04096 // separated by spaces.
04097 
04098 pid_t
04099 ACE_OS::fork_exec (ACE_TCHAR *argv[])
04100 {
04101 # if defined (ACE_WIN32)
04102   ACE_TCHAR *buf;
04103 
04104   if (ACE_OS::argv_to_string (argv, buf) != -1)
04105     {
04106       PROCESS_INFORMATION process_info;
04107 #   if !defined (ACE_HAS_WINCE)
04108       ACE_TEXT_STARTUPINFO startup_info;
04109       ACE_OS::memset ((void *) &startup_info,
04110                       0,
04111                       sizeof startup_info);
04112       startup_info.cb = sizeof startup_info;
04113 
04114       if (ACE_TEXT_CreateProcess (0,
04115                                   buf,
04116                                   0, // No process attributes.
04117                                   0,  // No thread attributes.
04118                                   TRUE, // Allow handle inheritance.
04119                                   0, // Don't create a new console window.
04120                                   0, // No environment.
04121                                   0, // No current directory.
04122                                   &startup_info,
04123                                   &process_info))
04124 #   else
04125       if (ACE_TEXT_CreateProcess (0,
04126                                   buf,
04127                                   0, // No process attributes.
04128                                   0,  // No thread attributes.
04129                                   FALSE, // Can's inherit handles on CE
04130                                   0, // Don't create a new console window.
04131                                   0, // No environment.
04132                                   0, // No current directory.
04133                                   0, // Can't use startup info on CE
04134                                   &process_info))
04135 #   endif /* ! ACE_HAS_WINCE */
04136         {
04137           // Free resources allocated in kernel.
04138           ACE_OS::close (process_info.hThread);
04139           ACE_OS::close (process_info.hProcess);
04140           // Return new process id.
04141           delete [] buf;
04142           return process_info.dwProcessId;
04143         }
04144     }
04145 
04146   // CreateProcess failed.
04147   return -1;
04148 # elif defined (CHORUS)
04149   return ACE_OS::execv (argv[0], argv);
04150 # else
04151       pid_t result = ACE_OS::fork ();
04152 
04153       switch (result)
04154         {
04155         case -1:
04156           // Error.
04157           return -1;
04158         case 0:
04159           // Child process.
04160           if (ACE_OS::execv (argv[0], argv) == -1)
04161             {
04162               // The OS layer should not print stuff out
04163               // ACE_ERROR ((LM_ERROR,
04164               //             "%p Exec failed\n"));
04165 
04166               // If the execv fails, this child needs to exit.
04167               ACE_OS::exit (errno);
04168             }
04169         default:
04170           // Server process.  The fork succeeded.
04171           return result;
04172         }
04173 # endif /* ACE_WIN32 */
04174 }
04175 
04176 ssize_t
04177 ACE_OS::read_n (ACE_HANDLE handle,
04178                 void *buf,
04179                 size_t len,
04180                 size_t *bt)
04181 {
04182   size_t temp;
04183   size_t &bytes_transferred = bt == 0 ? temp : *bt;
04184   ssize_t n;
04185 
04186   for (bytes_transferred = 0;
04187        bytes_transferred < len;
04188        bytes_transferred += n)
04189     {
04190       n = ACE_OS::read (handle,
04191                         (char *) buf + bytes_transferred,
04192                         len - bytes_transferred);
04193 
04194       if (n == -1 || n == 0)
04195         return n;
04196     }
04197 
04198   return bytes_transferred;
04199 }
04200 
04201 // Write <len> bytes from <buf> to <handle> (uses the <write>
04202 // system call on UNIX and the <WriteFile> call on Win32).
04203 
04204 ssize_t
04205 ACE_OS::write_n (ACE_HANDLE handle,
04206                  const void *buf,
04207                  size_t len,
04208                 size_t *bt)
04209 {
04210   size_t temp;
04211   size_t &bytes_transferred = bt == 0 ? temp : *bt;
04212   ssize_t n;
04213 
04214   for (bytes_transferred = 0;
04215        bytes_transferred < len;
04216        bytes_transferred += n)
04217     {
04218       n = ACE_OS::write (handle,
04219                          (char *) buf + bytes_transferred,
04220                          len - bytes_transferred);
04221 
04222       if (n == -1 || n == 0)
04223         return n;
04224     }
04225 
04226   return bytes_transferred;
04227 }
04228 
04229 # if defined (ACE_LACKS_WRITEV)
04230 
04231 // "Fake" writev for operating systems without it.  Note that this is
04232 // thread-safe.
04233 
04234 int
04235 ACE_OS::writev_emulation (ACE_HANDLE handle, ACE_WRITEV_TYPE iov[], int n)
04236 {
04237   ACE_OS_TRACE ("ACE_OS::writev_emulation");
04238 
04239   size_t length = 0;
04240   int i;
04241 
04242   // Determine the total length of all the buffers in <iov>.
04243   for (i = 0; i < n; i++)
04244     if (ACE_static_cast (int, iov[i].iov_len) < 0)
04245       return -1;
04246     else
04247       length += iov[i].iov_len;
04248 
04249   char *buf;
04250 
04251 #   if defined (ACE_HAS_ALLOCA)
04252   buf = (char *) alloca (length);
04253 #   else
04254   ACE_NEW_RETURN (buf,
04255                   char[length],
04256                   -1);
04257 #   endif /* !defined (ACE_HAS_ALLOCA) */
04258 
04259   char *ptr = buf;
04260 
04261   for (i = 0; i < n; i++)
04262     {
04263       ACE_OS::memcpy (ptr, iov[i].iov_base, iov[i].iov_len);
04264       ptr += iov[i].iov_len;
04265     }
04266 
04267   ssize_t result = ACE_OS::write (handle, buf, length);
04268 #   if !defined (ACE_HAS_ALLOCA)
04269   delete [] buf;
04270 #   endif /* !defined (ACE_HAS_ALLOCA) */
04271   return result;
04272 }
04273 # endif /* ACE_LACKS_WRITEV */
04274 
04275 # if defined (ACE_LACKS_READV)
04276 
04277 // "Fake" readv for operating systems without it.  Note that this is
04278 // thread-safe.
04279 
04280 ssize_t
04281 ACE_OS::readv_emulation (ACE_HANDLE handle,
04282                          ACE_READV_TYPE *iov,
04283                          int n)
04284 {
04285   ACE_OS_TRACE ("ACE_OS::readv_emulation");
04286 
04287   ssize_t length = 0;
04288   int i;
04289 
04290   for (i = 0; i < n; i++)
04291     if (ACE_static_cast (int, iov[i].iov_len) < 0)
04292       return -1;
04293     else
04294       length += iov[i].iov_len;
04295 
04296   char *buf;
04297 #   if defined (ACE_HAS_ALLOCA)
04298   buf = (char *) alloca (length);
04299 #   else
04300   ACE_NEW_RETURN (buf,
04301                   char[length],
04302                   -1);
04303 #   endif /* !defined (ACE_HAS_ALLOCA) */
04304 
04305   length = ACE_OS::read (handle, buf, length);
04306 
04307   if (length != -1)
04308     {
04309       char *ptr = buf;
04310       ssize_t copyn = length;
04311 
04312       for (i = 0;
04313            i < n && copyn > 0;
04314            i++)
04315         {
04316           ACE_OS::memcpy (iov[i].iov_base, ptr,
04317                           // iov_len is int on some platforms, size_t on others
04318                           copyn > (int) iov[i].iov_len
04319                             ? (size_t) iov[i].iov_len
04320                             : (size_t) copyn);
04321           ptr += iov[i].iov_len;
04322           copyn -= iov[i].iov_len;
04323         }
04324     }
04325 
04326 #   if !defined (ACE_HAS_ALLOCA)
04327   delete [] buf;
04328 #   endif /* !defined (ACE_HAS_ALLOCA) */
04329   return length;
04330 }
04331 # endif /* ACE_LACKS_READV */
04332 
04333 # if defined (ACE_NEEDS_FTRUNCATE)
04334 extern "C" int
04335 ftruncate (ACE_HANDLE handle, long len)
04336 {
04337   struct flock fl;
04338   fl.l_whence = 0;
04339   fl.l_len = 0;
04340   fl.l_start = len;
04341   fl.l_type = F_WRLCK;
04342 
04343   return ACE_OS::fcntl (handle, F_FREESP, ACE_reinterpret_cast (long, &fl));
04344 }
04345 # endif /* ACE_NEEDS_FTRUNCATE */
04346 
04347 # if defined (ACE_LACKS_MKTEMP)
04348 ACE_TCHAR *
04349 ACE_OS::mktemp (ACE_TCHAR *s)
04350 {
04351   ACE_OS_TRACE ("ACE_OS::mktemp");
04352   if (s == 0)
04353     // check for null template string failed!
04354     return 0;
04355   else
04356     {
04357       ACE_TCHAR *xxxxxx = ACE_OS::strstr (s, ACE_LIB_TEXT ("XXXXXX"));
04358 
04359       if (xxxxxx == 0)
04360         // the template string doesn't contain "XXXXXX"!
04361         return s;
04362       else
04363         {
04364           ACE_TCHAR unique_letter = ACE_LIB_TEXT ('a');
04365           ACE_stat sb;
04366 
04367           // Find an unused filename for this process.  It is assumed
04368           // that the user will open the file immediately after
04369           // getting this filename back (so, yes, there is a race
04370           // condition if multiple threads in a process use the same
04371           // template).  This appears to match the behavior of the
04372           // SunOS 5.5 mktemp().
04373           ACE_OS::sprintf (xxxxxx,
04374                            ACE_LIB_TEXT ("%05d%c"),
04375                            ACE_OS::getpid (),
04376                            unique_letter);
04377           while (ACE_OS::stat (s, &sb) >= 0)
04378             {
04379               if (++unique_letter <= ACE_LIB_TEXT ('z'))
04380                 ACE_OS::sprintf (xxxxxx,
04381                                  ACE_LIB_TEXT ("%05d%c"),
04382                                  ACE_OS::getpid (),
04383                                  unique_letter);
04384               else
04385                 {
04386                   // maximum of 26 unique files per template, per process
04387                   ACE_OS::sprintf (xxxxxx, ACE_LIB_TEXT ("%s"), ACE_LIB_TEXT (""));
04388                   return s;
04389                 }
04390             }
04391         }
04392       return s;
04393     }
04394 }
04395 # endif /* ACE_LACKS_MKTEMP */
04396 
04397 int
04398 ACE_OS::socket_init (int version_high, int version_low)
04399 {
04400 # if defined (ACE_WIN32)
04401   if (ACE_OS::socket_initialized_ == 0)
04402     {
04403       WORD version_requested = MAKEWORD (version_high, version_low);
04404       WSADATA wsa_data;
04405       int error = WSAStartup (version_requested, &wsa_data);
04406 
04407       if (error != 0)
04408 #   if defined (ACE_HAS_WINCE)
04409         {
04410           wchar_t fmt[] = ACE_LIB_TEXT ("%s failed, WSAGetLastError returned %d");
04411           wchar_t buf[80];  // @@ Eliminate magic number.
04412           ACE_OS::sprintf (buf, fmt, ACE_LIB_TEXT ("WSAStartup"), error);
04413           ::MessageBox (0, buf, ACE_LIB_TEXT ("WSAStartup failed!"), MB_OK);
04414         }
04415 #   else
04416       ACE_OS::fprintf (stderr,
04417                        "ACE_OS::socket_init; WSAStartup failed, "
04418                          "WSAGetLastError returned %d\n",
04419                        error);
04420 #   endif /* ACE_HAS_WINCE */
04421 
04422       ACE_OS::socket_initialized_ = 1;
04423     }
04424 # else
04425   ACE_UNUSED_ARG (version_high);
04426   ACE_UNUSED_ARG (version_low);
04427 # endif /* ACE_WIN32 */
04428   return 0;
04429 }
04430 
04431 int
04432 ACE_OS::socket_fini (void)
04433 {
04434 # if defined (ACE_WIN32)
04435   if (ACE_OS::socket_initialized_ != 0)
04436     {
04437       if (WSACleanup () != 0)
04438         {
04439           int error = ::WSAGetLastError ();
04440 #   if defined (ACE_HAS_WINCE)
04441           wchar_t fmt[] = ACE_LIB_TEXT ("%s failed, WSAGetLastError returned %d");
04442           wchar_t buf[80];  // @@ Eliminate magic number.
04443           ACE_OS::sprintf (buf, fmt, ACE_LIB_TEXT ("WSACleanup"), error);
04444           ::MessageBox (0, buf , ACE_LIB_TEXT ("WSACleanup failed!"), MB_OK);
04445 #   else
04446           ACE_OS::fprintf (stderr,
04447                            "ACE_OS::socket_fini; WSACleanup failed, "
04448                              "WSAGetLastError returned %d\n",
04449                            error);
04450 #   endif /* ACE_HAS_WINCE */
04451         }
04452       ACE_OS::socket_initialized_ = 0;
04453     }
04454 # endif /* ACE_WIN32 */
04455   return 0;
04456 }
04457 
04458 # if defined (ACE_LACKS_SYS_NERR)
04459 # if defined (__rtems__)
04460 int sys_nerr = EWOULDBLOCK + 1;  // definitely a hack.
04461 # else
04462  int sys_nerr = ERRMAX + 1;
04463 # endif /* __rtems__ */
04464 # endif /* ACE_LACKS_SYS_NERR */
04465 
04466 # if defined (VXWORKS)
04467 #   include /**/ <usrLib.h>   /* for ::sp() */
04468 
04469 // This global function can be used from the VxWorks shell to pass
04470 // arguments to a C main () function.
04471 //
04472 // usage: -> spa main, "arg1", "arg2"
04473 //
04474 // All arguments must be quoted, even numbers.
04475 int
04476 spa (FUNCPTR entry, ...)
04477 {
04478   static const unsigned int MAX_ARGS = 10;
04479   static char *argv[MAX_ARGS];
04480   va_list pvar;
04481   unsigned int argc;
04482 
04483   // Hardcode a program name because the real one isn't available
04484   // through the VxWorks shell.
04485   argv[0] = "ace_main";
04486 
04487   // Peel off arguments to spa () and put into argv.  va_arg () isn't
04488   // necessarily supposed to return 0 when done, though since the
04489   // VxWorks shell uses a fixed number (10) of arguments, it might 0
04490   // the unused ones.  This function could be used to increase that
04491   // limit, but then it couldn't depend on the trailing 0.  So, the
04492   // number of arguments would have to be passed.
04493   va_start (pvar, entry);
04494 
04495   for (argc = 1; argc <= MAX_ARGS; ++argc)
04496     {
04497       argv[argc] = va_arg (pvar, char *);
04498 
04499       if (argv[argc] == 0)
04500         break;
04501     }
04502 
04503   if (argc > MAX_ARGS  &&  argv[argc-1] != 0)
04504     {
04505       // try to read another arg, and warn user if the limit was exceeded
04506       if (va_arg (pvar, char *) != 0)
04507         ACE_OS::fprintf (stderr, "spa(): number of arguments limited to %d\n",
04508                          MAX_ARGS);
04509     }
04510   else
04511     {
04512       // fill unused argv slots with 0 to get rid of leftovers
04513       // from previous invocations
04514       for (unsigned int i = argc; i <= MAX_ARGS; ++i)
04515         argv[i] = 0;
04516     }
04517 
04518   // The hard-coded options are what ::sp () uses, except for the
04519   // larger stack size (instead of ::sp ()'s 20000).
04520   const int ret = ::taskSpawn (argv[0],    // task name
04521                                100,        // task priority
04522                                VX_FP_TASK, // task options
04523                                ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
04524                                entry,      // entry point
04525                                argc,       // first argument to main ()
04526                                (int) argv, // second argument to main ()
04527                                0, 0, 0, 0, 0, 0, 0, 0);
04528   va_end (pvar);
04529 
04530   // ::taskSpawn () returns the taskID on success: return 0 instead if
04531   // successful
04532   return ret > 0 ? 0 : ret;
04533 }
04534 
04535 
04536 
04537 // A helper function for the extended spa functions
04538 static void
04539 add_to_argv (int& argc, char** argv, int max_args, char* string)
04540 {
04541   char indouble   = 0;
04542   size_t previous = 0;
04543   size_t length   = ACE_OS_String::strlen (string);
04544 
04545   // We use <= to make sure that we get the last argument
04546   for (size_t i = 0; i <= length; i++)
04547     {
04548       // Is it a double quote that hasn't been escaped?
04549       if (string[i] == '\"' && (i == 0 || string[i - 1] != '\\'))
04550         {
04551           indouble ^= 1;
04552           if (indouble)
04553             {
04554               // We have just entered a double quoted string, so
04555               // save the starting position of the contents.
04556               previous = i + 1;
04557             }
04558           else
04559             {
04560               // We have just left a double quoted string, so
04561               // zero out the ending double quote.
04562               string[i] = '\0';
04563             }
04564         }
04565       else if (string[i] == '\\')  // Escape the next character
04566         {
04567           // The next character is automatically
04568           // skipped because of the strcpy
04569           ACE_OS_String::strcpy (string + i, string + i + 1);
04570           length--;
04571         }
04572       else if (!indouble &&
04573                (ACE_OS::ace_isspace (string[i]) || string[i] == '\0'))
04574         {
04575           string[i] = '\0';
04576           if (argc < max_args)
04577             {
04578               argv[argc] = string + previous;
04579               argc++;
04580             }
04581           else
04582             {
04583               ACE_OS::fprintf (stderr, "spae(): number of arguments "
04584                                        "limited to %d\n", max_args);
04585             }
04586 
04587           // Skip over whitespace in between arguments
04588           for(++i; i < length && ACE_OS::ace_isspace (string[i]); ++i)
04589             {
04590             }
04591 
04592           // Save the starting point for the next time around
04593           previous = i;
04594 
04595           // Make sure we don't skip over a character due
04596           // to the above loop to skip over whitespace
04597           i--;
04598         }
04599     }
04600 }
04601 
04602 // This global function can be used from the VxWorks shell to pass
04603 // arguments to a C main () function.
04604 //
04605 // usage: -> spae main, "arg1 arg2 \"arg3 with spaces\""
04606 //
04607 // All arguments must be within double quotes, even numbers.
04608 int
04609 spae (FUNCPTR entry, ...)
04610 {
04611   static const int WINDSH_ARGS = 10;
04612   static const int MAX_ARGS    = 128;
04613   static char* argv[MAX_ARGS]  = { "ace_main", 0 };
04614   va_list pvar;
04615   int argc = 1;
04616 
04617   // Peel off arguments to spa () and put into argv.  va_arg () isn't
04618   // necessarily supposed to return 0 when done, though since the
04619   // VxWorks shell uses a fixed number (10) of arguments, it might 0
04620   // the unused ones.
04621   va_start (pvar, entry);
04622 
04623   int i = 0;
04624   for (char* str = va_arg (pvar, char*);
04625        str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
04626     {
04627       add_to_argv(argc, argv, MAX_ARGS, str);
04628     }
04629 
04630   // fill unused argv slots with 0 to get rid of leftovers
04631   // from previous invocations
04632   for (i = argc; i < MAX_ARGS; ++i)
04633     argv[i] = 0;
04634 
04635   // The hard-coded options are what ::sp () uses, except for the
04636   // larger stack size (instead of ::sp ()'s 20000).
04637   const int ret = ::taskSpawn (argv[0],    // task name
04638                                100,        // task priority
04639                                VX_FP_TASK, // task options
04640                                ACE_NEEDS_HUGE_THREAD_STACKSIZE, // stack size
04641                                entry,      // entry point
04642                                argc,       // first argument to main ()
04643                                (int) argv, // second argument to main ()
04644                                0, 0, 0, 0, 0, 0, 0, 0);
04645   va_end (pvar);
04646 
04647   // ::taskSpawn () returns the taskID on success: return 0 instead if
04648   // successful
04649   return ret > 0 ? 0 : ret;
04650 }
04651 
04652 
04653 // This global function can be used from the VxWorks shell to pass
04654 // arguments to a C main () function.  The function will be run
04655 // within the shells task.
04656 //
04657 // usage: -> spaef main, "arg1 arg2 \"arg3 with spaces\""
04658 //
04659 // All arguments must be within double quotes, even numbers.
04660 // Unlike the spae function, this fuction executes the supplied
04661 // routine in the foreground, rather than spawning it in a separate
04662 // task.
04663 int
04664 spaef (FUNCPTR entry, ...)
04665 {
04666   static const int WINDSH_ARGS = 10;
04667   static const int MAX_ARGS    = 128;
04668   static char* argv[MAX_ARGS]  = { "ace_main", 0 };
04669   va_list pvar;
04670   int argc = 1;
04671 
04672   // Peel off arguments to spa () and put into argv.  va_arg () isn't
04673   // necessarily supposed to return 0 when done, though since the
04674   // VxWorks shell uses a fixed number (10) of arguments, it might 0
04675   // the unused ones.
04676   va_start (pvar, entry);
04677 
04678   int i = 0;
04679   for (char* str = va_arg (pvar, char*);
04680        str != 0 && i < WINDSH_ARGS; str = va_arg (pvar, char*), ++i)
04681     {
04682       add_to_argv(argc, argv, MAX_ARGS, str);
04683     }
04684 
04685   // fill unused argv slots with 0 to get rid of leftovers
04686   // from previous invocations
04687   for (i = argc; i < MAX_ARGS; ++i)
04688     argv[i] = 0;
04689 
04690   int ret = entry (argc, argv);
04691 
04692   va_end (pvar);
04693 
04694   // Return the return value of the invoked ace_main routine.
04695   return ret;
04696 }
04697 # endif /* VXWORKS */
04698 
04699 # if !defined (ACE_HAS_SIGINFO_T)
04700 siginfo_t::siginfo_t (ACE_HANDLE handle)
04701   : si_handle_ (handle),
04702     si_handles_ (&handle)
04703 {
04704 }
04705 
04706 siginfo_t::siginfo_t (ACE_HANDLE *handles)
04707   : si_handle_ (handles[0]),
04708     si_handles_ (handles)
04709 {
04710 }
04711 # endif /* ACE_HAS_SIGINFO_T */
04712 
04713 pid_t
04714 ACE_OS::fork (const ACE_TCHAR *program_name)
04715 {
04716   ACE_OS_TRACE ("ACE_OS::fork");
04717 # if defined (ACE_LACKS_FORK)
04718   ACE_UNUSED_ARG (program_name);
04719   ACE_NOTSUP_RETURN (pid_t (-1));
04720 # else
04721   pid_t pid =
04722 # if defined (ACE_HAS_STHREADS)
04723     ::fork1 ();
04724 #else
04725     ::fork ();
04726 #endif /* ACE_HAS_STHREADS */
04727 
04728 #if !defined (ACE_HAS_MINIMAL_ACE_OS)
04729   if (pid == 0)
04730     ACE_Base_Thread_Adapter::sync_log_msg (program_name);
04731 #endif /* ! ACE_HAS_MINIMAL_ACE_OS */
04732 
04733   return pid;
04734 # endif /* ACE_WIN32 */
04735 }
04736 
04737 void
04738 ACE_Cleanup::cleanup (void *)
04739 {
04740   delete this;
04741 }
04742 
04743 
04744 ACE_Cleanup::~ACE_Cleanup (void)
04745 {
04746 }
04747 
04748 // This is necessary to work around nasty problems with MVS C++.
04749 
04750 extern "C" void
04751 ace_mutex_lock_cleanup_adapter (void *args)
04752 {
04753   ACE_OS::mutex_lock_cleanup (args);
04754 }
04755 
04756 ACE_Thread_ID::ACE_Thread_ID (ACE_thread_t thread_id,
04757                               ACE_hthread_t thread_handle)
04758   : thread_id_ (thread_id),
04759     thread_handle_ (thread_handle)
04760 {
04761 }
04762 
04763 ACE_Thread_ID::ACE_Thread_ID (const ACE_Thread_ID &id)
04764   : thread_id_ (id.thread_id_),
04765     thread_handle_ (id.thread_handle_)
04766 {
04767 }
04768 
04769 ACE_thread_t
04770 ACE_Thread_ID::id (void)
04771 {
04772   return this->thread_id_;
04773 }
04774 
04775 void
04776 ACE_Thread_ID::id (ACE_thread_t thread_id)
04777 {
04778   this->thread_id_ = thread_id;
04779 }
04780 
04781 ACE_hthread_t
04782 ACE_Thread_ID::handle (void)
04783 {
04784   return this->thread_handle_;
04785 }
04786 
04787 void
04788 ACE_Thread_ID::handle (ACE_hthread_t thread_handle)
04789 {
04790   this->thread_handle_ = thread_handle;
04791 }
04792 
04793 int
04794 ACE_Thread_ID::operator== (const ACE_Thread_ID &rhs) const
04795 {
04796   return ACE_OS::thr_cmp (this->thread_handle_, rhs.thread_handle_) == 0
04797     && ACE_OS::thr_equal (this->thread_id_, rhs.thread_id_) == 0;
04798 }
04799 
04800 int
04801 ACE_Thread_ID::operator!= (const ACE_Thread_ID &rhs) const
04802 {
04803   return !(*this == rhs);
04804 }
04805 
04806 // All other platforms have this inlined in OS.i
04807 #if defined (ACE_PSOS)
04808 char *
04809 ACE_OS::inet_ntoa (const struct in_addr addr)
04810 {
04811   ACE_OS_TRACE ("ACE_OS::inet_ntoa");
04812 
04813   static char addrstr[INET_ADDRSTRLEN + 1] = { 0 };
04814   ACE_UINT32 ipaddr = ntohl (addr.s_addr);
04815   //printf("Socket address %X, IP address %X.\n",addr.s_addr,ipaddr);
04816   sprintf(addrstr, "%d.%d.%d.%d",
04817           ((ipaddr & 0xff000000) >> 24) & 0x000000ff,
04818           (ipaddr & 0x00ff0000) >> 16,
04819           (ipaddr & 0x0000ff00) >> 8,
04820           (ipaddr & 0x000000ff));
04821   return addrstr;
04822 }
04823 #endif /* defined (ACE_PSOS) */
04824 
04825 int
04826 ACE_OS::inet_aton (const char *host_name, struct in_addr *addr)
04827 {
04828 #if defined (ACE_LACKS_INET_ATON)
04829   ACE_UINT32 ip_addr = ACE_OS::inet_addr (host_name);
04830 
04831   if (ip_addr == INADDR_NONE
04832       // Broadcast addresses are weird...
04833       && ACE_OS::strcmp (host_name, "255.255.255.255") != 0)
04834     return 0;
04835   else if (addr == 0)
04836     return 0;
04837   else
04838     {
04839       addr->s_addr = ip_addr;  // Network byte ordered
04840       return 1;
04841     }
04842 #elif defined (VXWORKS)
04843   // inet_aton() must returns 0 upon failure and 1 on failure, but
04844   // VxWorks inet_aton() returns OK (0) on success and ERROR (-1) on failure
04845   // like most other systems calls.  We will align here.
04846   if ( host_name && addr )
04847     {
04848       // Must reset errno first. Refer to WindRiver SPR# 34949, SPR# 36026
04849       errnoSet(0);
04850       return ::inet_aton((char*)host_name,addr) ? 0 : 1;
04851     }
04852   return 0;
04853 #else
04854   // inet_aton() returns 0 upon failure, not -1 since -1 is a valid
04855   // address (255.255.255.255).
04856   ACE_OSCALL_RETURN (::inet_aton (host_name, addr), int, 0);
04857 #endif  /* ACE_LACKS_INET_ATON */
04858 }
04859 
04860 struct tm *
04861 ACE_OS::localtime_r (const time_t *t, struct tm *res)
04862 {
04863   ACE_OS_TRACE ("ACE_OS::localtime_r");
04864 #if defined (ACE_HAS_REENTRANT_FUNCTIONS)
04865 # if defined (DIGITAL_UNIX)
04866   ACE_OSCALL_RETURN (::_Plocaltime_r (t, res), struct tm *, 0);
04867 # elif defined (HPUX_10)
04868   return (::localtime_r (t, res) == 0 ? res : (struct tm *)0);
04869 # else
04870   ACE_OSCALL_RETURN (::localtime_r (t, res), struct tm *, 0);
04871 # endif /* DIGITAL_UNIX */
04872 #elif !defined (ACE_HAS_WINCE) && !defined(ACE_PSOS) || defined (ACE_PSOS_HAS_TIME)
04873   ACE_OS_GUARD
04874 
04875   ACE_UNUSED_ARG (res);
04876   struct tm * res_ptr;
04877   ACE_OSCALL (::localtime (t), struct tm *, 0, res_ptr);
04878   if (res_ptr == 0)
04879     return 0;
04880   else
04881     {
04882       *res = *res_ptr;
04883       return res;
04884     }
04885 #else
04886   // @@ Same as ACE_OS::localtime (), you need to implement it
04887   //    yourself.
04888   ACE_UNUSED_ARG (t);
04889   ACE_UNUSED_ARG (res);
04890   ACE_NOTSUP_RETURN (0);
04891 #endif /* ACE_HAS_REENTRANT_FUNCTIONS */
04892 }
04893 
04894 ssize_t
04895 ACE_OS::pread (ACE_HANDLE handle,
04896                void *buf,
04897                size_t nbytes,
04898                off_t offset)
04899 {
04900 # if defined (ACE_HAS_P_READ_WRITE)
04901 #   if defined (ACE_WIN32)
04902 
04903   ACE_OS_GUARD
04904 
04905   // Remember the original file pointer position
04906   DWORD original_position = ::SetFilePointer (handle,
04907                                               0,
04908                                               0,
04909                                               FILE_CURRENT);
04910 
04911   if (original_position == 0xFFFFFFFF)
04912     return -1;
04913 
04914   // Go to the correct position
04915   DWORD altered_position = ::SetFilePointer (handle,
04916                                              offset,
04917                                              0,
04918                                              FILE_BEGIN);
04919   if (altered_position == 0xFFFFFFFF)
04920     return -1;
04921 
04922   DWORD bytes_read;
04923 
04924 #     if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
04925 
04926   OVERLAPPED overlapped;
04927   overlapped.Internal = 0;
04928   overlapped.InternalHigh = 0;
04929   overlapped.Offset = offset;
04930   overlapped.OffsetHigh = 0;
04931   overlapped.hEvent = 0;
04932 
04933   BOOL result = ::ReadFile (handle,
04934                             buf,
04935                             ACE_static_cast (DWORD, nbytes),
04936                             &bytes_read,
04937                             &overlapped);
04938 
04939   if (result == FALSE)
04940     {
04941       if (::GetLastError () != ERROR_IO_PENDING)
04942         return -1;
04943 
04944       else
04945         {
04946           result = ::GetOverlappedResult (handle,
04947                                           &overlapped,
04948                                           &bytes_read,
04949                                           TRUE);
04950           if (result == FALSE)
04951             return -1;
04952         }
04953     }
04954 
04955 #     else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
04956 
04957   BOOL result = ::ReadFile (handle,
04958                             buf,
04959                             nbytes,
04960                             &bytes_read,
04961                             0);
04962   if (result == FALSE)
04963     return -1;
04964 
04965 #     endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
04966 
04967   // Reset the original file pointer position
04968   if (::SetFilePointer (handle,
04969                         original_position,
04970                         0,
04971                         FILE_BEGIN) == 0xFFFFFFFF)
04972     return -1;
04973 
04974   return (ssize_t) bytes_read;
04975 
04976 #   else /* ACE_WIN32 */
04977 
04978   return ::pread (handle, buf, nbytes, offset);
04979 
04980 #   endif /* ACE_WIN32 */
04981 
04982 # else /* ACE_HAS_P_READ_WRITE */
04983 
04984   ACE_OS_GUARD
04985 
04986   // Remember the original file pointer position
04987   off_t original_position = ACE_OS::lseek (handle,
04988                                            0,
04989                                            SEEK_CUR);
04990 
04991   if (original_position == -1)
04992     return -1;
04993 
04994   // Go to the correct position
04995   off_t altered_position = ACE_OS::lseek (handle,
04996                                           offset,
04997                                           SEEK_SET);
04998 
04999   if (altered_position == -1)
05000     return -1;
05001 
05002   ssize_t bytes_read = ACE_OS::read (handle,
05003                                      buf,
05004                                      nbytes);
05005 
05006   if (bytes_read == -1)
05007     return -1;
05008 
05009   if (ACE_OS::lseek (handle,
05010                      original_position,
05011                      SEEK_SET) == -1)
05012     return -1;
05013 
05014   return bytes_read;
05015 
05016 # endif /* ACE_HAD_P_READ_WRITE */
05017 }
05018 
05019 ssize_t
05020 ACE_OS::pwrite (ACE_HANDLE handle,
05021                 const void *buf,
05022                 size_t nbytes,
05023                 off_t offset)
05024 {
05025 # if defined (ACE_HAS_P_READ_WRITE)
05026 #   if defined (ACE_WIN32)
05027 
05028   ACE_OS_GUARD
05029 
05030   // Remember the original file pointer position
05031   DWORD original_position = ::SetFilePointer (handle,
05032                                               0,
05033                                               0,
05034                                               FILE_CURRENT);
05035 
05036   if (original_position == 0xFFFFFFFF)
05037     return -1;
05038 
05039   // Go to the correct position
05040   DWORD altered_position = ::SetFilePointer (handle,
05041                                              offset,
05042                                              0,
05043                                              FILE_BEGIN);
05044   if (altered_position == 0xFFFFFFFF)
05045     return -1;
05046 
05047   DWORD bytes_written;
05048 
05049 #     if defined (ACE_HAS_WINNT4) && (ACE_HAS_WINNT4 != 0)
05050 
05051   OVERLAPPED overlapped;
05052   overlapped.Internal = 0;
05053   overlapped.InternalHigh = 0;
05054   overlapped.Offset = offset;
05055   overlapped.OffsetHigh = 0;
05056   overlapped.hEvent = 0;
05057 
05058   BOOL result = ::WriteFile (handle,
05059                              buf,
05060                              ACE_static_cast (DWORD, nbytes),
05061                              &bytes_written,
05062                              &overlapped);
05063 
05064   if (result == FALSE)
05065     {
05066       if (::GetLastError () != ERROR_IO_PENDING)
05067         return -1;
05068 
05069       else
05070         {
05071           result = ::GetOverlappedResult (handle,
05072                                           &overlapped,
05073                                           &bytes_written,
05074                                           TRUE);
05075           if (result == FALSE)
05076             return -1;
05077         }
05078     }
05079 
05080 #     else /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
05081 
05082   BOOL result = ::WriteFile (handle,
05083                              buf,
05084                              nbytes,
05085                              &bytes_written,
05086                              0);
05087   if (result == FALSE)
05088     return -1;
05089 
05090 #     endif /* ACE_HAS_WINNT4 && (ACE_HAS_WINNT4 != 0) */
05091 
05092   // Reset the original file pointer position
05093   if (::SetFilePointer (handle,
05094                         original_position,
05095                         0,
05096                         FILE_BEGIN) == 0xFFFFFFFF)
05097     return -1;
05098 
05099   return (ssize_t) bytes_written;
05100 
05101 #   else /* ACE_WIN32 */
05102 
05103   return ::pwrite (handle, buf, nbytes, offset);
05104 #   endif /* ACE_WIN32 */
05105 # else /* ACE_HAS_P_READ_WRITE */
05106 
05107   ACE_OS_GUARD
05108 
05109   // Remember the original file pointer position
05110   off_t original_position = ACE_OS::lseek (handle,
05111                                            0,
05112                                            SEEK_CUR);
05113   if (original_position == -1)
05114     return -1;
05115 
05116   // Go to the correct position
05117   off_t altered_position = ACE_OS::lseek (handle,
05118                                           offset,
05119                                           SEEK_SET);
05120   if (altered_position == -1)
05121     return -1;
05122 
05123   ssize_t bytes_written = ACE_OS::write (handle,
05124                                          buf,
05125                                          nbytes);
05126   if (bytes_written == -1)
05127     return -1;
05128 
05129   if (ACE_OS::lseek (handle,
05130                      original_position,
05131                      SEEK_SET) == -1)
05132     return -1;
05133 
05134   return bytes_written;
05135 # endif /* ACE_HAD_P_READ_WRITE */
05136 }
05137 
05138 ACE_HANDLE
05139 ACE_OS::open (const char *filename,
05140               int mode,
05141               int perms,
05142               LPSECURITY_ATTRIBUTES sa)
05143 {
05144   ACE_OS_TRACE ("ACE_OS::open");
05145 
05146 #if defined (ACE_WIN32)
05147   DWORD access = GENERIC_READ;
05148   if (ACE_BIT_ENABLED (mode, O_WRONLY))
05149     access = GENERIC_WRITE;
05150   else if (ACE_BIT_ENABLED (mode, O_RDWR))
05151     access = GENERIC_READ | GENERIC_WRITE;
05152 
05153   DWORD creation = OPEN_EXISTING;
05154 
05155   if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
05156     creation = CREATE_NEW;
05157   else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC))
05158     creation = CREATE_ALWAYS;
05159   else if (ACE_BIT_ENABLED (mode, _O_CREAT))
05160     creation = OPEN_ALWAYS;
05161   else if (ACE_BIT_ENABLED (mode, _O_TRUNC))
05162     creation = TRUNCATE_EXISTING;
05163 
05164   DWORD flags = 0;
05165 
05166   if (ACE_BIT_ENABLED (mode, _O_TEMPORARY))
05167     flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
05168 
05169   if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH))
05170     flags |= FILE_FLAG_WRITE_THROUGH;
05171   if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED))
05172     flags |= FILE_FLAG_OVERLAPPED;
05173   if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING))
05174     flags |= FILE_FLAG_NO_BUFFERING;
05175   if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS))
05176     flags |= FILE_FLAG_RANDOM_ACCESS;
05177   if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN))
05178     flags |= FILE_FLAG_SEQUENTIAL_SCAN;
05179   if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE))
05180     flags |= FILE_FLAG_DELETE_ON_CLOSE;
05181   if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS))
05182     flags |= FILE_FLAG_BACKUP_SEMANTICS;
05183   if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS))
05184     flags |= FILE_FLAG_POSIX_SEMANTICS;
05185 
05186   ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;)
05187 
05188   if (ACE_BIT_ENABLED (mode, _O_APPEND))
05189     {
05190       ACE_MT
05191         (
05192           ace_os_monitor_lock = (ACE_thread_mutex_t *)
05193             ACE_OS_Object_Manager::preallocated_object[
05194               ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK];
05195           ACE_OS::thread_mutex_lock (ace_os_monitor_lock);
05196         )
05197     }
05198 
05199   DWORD shared_mode = perms;
05200 
05201 #if defined (ACE_HAS_WINCE)
05202   ACE_HANDLE h = ::CreateFileW (ACE_Ascii_To_Wide (filename).wchar_rep (), access,
05203                                 shared_mode,
05204                                 ACE_OS::default_win32_security_attributes (sa),
05205                                 creation,
05206                                 flags,
05207                                 0);
05208 #else /* ACE_HAS_WINCE */
05209   ACE_HANDLE h = ::CreateFileA (filename, access,
05210                                 shared_mode,
05211                                 ACE_OS::default_win32_security_attributes (sa),
05212                                 creation,
05213                                 flags,
05214                                 0);
05215 #endif /* ACE_HAS_WINCE */
05216 
05217   if (ACE_BIT_ENABLED (mode, _O_APPEND))
05218     {
05219       if (h != ACE_INVALID_HANDLE)
05220         {
05221           ::SetFilePointer (h, 0, 0, FILE_END);
05222         }
05223 
05224       ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);)
05225     }
05226 
05227   if (h == ACE_INVALID_HANDLE) {
05228     ACE_FAIL_RETURN (h);
05229   } else {
05230     return h;
05231   }
05232 #elif defined (ACE_PSOS)
05233   ACE_UNUSED_ARG (perms);
05234   ACE_UNUSED_ARG (sa);
05235 # if defined (ACE_PSOS_LACKS_PHILE)
05236   ACE_UNUSED_ARG (filename);
05237   return 0;
05238 # else
05239   unsigned long result, handle;
05240   result = ::open_f (&handle, ACE_const_cast(char *, filename), 0);
05241   if (result != 0)
05242     {
05243       // We need to clean this up...not 100% correct!
05244       // To correct we should handle all the cases of TRUNC and CREAT
05245       if ((result == 0x200B) && (ACE_BIT_ENABLED (mode, O_CREAT)))
05246         {
05247           result = ::create_f(ACE_const_cast(char *, filename),1,0);
05248           if (result != 0)
05249             {
05250               errno = result;
05251               return ACE_static_cast (ACE_HANDLE, -1);
05252             }
05253           else  //File created...try to open it again
05254             {
05255               result = ::open_f (&handle, ACE_const_cast(char *, filename), 0);
05256               if (result != 0)
05257                 {
05258                   errno = result;
05259                   return ACE_static_cast (ACE_HANDLE, -1);
05260                 }
05261 
05262             }
05263         }
05264       else
05265         {
05266           errno = result;
05267           return ACE_static_cast (ACE_HANDLE, -1);
05268         }
05269     }
05270   return ACE_static_cast (ACE_HANDLE, handle);
05271 # endif /* defined (ACE_PSOS_LACKS_PHILE) */
05272 #else
05273   ACE_UNUSED_ARG (sa);
05274   ACE_OSCALL_RETURN (::open (filename, mode, perms), ACE_HANDLE, -1);
05275 #endif /* ACE_WIN32 */
05276 }
05277 
05278 #if defined (ACE_HAS_WCHAR)
05279 ACE_HANDLE
05280 ACE_OS::open (const wchar_t *filename,
05281               int mode,
05282               int perms,
05283               LPSECURITY_ATTRIBUTES sa)
05284 {
05285 #if defined (ACE_WIN32)
05286   // @@ (brunsch) Yuck, maybe there is a way to combine the code
05287   // here with the char version
05288 
05289   DWORD access = GENERIC_READ;
05290   if (ACE_BIT_ENABLED (mode, O_WRONLY))
05291     access = GENERIC_WRITE;
05292   else if (ACE_BIT_ENABLED (mode, O_RDWR))
05293     access = GENERIC_READ | GENERIC_WRITE;
05294 
05295   DWORD creation = OPEN_EXISTING;
05296 
05297   if ((mode & (_O_CREAT | _O_EXCL)) == (_O_CREAT | _O_EXCL))
05298     creation = CREATE_NEW;
05299   else if ((mode & (_O_CREAT | _O_TRUNC)) == (_O_CREAT | _O_TRUNC))
05300     creation = CREATE_ALWAYS;
05301   else if (ACE_BIT_ENABLED (mode, _O_CREAT))
05302     creation = OPEN_ALWAYS;
05303   else if (ACE_BIT_ENABLED (mode, _O_TRUNC))
05304     creation = TRUNCATE_EXISTING;
05305 
05306   DWORD flags = 0;
05307 
05308   if (ACE_BIT_ENABLED (mode, _O_TEMPORARY))
05309     flags |= FILE_FLAG_DELETE_ON_CLOSE | FILE_ATTRIBUTE_TEMPORARY;
05310 
05311   if (ACE_BIT_ENABLED (mode, FILE_FLAG_WRITE_THROUGH))
05312     flags |= FILE_FLAG_WRITE_THROUGH;
05313   if (ACE_BIT_ENABLED (mode, FILE_FLAG_OVERLAPPED))
05314     flags |= FILE_FLAG_OVERLAPPED;
05315   if (ACE_BIT_ENABLED (mode, FILE_FLAG_NO_BUFFERING))
05316     flags |= FILE_FLAG_NO_BUFFERING;
05317   if (ACE_BIT_ENABLED (mode, FILE_FLAG_RANDOM_ACCESS))
05318     flags |= FILE_FLAG_RANDOM_ACCESS;
05319   if (ACE_BIT_ENABLED (mode, FILE_FLAG_SEQUENTIAL_SCAN))
05320     flags |= FILE_FLAG_SEQUENTIAL_SCAN;
05321   if (ACE_BIT_ENABLED (mode, FILE_FLAG_DELETE_ON_CLOSE))
05322     flags |= FILE_FLAG_DELETE_ON_CLOSE;
05323   if (ACE_BIT_ENABLED (mode, FILE_FLAG_BACKUP_SEMANTICS))
05324     flags |= FILE_FLAG_BACKUP_SEMANTICS;
05325   if (ACE_BIT_ENABLED (mode, FILE_FLAG_POSIX_SEMANTICS))
05326     flags |= FILE_FLAG_POSIX_SEMANTICS;
05327 
05328   ACE_MT (ACE_thread_mutex_t *ace_os_monitor_lock = 0;)
05329 
05330   if (ACE_BIT_ENABLED (mode, _O_APPEND))
05331     {
05332       ACE_MT
05333         (
05334           ace_os_monitor_lock = (ACE_thread_mutex_t *)
05335             ACE_OS_Object_Manager::preallocated_object[
05336               ACE_OS_Object_Manager::ACE_OS_MONITOR_LOCK];
05337           ACE_OS::thread_mutex_lock (ace_os_monitor_lock);
05338         )
05339     }
05340 
05341   DWORD shared_mode = perms;
05342 
05343   ACE_HANDLE h = ::CreateFileW (filename,
05344                                 access,
05345                                 shared_mode,
05346                                 ACE_OS::default_win32_security_attributes (sa),
05347                                 creation,
05348                                 flags,
05349                                 0);
05350 
05351   if (ACE_BIT_ENABLED (mode, _O_APPEND))
05352     {
05353       if (h != ACE_INVALID_HANDLE)
05354         {
05355           ::SetFilePointer (h, 0, 0, FILE_END);
05356         }
05357 
05358       ACE_MT (ACE_OS::thread_mutex_unlock (ace_os_monitor_lock);)
05359     }
05360 
05361   if (h == ACE_INVALID_HANDLE)
05362     ACE_FAIL_RETURN (h);
05363   else
05364     return h;
05365 #else /* ACE_WIN32 */
05366   // Just emulate with ascii version
05367   return ACE_OS::open (ACE_Wide_To_Ascii (filename).char_rep (),
05368                        mode,
05369                        perms,
05370                        sa);
05371 #endif /* ACE_WIN32 */
05372 }
05373 #endif /* ACE_HAS_WCHAR */
05374 
05375 # if defined (ACE_LACKS_DIFFTIME)
05376 double
05377 ACE_OS::difftime (time_t t1, time_t t0)
05378 {
05379   /* return t1 - t0 in seconds */
05380   struct tm tms[2], *ptms[2], temp;
05381   double seconds;
05382   double days;
05383   int swap = 0;
05384 
05385   /* extract the tm structure from time_t */
05386   ptms[1] = gmtime_r (&t1, &tms[1]);
05387   if (ptms[1] == 0) return 0.0;
05388 
05389   ptms[0] = gmtime_r (&t0, &tms[0]);
05390   if (ptms[0] == 0) return 0.0;
05391 
05392     /* make sure t1 is > t0 */
05393   if (tms[1].tm_year < tms[0].tm_year)
05394     swap = 1;
05395   else if (tms[1].tm_year == tms[0].tm_year)
05396     {
05397       if (tms[1].tm_yday < tms[0].tm_yday)
05398         swap = 1;
05399       else if (tms[1].tm_yday == tms[0].tm_yday)
05400         {
05401           if (tms[1].tm_hour < tms[0].tm_hour)
05402             swap = 1;
05403           else if (tms[1].tm_hour == tms[0].tm_hour)
05404             {
05405               if (tms[1].tm_min < tms[0].tm_min)
05406                 swap = 1;
05407               else if (tms[1].tm_min == tms[0].tm_min)
05408                 {
05409                   if (tms[1].tm_sec < tms[0].tm_sec)
05410                     swap = 1;
05411                 }
05412             }
05413         }
05414     }
05415 
05416   if (swap)
05417     temp = tms[0], tms[0] = tms[1], tms[1] = temp;
05418 
05419   seconds = 0.0;
05420   if (tms[1].tm_year > tms[0].tm_year)
05421     {
05422       // Accumulate the time until t[0] catches up to t[1]'s year.
05423       seconds = 60 - tms[0].tm_sec;
05424       tms[0].tm_sec = 0;
05425       tms[0].tm_min += 1;
05426       seconds += 60 * (60 - tms[0].tm_min);
05427       tms[0].tm_min = 0;
05428       tms[0].tm_hour += 1;
05429       seconds += 60*60 * (24 - tms[0].tm_hour);
05430       tms[0].tm_hour = 0;
05431       tms[0].tm_yday += 1;
05432 
05433 #   define ISLEAPYEAR(y) ((y)&3u?0:(y)%25u?1:(y)/25u&12?0:1)
05434 
05435       if (ISLEAPYEAR(tms[0].tm_year))
05436         seconds += 60*60*24 * (366 - tms[0].tm_yday);
05437       else
05438         seconds += 60*60*24 * (365 - tms[0].tm_yday);
05439 
05440       tms[0].tm_yday = 0;
05441       tms[0].tm_year += 1;
05442 
05443       while (tms[1].tm_year > tms[0].tm_year)
05444         {
05445           if (ISLEAPYEAR(tms[0].tm_year))
05446             seconds += 60*60*24 * 366;
05447           else
05448             seconds += 60*60*24 * 365;
05449 
05450           tms[0].tm_year += 1;
05451         }
05452 
05453 #   undef ISLEAPYEAR
05454 
05455     }
05456   else
05457     {
05458       // Normalize
05459       if (tms[1].tm_sec < tms[0].tm_sec)
05460         {
05461           if (tms[1].tm_min == 0)
05462             {
05463               if (tms[1].tm_hour == 0)
05464                 {
05465                   tms[1].tm_yday -= 1;
05466                   tms[1].tm_hour += 24;
05467                 }
05468               tms[1].tm_hour -= 1;
05469               tms[1].tm_min += 60;
05470             }
05471           tms[1].tm_min -= 1;
05472           tms[1].tm_sec += 60;
05473         }
05474       tms[1].tm_sec -= tms[0].tm_sec;
05475 
05476       if (tms[1].tm_min < tms[0].tm_min)
05477         {
05478           if (tms[1].tm_hour == 0)
05479             {
05480               tms[1].tm_yday -= 1;
05481               tms[1].tm_hour += 24;
05482             }
05483           tms[1].tm_hour -= 1;
05484           tms[1].tm_min += 60;
05485         }
05486       tms[1].tm_min -= tms[0].tm_min;
05487 
05488       if (tms[1].tm_hour < tms[0].tm_hour)
05489         {
05490           tms[1].tm_yday -= 1;
05491           tms[1].tm_hour += 24;
05492         }
05493       tms[1].tm_hour -= tms[0].tm_hour;
05494 
05495       tms[1].tm_yday -= tms[0].tm_yday;
05496     }
05497 
05498   // accumulate the seconds
05499   seconds += tms[1].tm_sec;
05500   seconds += 60 * tms[1].tm_min;
05501   seconds += 60*60 * tms[1].tm_hour;
05502   seconds += 60*60*24 * tms[1].tm_yday;
05503 
05504   return seconds;
05505 }
05506 # endif /* ACE_LACKS_DIFFTIME */
05507 
05508 # if defined (ACE_HAS_WINCE)
05509 ACE_TCHAR *
05510 ACE_OS::ctime_r (const time_t *clock, ACE_TCHAR *buf, int buflen)
05511 {
05512   // buflen must be at least 26 wchar_t long.
05513   if (buflen < 26)              // Again, 26 is a magic number.
05514     {
05515       errno = ERANGE;
05516       return 0;
05517     }
05518   // This is really stupid, converting FILETIME to timeval back and
05519   // forth.  It assumes FILETIME and DWORDLONG are the same structure
05520   // internally.
05521   ULARGE_INTEGER _100ns;
05522   _100ns.QuadPart = (DWORDLONG) *clock * 10000 * 1000
05523                      + ACE_Time_Value::FILETIME_to_timval_skew;
05524   FILETIME file_time;
05525   file_time.dwLowDateTime = _100ns.LowPart;
05526   file_time.dwHighDateTime = _100ns.HighPart;
05527 
05528   FILETIME localtime;
05529   SYSTEMTIME systime;
05530   FileTimeToLocalFileTime (&file_time, &localtime);
05531   FileTimeToSystemTime (&localtime, &systime);
05532   ACE_OS::sprintf (buf, ACE_OS_CTIME_R_FMTSTR,
05533                    ACE_OS::day_of_week_name[systime.wDayOfWeek],
05534                    ACE_OS::month_name[systime.wMonth - 1],
05535                    systime.wDay,
05536                    systime.wHour,
05537                    systime.wMinute,
05538                    systime.wSecond,
05539                    systime.wYear);
05540   return buf;
05541 }
05542 # endif /* ACE_HAS_WINCE */
05543 
05544 time_t
05545 ACE_OS::mktime (struct tm *t)
05546 {
05547   ACE_OS_TRACE ("ACE_OS::mktime");
05548 #   if defined (ACE_PSOS) && ! defined (ACE_PSOS_HAS_TIME)
05549   ACE_UNUSED_ARG (t);
05550   ACE_NOTSUP_RETURN (-1);
05551 #   elif defined (ACE_HAS_WINCE)
05552   SYSTEMTIME t_sys;
05553   FILETIME t_file;
05554   t_sys.wSecond = t->tm_sec;
05555   t_sys.wMinute = t->tm_min;
05556   t_sys.wHour = t->tm_hour;
05557   t_sys.wDay = t->tm_mday;
05558   t_sys.wMonth = t->tm_mon + 1;  // SYSTEMTIME is 1-indexed, tm is 0-indexed
05559   t_sys.wYear = t->tm_year + 1900; // SYSTEMTIME is real; tm is since 1900
05560   t_sys.wDayOfWeek = t->tm_wday;  // Ignored in below function call.
05561   if (SystemTimeToFileTime (&t_sys, &t_file) == 0)
05562     return -1;
05563   ACE_Time_Value tv (t_file);
05564   return tv.sec ();
05565 #   else
05566 #     if defined (ACE_HAS_THREADS)  &&  !defined (ACE_HAS_MT_SAFE_MKTIME)
05567   ACE_OS_GUARD
05568 #     endif /* ACE_HAS_THREADS  &&  ! ACE_HAS_MT_SAFE_MKTIME */
05569 
05570   ACE_OSCALL_RETURN (::mktime (t), time_t, (time_t) -1);
05571 #   endif /* ACE_PSOS && ! ACE_PSOS_HAS_TIME */
05572 }
05573 
05574 # if !defined (ACE_HAS_THREADS) || defined (ACE_LACKS_RWLOCK_T)
05575 int
05576 ACE_OS::rwlock_init (ACE_rwlock_t *rw,
05577                      int type,
05578                      const ACE_TCHAR *name,
05579                      void *arg)
05580 {
05581   // ACE_OS_TRACE ("ACE_OS::rwlock_init");
05582 #   if defined (ACE_HAS_THREADS) && defined (ACE_LACKS_RWLOCK_T)
05583   // NT, POSIX, and VxWorks don't support this natively.
05584   ACE_UNUSED_ARG (name);
05585   int result = -1;
05586 
05587   // Since we cannot use the user specified name for all three
05588   // objects, we will create three completely new names.
05589   ACE_TCHAR name1[ACE_UNIQUE_NAME_LEN];
05590   ACE_TCHAR name2[ACE_UNIQUE_NAME_LEN];
05591   ACE_TCHAR name3[ACE_UNIQUE_NAME_LEN];
05592   ACE_TCHAR name4[ACE_UNIQUE_NAME_LEN];
05593 
05594   ACE_OS::unique_name ((const void *) &rw->lock_,
05595                        name1,
05596                        ACE_UNIQUE_NAME_LEN);
05597   ACE_OS::unique_name ((const void *) &rw->waiting_readers_,
05598                        name2,
05599                        ACE_UNIQUE_NAME_LEN);
05600   ACE_OS::unique_name ((const void *) &rw->waiting_writers_,
05601                        name3,
05602                        ACE_UNIQUE_NAME_LEN);
05603   ACE_OS::unique_name ((const void *) &rw->waiting_important_writer_,
05604                        name4,
05605                        ACE_UNIQUE_NAME_LEN);
05606 
05607   ACE_condattr_t attributes;
05608   if (ACE_OS::condattr_init (attributes, type) == 0)
05609     {
05610       if (ACE_OS::mutex_init (&rw->lock_, type, name1,
05611                               (ACE_mutexattr_t *) arg) == 0
05612           && ACE_OS::cond_init (&rw->waiting_readers_,
05613                                 attributes, name2, arg) == 0
05614           && ACE_OS::cond_init (&rw->waiting_writers_,
05615                                 attributes, name3, arg) == 0
05616           && ACE_OS::cond_init (&rw->waiting_important_writer_,
05617                                 attributes, name4, arg) == 0)
05618         {
05619           // Success!
05620           rw->ref_count_ = 0;
05621           rw->num_waiting_writers_ = 0;
05622           rw->num_waiting_readers_ = 0;
05623           rw->important_writer_ = 0;
05624           result = 0;
05625         }
05626       ACE_OS::condattr_destroy (attributes);
05627     }
05628 
05629   if (result == -1)
05630     {
05631       // Save/restore errno.
05632       ACE_Errno_Guard error (errno);
05633       ACE_OS::mutex_destroy (&rw->lock_);
05634       ACE_OS::cond_destroy (&rw->waiting_readers_);
05635       ACE_OS::cond_destroy (&rw->waiting_writers_);
05636       ACE_OS::cond_destroy (&rw->waiting_important_writer_);
05637     }
05638   return result;
05639 #   else
05640   ACE_UNUSED_ARG (rw);
05641   ACE_UNUSED_ARG (type);
05642   ACE_UNUSED_ARG (name);
05643   ACE_UNUSED_ARG (arg);
05644   ACE_NOTSUP_RETURN (-1);
05645 #   endif /* ACE_HAS_THREADS */
05646 }
05647 # endif /* ! ACE_HAS_THREADS || ACE_LACKS_RWLOCK_T */
05648 
05649 #if defined (ACE_LACKS_COND_T) && ! defined (ACE_PSOS_DIAB_MIPS)
05650 // NOTE: The ACE_OS::cond_* functions for some non-Unix platforms are
05651 // defined here either because they're too big to be inlined, or
05652 // to avoid use before definition if they were inline.
05653 
05654 int
05655 ACE_OS::cond_destroy (ACE_cond_t *cv)
05656 {
05657   ACE_OS_TRACE ("ACE_OS::cond_destroy");
05658 # if defined (ACE_HAS_THREADS)
05659 #   if defined (ACE_HAS_WTHREADS)
05660   ACE_OS::event_destroy (&cv->waiters_done_);
05661 #   elif defined (VXWORKS) || defined (ACE_PSOS)
05662   ACE_OS::sema_destroy (&cv->waiters_done_);
05663 #   endif /* VXWORKS */
05664   ACE_OS::thread_mutex_destroy (&cv->waiters_lock_);
05665   return ACE_OS::sema_destroy (&cv->sema_);
05666 # else
05667   ACE_UNUSED_ARG (cv);
05668   ACE_NOTSUP_RETURN (-1);
05669 # endif /* ACE_HAS_THREADS */
05670 }
05671 
05672 // @@ The following functions could be inlined if i could figure where
05673 // to put it among the #ifdefs!
05674 int
05675 ACE_OS::condattr_init (ACE_condattr_t &attributes,
05676                        int type)
05677 {
05678   attributes.type = type;
05679   return 0;
05680 }
05681 
05682 int
05683 ACE_OS::condattr_destroy (ACE_condattr_t &)
05684 {
05685   return 0;
05686 }
05687 
05688 int
05689 ACE_OS::cond_init (ACE_cond_t *cv,
05690                    ACE_condattr_t &attributes,
05691                    const char *name, void *arg)
05692 {
05693   return ACE_OS::cond_init (cv, attributes.type, name, arg);
05694 }
05695 
05696 #if defined (ACE_HAS_WCHAR)
05697 int
05698 ACE_OS::cond_init (ACE_cond_t *cv,
05699                    ACE_condattr_t &attributes,
05700                    const wchar_t *name, void *arg)
05701 {
05702   return ACE_OS::cond_init (cv, attributes.type, name, arg);
05703 }
05704 #endif /* ACE_HAS_WCHAR */
05705 
05706 int
05707 ACE_OS::cond_init (ACE_cond_t *cv, short type, const char *name, void *arg)
05708 {
05709   ACE_OS_TRACE ("ACE_OS::cond_init");
05710 # if defined (ACE_HAS_THREADS)
05711   cv->waiters_ = 0;
05712   cv->was_broadcast_ = 0;
05713 
05714   int result = 0;
05715   if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
05716     result = -1;
05717   else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
05718     result = -1;
05719 #   if defined (VXWORKS) || defined (ACE_PSOS)
05720   else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
05721 #   else
05722   else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
05723 #   endif /* VXWORKS */
05724     result = -1;
05725   return result;
05726 # else
05727   ACE_UNUSED_ARG (cv);
05728   ACE_UNUSED_ARG (type);
05729   ACE_UNUSED_ARG (name);
05730   ACE_UNUSED_ARG (arg);
05731   ACE_NOTSUP_RETURN (-1);
05732 # endif /* ACE_HAS_THREADS */
05733 }
05734 
05735 #if defined (ACE_HAS_WCHAR)
05736 int
05737 ACE_OS::cond_init (ACE_cond_t *cv, short type, const wchar_t *name, void *arg)
05738 {
05739   ACE_OS_TRACE ("ACE_OS::cond_init");
05740 # if defined (ACE_HAS_THREADS)
05741   cv->waiters_ = 0;
05742   cv->was_broadcast_ = 0;
05743 
05744   int result = 0;
05745   if (ACE_OS::sema_init (&cv->sema_, 0, type, name, arg) == -1)
05746     result = -1;
05747   else if (ACE_OS::thread_mutex_init (&cv->waiters_lock_) == -1)
05748     result = -1;
05749 #   if defined (VXWORKS) || defined (ACE_PSOS)
05750   else if (ACE_OS::sema_init (&cv->waiters_done_, 0, type) == -1)
05751 #   else
05752   else if (ACE_OS::event_init (&cv->waiters_done_) == -1)
05753 #   endif /* VXWORKS */
05754     result = -1;
05755   return result;
05756 # else
05757   ACE_UNUSED_ARG (cv);
05758   ACE_UNUSED_ARG (type);
05759   ACE_UNUSED_ARG (name);
05760   ACE_UNUSED_ARG (arg);
05761   ACE_NOTSUP_RETURN (-1);
05762 # endif /* ACE_HAS_THREADS */
05763 }
05764 #endif /* ACE_HAS_WCHAR */
05765 
05766 int
05767 ACE_OS::cond_signal (ACE_cond_t *cv)
05768 {
05769   ACE_OS_TRACE ("ACE_OS::cond_signal");
05770 # if defined (ACE_HAS_THREADS)
05771   // If there aren't any waiters, then this is a no-op.  Note that
05772   // this function *must* be called with the <external_mutex> held
05773   // since other wise there is a race condition that can lead to the
05774   // lost wakeup bug...  This is needed to ensure that the <waiters_>
05775   // value is not in an inconsistent internal state while being
05776   // updated by another thread.
05777   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
05778   int have_waiters = cv->waiters_ > 0;
05779   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
05780 
05781   if (have_waiters != 0)
05782     return ACE_OS::sema_post (&cv->sema_);
05783   else
05784     return 0; // No-op
05785 # else
05786   ACE_UNUSED_ARG (cv);
05787   ACE_NOTSUP_RETURN (-1);
05788 # endif /* ACE_HAS_THREADS */
05789 }
05790 
05791 int
05792 ACE_OS::cond_broadcast (ACE_cond_t *cv)
05793 {
05794   ACE_OS_TRACE ("ACE_OS::cond_broadcast");
05795 # if defined (ACE_HAS_THREADS)
05796   // The <external_mutex> must be locked before this call is made.
05797 
05798   // This is needed to ensure that <waiters_> and <was_broadcast_> are
05799   // consistent relative to each other.
05800   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
05801   int have_waiters = 0;
05802 
05803   if (cv->waiters_ > 0)
05804     {
05805       // We are broadcasting, even if there is just one waiter...
05806       // Record the fact that we are broadcasting.  This helps the
05807       // cond_wait() method know how to optimize itself.  Be sure to
05808       // set this with the <waiters_lock_> held.
05809       cv->was_broadcast_ = 1;
05810       have_waiters = 1;
05811     }
05812   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
05813   int result = 0;
05814   if (have_waiters)
05815     {
05816       // Wake up all the waiters.
05817       if (ACE_OS::sema_post (&cv->sema_, cv->waiters_) == -1)
05818         result = -1;
05819       // Wait for all the awakened threads to acquire their part of
05820       // the counting semaphore.
05821 #   if defined (VXWORKS) || defined (ACE_PSOS)
05822       else if (ACE_OS::sema_wait (&cv->waiters_done_) == -1)
05823 #   else
05824       else if (ACE_OS::event_wait (&cv->waiters_done_) == -1)
05825 #   endif /* VXWORKS */
05826         result = -1;
05827       // This is okay, even without the <waiters_lock_> held because
05828       // no other waiter threads can wake up to access it.
05829       cv->was_broadcast_ = 0;
05830     }
05831   return result;
05832 # else
05833   ACE_UNUSED_ARG (cv);
05834   ACE_NOTSUP_RETURN (-1);
05835 # endif /* ACE_HAS_THREADS */
05836 }
05837 
05838 int
05839 ACE_OS::cond_wait (ACE_cond_t *cv,
05840                    ACE_mutex_t *external_mutex)
05841 {
05842   ACE_OS_TRACE ("ACE_OS::cond_wait");
05843 # if defined (ACE_HAS_THREADS)
05844   // Prevent race conditions on the <waiters_> count.
05845   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
05846   cv->waiters_++;
05847   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
05848 
05849   int result = 0;
05850 
05851 #   if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
05852   if (external_mutex->type_ == USYNC_PROCESS)
05853     // This call will automatically release the mutex and wait on the semaphore.
05854     ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (external_mutex->proc_mutex_,
05855                                                             cv->sema_, INFINITE, FALSE),
05856                                      result),
05857                    int, -1, result);
05858   else
05859 #   endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
05860     {
05861       // We keep the lock held just long enough to increment the count of
05862       // waiters by one.  Note that we can't keep it held across the call
05863       // to ACE_OS::sema_wait() since that will deadlock other calls to
05864       // ACE_OS::cond_signal().
05865       if (ACE_OS::mutex_unlock (external_mutex) != 0)
05866         return -1;
05867 
05868       // Wait to be awakened by a ACE_OS::cond_signal() or
05869       // ACE_OS::cond_broadcast().
05870       result = ACE_OS::sema_wait (&cv->sema_);
05871     }
05872 
05873   // Reacquire lock to avoid race conditions on the <waiters_> count.
05874   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
05875 
05876   // We're ready to return, so there's one less waiter.
05877   cv->waiters_--;
05878 
05879   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
05880 
05881   // Release the lock so that other collaborating threads can make
05882   // progress.
05883   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
05884 
05885   if (result == -1)
05886     // Bad things happened, so let's just return below.
05887     /* NOOP */;
05888 #   if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
05889   else if (external_mutex->type_ == USYNC_PROCESS)
05890     {
05891       if (last_waiter)
05892 
05893         // This call atomically signals the <waiters_done_> event and
05894         // waits until it can acquire the mutex.  This is important to
05895         // prevent unfairness.
05896         ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
05897                                                                 external_mutex->proc_mutex_,
05898                                                                 INFINITE, FALSE),
05899                                          result),
05900                        int, -1, result);
05901       else
05902         // We must always regain the <external_mutex>, even when
05903         // errors occur because that's the guarantee that we give to
05904         // our callers.
05905         ACE_OS::mutex_lock (external_mutex);
05906 
05907       return result;
05908       /* NOTREACHED */
05909     }
05910 #   endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
05911   // If we're the last waiter thread during this particular broadcast
05912   // then let all the other threads proceed.
05913   else if (last_waiter)
05914 #   if defined (VXWORKS) || defined (ACE_PSOS)
05915     ACE_OS::sema_post (&cv->waiters_done_);
05916 #   else
05917     ACE_OS::event_signal (&cv->waiters_done_);
05918 #   endif /* VXWORKS */
05919 
05920   // We must always regain the <external_mutex>, even when errors
05921   // occur because that's the guarantee that we give to our callers.
05922   ACE_OS::mutex_lock (external_mutex);
05923 
05924   return result;
05925 # else
05926   ACE_UNUSED_ARG (cv);
05927   ACE_UNUSED_ARG (external_mutex);
05928   ACE_NOTSUP_RETURN (-1);
05929 # endif /* ACE_HAS_THREADS */
05930 }
05931 
05932 int
05933 ACE_OS::cond_timedwait (ACE_cond_t *cv,
05934                         ACE_mutex_t *external_mutex,
05935                         ACE_Time_Value *timeout)
05936 {
05937   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
05938 # if defined (ACE_HAS_THREADS)
05939   // Handle the easy case first.
05940   if (timeout == 0)
05941     return ACE_OS::cond_wait (cv, external_mutex);
05942 #   if defined (ACE_HAS_WTHREADS) || defined (VXWORKS) || defined (ACE_PSOS)
05943 
05944   // Prevent race conditions on the <waiters_> count.
05945   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
05946   cv->waiters_++;
05947   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
05948 
05949   int result = 0;
05950   ACE_Errno_Guard error (errno, 0);
05951   int msec_timeout;
05952 
05953   if (timeout->sec () == 0 && timeout->usec () == 0)
05954     msec_timeout = 0; // Do a "poll."
05955   else
05956     {
05957       // Note that we must convert between absolute time (which is
05958       // passed as a parameter) and relative time (which is what
05959       // WaitForSingleObjects() expects).
05960       ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
05961 
05962       // Watchout for situations where a context switch has caused the
05963       // current time to be > the timeout.
05964       if (relative_time < ACE_Time_Value::zero)
05965         msec_timeout = 0;
05966       else
05967         msec_timeout = relative_time.msec ();
05968     }
05969 
05970 #     if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
05971   if (external_mutex->type_ == USYNC_PROCESS)
05972     // This call will automatically release the mutex and wait on the
05973     // semaphore.
05974     result = ::SignalObjectAndWait (external_mutex->proc_mutex_,
05975                                     cv->sema_,
05976                                     msec_timeout,
05977                                     FALSE);
05978   else
05979 #     endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
05980     {
05981       // We keep the lock held just long enough to increment the count
05982       // of waiters by one.  Note that we can't keep it held across
05983       // the call to WaitForSingleObject since that will deadlock
05984       // other calls to ACE_OS::cond_signal().
05985       if (ACE_OS::mutex_unlock (external_mutex) != 0)
05986         return -1;
05987 
05988       // Wait to be awakened by a ACE_OS::signal() or
05989       // ACE_OS::broadcast().
05990 #     if defined (ACE_WIN32)
05991 #       if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
05992       result = ::WaitForSingleObject (cv->sema_, msec_timeout);
05993 #       else /* ACE_USES_WINCE_SEMA_SIMULATION */
05994       // Can't use Win32 API on our simulated semaphores.
05995       result = ACE_OS::sema_wait (&cv->sema_,
05996                                   timeout);
05997 #       endif /* ACE_USES_WINCE_SEMA_SIMULATION */
05998 #     elif defined (ACE_PSOS)
05999       // Inline the call to ACE_OS::sema_wait () because it takes an
06000       // ACE_Time_Value argument.  Avoid the cost of that conversion . . .
06001       u_long ticks = (KC_TICKS2SEC * msec_timeout) / ACE_ONE_SECOND_IN_MSECS;
06002       //Tick set to 0 tells pSOS to wait forever is SM_WAIT is set.
06003       if(ticks == 0)
06004         result = ::sm_p (cv->sema_.sema_, SM_NOWAIT, ticks); //no timeout
06005       else
06006         result = ::sm_p (cv->sema_.sema_, SM_WAIT, ticks);
06007 #     elif defined (VXWORKS)
06008       // Inline the call to ACE_OS::sema_wait () because it takes an
06009       // ACE_Time_Value argument.  Avoid the cost of that conversion . . .
06010       int ticks_per_sec = ::sysClkRateGet ();
06011       int ticks = msec_timeout * ticks_per_sec / ACE_ONE_SECOND_IN_MSECS;
06012       result = ::semTake (cv->sema_.sema_, ticks);
06013 #     endif /* ACE_WIN32 || VXWORKS */
06014     }
06015 
06016   // Reacquire lock to avoid race conditions.
06017   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
06018   cv->waiters_--;
06019 
06020   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
06021 
06022   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
06023 
06024 #     if defined (ACE_WIN32)
06025   if (result != WAIT_OBJECT_0)
06026     {
06027       switch (result)
06028         {
06029         case WAIT_TIMEOUT:
06030           error = ETIME;
06031           break;
06032         default:
06033           error = ::GetLastError ();
06034           break;
06035         }
06036       result = -1;
06037     }
06038 #     elif defined (ACE_PSOS)
06039   if (result != 0)
06040     {
06041       switch (result)
06042         {
06043         case ERR_TIMEOUT:  // Timeout occured with SM_WAIT
06044         case ERR_NOMSG:    // Didn't acquire semaphore w/ SM_NOWAIT (ticks=0)
06045           error = ETIME;
06046           break;
06047         default:
06048           error = errno;
06049           break;
06050         }
06051       result = -1;
06052     }
06053 #     elif defined (VXWORKS)
06054   if (result == ERROR)
06055     {
06056       switch (errno)
06057         {
06058         case S_objLib_OBJ_TIMEOUT:
06059           error = ETIME;
06060           break;
06061         case S_objLib_OBJ_UNAVAILABLE:
06062           if (msec_timeout == 0)
06063             error = ETIME;
06064           break;
06065         default:
06066           error = errno;
06067           break;
06068         }
06069       result = -1;
06070     }
06071 #     endif /* ACE_WIN32 || VXWORKS */
06072 #     if defined (ACE_HAS_SIGNAL_OBJECT_AND_WAIT)
06073   if (external_mutex->type_ == USYNC_PROCESS)
06074     {
06075       if (last_waiter)
06076         // This call atomically signals the <waiters_done_> event and
06077         // waits until it can acquire the mutex.  This is important to
06078         // prevent unfairness.
06079         ACE_WIN32CALL (ACE_ADAPT_RETVAL (::SignalObjectAndWait (cv->waiters_done_,
06080                                                                 external_mutex->proc_mutex_,
06081                                                                 INFINITE, FALSE),
06082                                          result),
06083                        int, -1, result);
06084       else
06085         // We must always regain the <external_Mutex>, even when
06086         // errors occur because that's the guarantee that we give to
06087         // our callers.
06088         ACE_OS::mutex_lock (external_mutex);
06089 
06090       return result;
06091       /* NOTREACHED */
06092     }
06093 #     endif /* ACE_HAS_SIGNAL_OBJECT_AND_WAIT */
06094   // Note that this *must* be an "if" statement rather than an "else
06095   // if" statement since the caller may have timed out and hence the
06096   // result would have been -1 above.
06097   if (last_waiter)
06098     // Release the signaler/broadcaster if we're the last waiter.
06099 #     if defined (ACE_WIN32)
06100     ACE_OS::event_signal (&cv->waiters_done_);
06101 #     else
06102     ACE_OS::sema_post (&cv->waiters_done_);
06103 #     endif /* ACE_WIN32 */
06104 
06105   // We must always regain the <external_mutex>, even when errors
06106   // occur because that's the guarantee that we give to our callers.
06107   ACE_OS::mutex_lock (external_mutex);
06108 
06109   return result;
06110 #   endif /* ACE_HAS_WTHREADS || ACE_HAS_VXWORKS || ACE_PSOS */
06111 # else
06112   ACE_UNUSED_ARG (cv);
06113   ACE_UNUSED_ARG (external_mutex);
06114   ACE_UNUSED_ARG (timeout);
06115   ACE_NOTSUP_RETURN (-1);
06116 # endif /* ACE_HAS_THREADS */
06117 }
06118 
06119 # if defined (ACE_HAS_WTHREADS)
06120 int
06121 ACE_OS::cond_timedwait (ACE_cond_t *cv,
06122                         ACE_thread_mutex_t *external_mutex,
06123                         ACE_Time_Value *timeout)
06124 {
06125   ACE_OS_TRACE ("ACE_OS::cond_timedwait");
06126 #   if defined (ACE_HAS_THREADS)
06127   // Handle the easy case first.
06128   if (timeout == 0)
06129     return ACE_OS::cond_wait (cv, external_mutex);
06130 
06131   // Prevent race conditions on the <waiters_> count.
06132   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
06133   cv->waiters_++;
06134   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
06135 
06136   int result = 0;
06137   int error = 0;
06138   int msec_timeout;
06139 
06140   if (timeout->sec () == 0 && timeout->usec () == 0)
06141     msec_timeout = 0; // Do a "poll."
06142   else
06143     {
06144       // Note that we must convert between absolute time (which is
06145       // passed as a parameter) and relative time (which is what
06146       // WaitForSingleObjects() expects).
06147       ACE_Time_Value relative_time (*timeout - ACE_OS::gettimeofday ());
06148 
06149       // Watchout for situations where a context switch has caused the
06150       // current time to be > the timeout.
06151       if (relative_time < ACE_Time_Value::zero)
06152         msec_timeout = 0;
06153       else
06154         msec_timeout = relative_time.msec ();
06155     }
06156 
06157   // We keep the lock held just long enough to increment the count of
06158   // waiters by one.  Note that we can't keep it held across the call
06159   // to WaitForSingleObject since that will deadlock other calls to
06160   // ACE_OS::cond_signal().
06161   if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
06162     return -1;
06163 
06164   // Wait to be awakened by a ACE_OS::signal() or ACE_OS::broadcast().
06165 #     if defined (ACE_USES_WINCE_SEMA_SIMULATION)
06166   // Can't use Win32 API on simulated semaphores.
06167   result = ACE_OS::sema_wait (&cv->sema_,
06168                               timeout);
06169 
06170   if (result == -1 && errno == ETIME)
06171     result = WAIT_TIMEOUT;
06172 #     else
06173   result = ::WaitForSingleObject (cv->sema_, msec_timeout);
06174 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
06175 
06176   // Reacquire lock to avoid race conditions.
06177   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
06178 
06179   cv->waiters_--;
06180 
06181   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
06182 
06183   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
06184 
06185   if (result != WAIT_OBJECT_0)
06186     {
06187       switch (result)
06188         {
06189         case WAIT_TIMEOUT:
06190           error = ETIME;
06191           break;
06192         default:
06193           error = ::GetLastError ();
06194           break;
06195         }
06196       result = -1;
06197     }
06198 
06199   if (last_waiter)
06200     // Release the signaler/broadcaster if we're the last waiter.
06201     ACE_OS::event_signal (&cv->waiters_done_);
06202 
06203   // We must always regain the <external_mutex>, even when errors
06204   // occur because that's the guarantee that we give to our callers.
06205   ACE_OS::thread_mutex_lock (external_mutex);
06206   errno = error;
06207   return result;
06208 #   else
06209   ACE_NOTSUP_RETURN (-1);
06210 #   endif /* ACE_HAS_THREADS */
06211 }
06212 
06213 int
06214 ACE_OS::cond_wait (ACE_cond_t *cv,
06215                    ACE_thread_mutex_t *external_mutex)
06216 {
06217   ACE_OS_TRACE ("ACE_OS::cond_wait");
06218 #   if defined (ACE_HAS_THREADS)
06219   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
06220   cv->waiters_++;
06221   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
06222 
06223   int result = 0;
06224   int error = 0;
06225 
06226   // We keep the lock held just long enough to increment the count of
06227   // waiters by one.  Note that we can't keep it held across the call
06228   // to ACE_OS::sema_wait() since that will deadlock other calls to
06229   // ACE_OS::cond_signal().
06230   if (ACE_OS::thread_mutex_unlock (external_mutex) != 0)
06231     return -1;
06232 
06233   // Wait to be awakened by a ACE_OS::cond_signal() or
06234   // ACE_OS::cond_broadcast().
06235 #     if !defined (ACE_USES_WINCE_SEMA_SIMULATION)
06236   result = ::WaitForSingleObject (cv->sema_, INFINITE);
06237 #     else
06238   // Can't use Win32 API on simulated semaphores.
06239   result = ACE_OS::sema_wait (&cv->sema_);
06240 
06241   if (result != WAIT_OBJECT_0 && errno == ETIME)
06242     result = WAIT_TIMEOUT;
06243 
06244 #     endif /* ACE_USES_WINCE_SEMA_SIMULATION */
06245 
06246   // Reacquire lock to avoid race conditions.
06247   ACE_OS::thread_mutex_lock (&cv->waiters_lock_);
06248 
06249   cv->waiters_--;
06250 
06251   int last_waiter = cv->was_broadcast_ && cv->waiters_ == 0;
06252 
06253   ACE_OS::thread_mutex_unlock (&cv->waiters_lock_);
06254 
06255   if (result != WAIT_OBJECT_0)
06256     {
06257       switch (result)
06258         {
06259         case WAIT_TIMEOUT:
06260           error = ETIME;
06261           break;
06262         default:
06263           error = ::GetLastError ();
06264           break;
06265         }
06266     }
06267   else if (last_waiter)
06268     // Release the signaler/broadcaster if we're the last waiter.
06269     ACE_OS::event_signal (&cv->waiters_done_);
06270 
06271   // We must always regain the <external_mutex>, even when errors
06272   // occur because that's the guarantee that we give to our callers.
06273   ACE_OS::thread_mutex_lock (external_mutex);
06274 
06275   // Reset errno in case mutex_lock() also fails...
06276   errno = error;
06277   return result;
06278 #   else
06279   ACE_NOTSUP_RETURN (-1);
06280 #   endif /* ACE_HAS_THREADS */
06281 }
06282 # endif /* ACE_HAS_WTHREADS */
06283 #endif /* ACE_LACKS_COND_T */
06284 
06285 void
06286 ACE_OS::exit (int status)
06287 {
06288   ACE_OS_TRACE ("ACE_OS::exit");
06289 
06290 #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER) && !defined (ACE_HAS_WINCE) && !defined (ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER)
06291   // Shut down the ACE_Object_Manager, if it had registered its exit_hook.
06292   // With ACE_HAS_NONSTATIC_OBJECT_MANAGER, the ACE_Object_Manager is
06293   // instantiated on the main's stack.  ::exit () doesn't destroy it.
06294   if (exit_hook_)
06295     (*exit_hook_) ();
06296 #endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER && !ACE_HAS_WINCE && !ACE_DOESNT_INSTANTIATE_NONSTATIC_OBJECT_MANAGER */
06297 
06298 #if !defined (ACE_HAS_WINCE)
06299 # if defined (ACE_WIN32)
06300   ::ExitProcess ((UINT) status);
06301 # elif defined (ACE_PSOSIM)
06302   ::u_exit (status);
06303 # else
06304   ::exit (status);
06305 # endif /* ACE_WIN32 */
06306 #else
06307   // @@ This is not exactly the same as ExitProcess.  But this is the
06308   // closest one I can get.
06309   ::TerminateProcess (::GetCurrentProcess (), status);
06310 #endif /* ACE_HAS_WINCE */
06311 }
06312 
06313 # if defined (ACE_PSOS)
06314 
06315 // bit masks and shifts for prying info out of the pSOS time encoding
06316 const u_long ACE_PSOS_Time_t::year_mask     = 0x0000FFFFul;
06317 const u_long ACE_PSOS_Time_t::month_mask    = 0x000000FFul;
06318 const u_long ACE_PSOS_Time_t::day_mask      = 0x000000FFul;
06319 const u_long ACE_PSOS_Time_t::hour_mask     = 0x0000FFFFul;
06320 const u_long ACE_PSOS_Time_t::minute_mask   = 0x000000FFul;
06321 const u_long ACE_PSOS_Time_t::second_mask   = 0x000000FFul;
06322 const int ACE_PSOS_Time_t::year_shift   = 16;
06323 const int ACE_PSOS_Time_t::month_shift  = 8;
06324 const int ACE_PSOS_Time_t::hour_shift   = 16;
06325 const int ACE_PSOS_Time_t::minute_shift = 8;
06326 const int ACE_PSOS_Time_t::year_origin = 1900;
06327 const int ACE_PSOS_Time_t::month_origin = 1;
06328 
06329 // maximum number of clock ticks supported
06330 const u_long ACE_PSOS_Time_t::max_ticks = ~0UL;
06331 
06332 ACE_PSOS_Time_t::ACE_PSOS_Time_t (void)
06333   : date_ (0),
06334     time_ (0),
06335     ticks_ (0)
06336 {
06337 }
06338 
06339 // default ctor: date, time, and ticks all zeroed
06340 
06341 ACE_PSOS_Time_t::ACE_PSOS_Time_t (const timespec_t& t)
06342 {
06343   struct tm* tm_struct = ACE_OS::gmtime (&(t.tv_sec));
06344 
06345   // Encode date values from tm struct into pSOS date bit array.
06346   date_ = (ACE_PSOS_Time_t::year_mask &
06347            ACE_static_cast (u_long,
06348                             tm_struct->tm_year + ACE_PSOS_Time_t::year_origin)) <<
06349     ACE_PSOS_Time_t::year_shift;
06350   date_ |= (ACE_PSOS_Time_t::month_mask &
06351             ACE_static_cast (u_long,
06352                              tm_struct->tm_mon + ACE_PSOS_Time_t::month_origin)) <<
06353     ACE_PSOS_Time_t::month_shift;
06354   date_ |= ACE_PSOS_Time_t::day_mask &
06355     ACE_static_cast (u_long, tm_struct->tm_mday);
06356   // Encode time values from tm struct into pSOS time bit array.
06357   time_ = (ACE_PSOS_Time_t::hour_mask  &
06358             ACE_static_cast (u_long, tm_struct->tm_hour)) <<
06359     ACE_PSOS_Time_t::hour_shift;
06360   time_ |= (ACE_PSOS_Time_t::minute_mask &
06361             ACE_static_cast (u_long, tm_struct->tm_min)) <<
06362     ACE_PSOS_Time_t::minute_shift;
06363   time_ |= ACE_PSOS_Time_t::second_mask &
06364     ACE_static_cast (u_int, tm_struct->tm_sec);
06365 
06366   // encode nanoseconds as system clock ticks
06367   ticks_ = ACE_static_cast (u_long,
06368                             ((ACE_static_cast (double, t.tv_nsec) *
06369                               ACE_static_cast (double, KC_TICKS2SEC)) /
06370                              ACE_static_cast (double, 1000000000)));
06371 
06372 }
06373 
06374 // ctor from a timespec_t
06375 
06376 ACE_PSOS_Time_t::operator timespec_t (void)
06377 {
06378   struct tm tm_struct;
06379 
06380   // Decode date and time bit arrays and fill in fields of tm_struct.
06381 
06382   tm_struct.tm_year =
06383     ACE_static_cast (int, (ACE_PSOS_Time_t::year_mask &
06384                            (date_ >> ACE_PSOS_Time_t::year_shift))) -
06385     ACE_PSOS_Time_t::year_origin;
06386   tm_struct.tm_mon =
06387     ACE_static_cast (int, (ACE_PSOS_Time_t::month_mask &
06388                            (date_ >> ACE_PSOS_Time_t::month_shift))) -
06389     ACE_PSOS_Time_t::month_origin;
06390   tm_struct.tm_mday =
06391     ACE_static_cast (int, (ACE_PSOS_Time_t::day_mask & date_));
06392   tm_struct.tm_hour =
06393     ACE_static_cast (int, (ACE_PSOS_Time_t::hour_mask &
06394                            (time_ >> ACE_PSOS_Time_t::hour_shift)));
06395   tm_struct.tm_min =
06396     ACE_static_cast (int, (ACE_PSOS_Time_t::minute_mask &
06397                            (time_ >> ACE_PSOS_Time_t::minute_shift)));
06398   tm_struct.tm_sec =
06399     ACE_static_cast (int, (ACE_PSOS_Time_t::second_mask & time_));
06400 
06401   // Indicate values we don't know as negative numbers.
06402   tm_struct.tm_wday  = -1;
06403   tm_struct.tm_yday  = -1;
06404   tm_struct.tm_isdst = -1;
06405 
06406   timespec_t t;
06407 
06408   // Convert calendar time to time struct.
06409   t.tv_sec = ACE_OS::mktime (&tm_struct);
06410 
06411   // Encode nanoseconds as system clock ticks.
06412   t.tv_nsec = ACE_static_cast (long,
06413                                ((ACE_static_cast (double, ticks_) *
06414                                  ACE_static_cast (double, 1000000000)) /
06415                                 ACE_static_cast (double, KC_TICKS2SEC)));
06416   return t;
06417 }
06418 
06419 // type cast operator (to a timespec_t)
06420 
06421 u_long
06422 ACE_PSOS_Time_t::get_system_time (ACE_PSOS_Time_t& t)
06423 {
06424   u_long ret_val = 0;
06425 
06426 #   if defined (ACE_PSOSIM) // system time is broken in simulator.
06427   timeval tv;
06428   int result = 0;
06429   ACE_OSCALL (::gettimeofday (&tv, 0), int, -1, result);
06430   if (result == -1)
06431     return 1;
06432 
06433   ACE_Time_Value atv (tv);
06434   timespec ts = atv;
06435   ACE_PSOS_Time_t pt (ts);
06436   t.date_ = pt.date_;
06437   t.time_ = pt.time_;
06438   t.ticks_ = pt.ticks_;
06439 #   else
06440   ret_val = tm_get (&(t.date_), &(t.time_), &(t.ticks_));
06441 #   endif  /* ACE_PSOSIM */
06442   return ret_val;
06443 }
06444 
06445 // Static member function to get current system time.
06446 
06447 u_long
06448 ACE_PSOS_Time_t::set_system_time (const ACE_PSOS_Time_t& t)
06449 {
06450   return tm_set (t.date_, t.time_, t.ticks_);
06451 }
06452 
06453 // Static member function to set current system time.
06454 
06455 #   if defined (ACE_PSOSIM)
06456 
06457 u_long
06458 ACE_PSOS_Time_t::init_simulator_time (void)
06459 {
06460   // This is a hack using a direct UNIX system call, because the
06461   // appropriate ACE_OS method ultimately uses the pSOS tm_get
06462   // function, which would fail because the simulator's system time is
06463   // uninitialized (chicken and egg).
06464   timeval t;
06465   int result = 0;
06466   ACE_OSCALL (::gettimeofday (&t, 0),
06467               int,
06468               -1,
06469               result);
06470 
06471   if (result == -1)
06472     return 1;
06473   else
06474     {
06475       ACE_Time_Value tv (t);
06476       timespec ts = tv;
06477       ACE_PSOS_Time_t pt (ts);
06478       u_long ret_val =
06479         ACE_PSOS_Time_t::set_system_time (pt);
06480       return ret_val;
06481 
06482     }
06483 }
06484 
06485 // Static member function to initialize system time, using UNIX calls.
06486 
06487 #   endif /* ACE_PSOSIM */
06488 # endif /* ACE_PSOS && ! ACE_PSOS_DIAB_MIPS */
06489 
06490 # if defined (__DGUX) && defined (ACE_HAS_THREADS) && defined (_POSIX4A_DRAFT10_SOURCE)
06491 extern "C" int __d6_sigwait (sigset_t *set);
06492 
06493 extern "C" int __d10_sigwait (const sigset_t *set, int *sig)
06494 {
06495   sigset_t unconst_set = *set;
06496   int caught_sig = __d6_sigwait (&unconst_set);
06497 
06498   if (caught == -1)
06499     return -1;
06500 
06501   *sig = caught_sig;
06502   return 0;
06503 }
06504 # endif /* __DGUX && PTHREADS && _POSIX4A_DRAFT10_SOURCE */
06505 
06506 # define ACE_OS_PREALLOCATE_OBJECT(TYPE, ID)\
06507     {\
06508       TYPE *obj_p = 0;\
06509       ACE_NEW_RETURN (obj_p, TYPE, -1);\
06510       preallocated_object[ID] = (void *) obj_p;\
06511     }
06512 # define ACE_OS_DELETE_PREALLOCATED_OBJECT(TYPE, ID)\
06513     delete (TYPE *) preallocated_object[ID];\
06514     preallocated_object[ID] = 0;
06515 
06516 ACE_Object_Manager_Base::ACE_Object_Manager_Base (void)
06517   : object_manager_state_ (OBJ_MAN_UNINITIALIZED)
06518   , dynamically_allocated_ (0)
06519   , next_ (0)
06520 {
06521 }
06522 
06523 ACE_Object_Manager_Base::~ACE_Object_Manager_Base (void)
06524 {
06525 #if defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
06526   // Clear the flag so that fini () doesn't delete again.
06527   dynamically_allocated_ = 0;
06528 #endif /* ACE_HAS_NONSTATIC_OBJECT_MANAGER */
06529 }
06530 
06531 int
06532 ACE_Object_Manager_Base::starting_up_i ()
06533 {
06534   return object_manager_state_ < OBJ_MAN_INITIALIZED;
06535 }
06536 
06537 int
06538 ACE_Object_Manager_Base::shutting_down_i ()
06539 {
06540   return object_manager_state_ > OBJ_MAN_INITIALIZED;
06541 }
06542 
06543 extern "C"
06544 void
06545 ACE_OS_Object_Manager_Internal_Exit_Hook (void)
06546 {
06547   if (ACE_OS_Object_Manager::instance_)
06548     ACE_OS_Object_Manager::instance ()->fini ();
06549 }
06550 
06551 ACE_OS_Object_Manager *ACE_OS_Object_Manager::instance_ = 0;
06552 
06553 void *ACE_OS_Object_Manager::preallocated_object[
06554   ACE_OS_Object_Manager::ACE_OS_PREALLOCATED_OBJECTS] = { 0 };
06555 
06556 ACE_OS_Object_Manager::ACE_OS_Object_Manager (void)
06557   // default_mask_ isn't initialized, because it's defined by <init>.
06558   : thread_hook_ (0)
06559   , exit_info_ ()
06560 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
06561   , seh_except_selector_ (ACE_SEH_Default_Exception_Selector)
06562   , seh_except_handler_ (ACE_SEH_Default_Exception_Handler)
06563 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
06564 {
06565   // If instance_ was not 0, then another ACE_OS_Object_Manager has
06566   // already been instantiated (it is likely to be one initialized by
06567   // way of library/DLL loading).  Let this one go through
06568   // construction in case there really is a good reason for it (like,
06569   // ACE is a static/archive library, and this one is the non-static
06570   // instance (with ACE_HAS_NONSTATIC_OBJECT_MANAGER, or the user has
06571   // a good reason for creating a separate one) but the original one
06572   // will be the one retrieved from calls to
06573   // ACE_Object_Manager::instance().
06574 
06575   // Be sure that no further instances are created via instance ().
06576   if (instance_ == 0)
06577     instance_ = this;
06578 
06579   init ();
06580 }
06581 
06582 ACE_OS_Object_Manager::~ACE_OS_Object_Manager (void)
06583 {
06584   dynamically_allocated_ = 0;   // Don't delete this again in fini()
06585   fini ();
06586 }
06587 
06588 sigset_t *
06589 ACE_OS_Object_Manager::default_mask (void)
06590 {
06591   return ACE_OS_Object_Manager::instance ()->default_mask_;
06592 }
06593 
06594 ACE_Thread_Hook *
06595 ACE_OS_Object_Manager::thread_hook (void)
06596 {
06597   return ACE_OS_Object_Manager::instance ()->thread_hook_;
06598 }
06599 
06600 #if defined (ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS)
06601 ACE_SEH_EXCEPT_HANDLER
06602 ACE_OS_Object_Manager::seh_except_selector (void)
06603 {
06604   return ACE_OS_Object_Manager::instance ()->seh_except_selector_;
06605 }
06606 
06607 ACE_SEH_EXCEPT_HANDLER
06608 ACE_OS_Object_Manager::seh_except_selector (ACE_SEH_EXCEPT_HANDLER n)
06609 {
06610   ACE_OS_Object_Manager *instance =
06611     ACE_OS_Object_Manager::instance ();
06612 
06613   ACE_SEH_EXCEPT_HANDLER retv = instance->seh_except_selector_;
06614   instance->seh_except_selector_ = n;
06615   return retv;
06616 }
06617 
06618 ACE_SEH_EXCEPT_HANDLER
06619 ACE_OS_Object_Manager::seh_except_handler (void)
06620 {
06621   return ACE_OS_Object_Manager::instance ()->seh_except_handler_;
06622 }
06623 
06624 ACE_SEH_EXCEPT_HANDLER
06625 ACE_OS_Object_Manager::seh_except_handler (ACE_SEH_EXCEPT_HANDLER n)
06626 {
06627   ACE_OS_Object_Manager *instance =
06628     ACE_OS_Object_Manager::instance ();
06629 
06630   ACE_SEH_EXCEPT_HANDLER retv = instance->seh_except_handler_;
06631   instance->seh_except_handler_ = n;
06632   return retv;
06633 }
06634 #endif /* ACE_HAS_WIN32_STRUCTURAL_EXCEPTIONS */
06635 
06636 ACE_Thread_Hook *
06637 ACE_OS_Object_Manager::thread_hook (ACE_Thread_Hook *new_thread_hook)
06638 {
06639   ACE_OS_Object_Manager *os_om = ACE_OS_Object_Manager::instance ();
06640   ACE_Thread_Hook *old_hook = os_om->thread_hook_;
06641   os_om->thread_hook_ = new_thread_hook;
06642   return old_hook;
06643 }
06644 
06645 ACE_OS_Object_Manager *
06646 ACE_OS_Object_Manager::instance (void)
06647 {
06648   // This function should be called during construction of static
06649   // instances, or before any other threads have been created in the
06650   // process.  So, it's not thread safe.
06651 
06652   if (instance_ == 0)
06653     {
06654       ACE_OS_Object_Manager *instance_pointer;
06655 
06656       ACE_NEW_RETURN (instance_pointer,
06657                       ACE_OS_Object_Manager,
06658                       0);
06659       // I (coryan) removed it, using asserts in the OS layer
06660       // brings down the Log msg stuff
06661       // ACE_ASSERT (instance_pointer == instance_);
06662 
06663       instance_pointer->dynamically_allocated_ = 1;
06664 
06665     }
06666 
06667   return instance_;
06668 }
06669 
06670 int
06671 ACE_OS_Object_Manager::init (void)
06672 {
06673   if (starting_up_i ())
06674     {
06675       // First, indicate that this ACE_OS_Object_Manager instance is being
06676       // initialized.
06677       object_manager_state_ = OBJ_MAN_INITIALIZING;
06678 
06679       if (this == instance_)
06680         {
06681 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
06682 #   if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
06683           ACE_CE_Errno::init ();
06684 #   endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
06685           ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t, ACE_OS_MONITOR_LOCK)
06686           if (ACE_OS::thread_mutex_init
06687               // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06688               (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0)
06689             ACE_OS_Object_Manager::print_error_message (
06690               __LINE__, ACE_LIB_TEXT ("ACE_OS_MONITOR_LOCK"));
06691           ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t,
06692                                      ACE_TSS_CLEANUP_LOCK)
06693           if (ACE_OS::recursive_mutex_init
06694               // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06695               (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_CLEANUP_LOCK])) != 0)
06696             ACE_OS_Object_Manager::print_error_message (
06697               __LINE__, ACE_LIB_TEXT ("ACE_TSS_CLEANUP_LOCK"));
06698           ACE_OS_PREALLOCATE_OBJECT (ACE_thread_mutex_t,
06699                                      ACE_LOG_MSG_INSTANCE_LOCK)
06700           if (ACE_OS::thread_mutex_init
06701               // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06702               (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_LOG_MSG_INSTANCE_LOCK])) != 0)
06703             ACE_OS_Object_Manager::print_error_message (
06704               __LINE__, ACE_LIB_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK"));
06705 #   if defined (ACE_HAS_TSS_EMULATION)
06706           ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t,
06707                                      ACE_TSS_KEY_LOCK)
06708           if (ACE_OS::recursive_mutex_init
06709               // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06710               (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_KEY_LOCK])) != 0)
06711             ACE_OS_Object_Manager::print_error_message (
06712               __LINE__, ACE_LIB_TEXT ("ACE_TSS_KEY_LOCK"));
06713 #     if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
06714           ACE_OS_PREALLOCATE_OBJECT (ACE_recursive_thread_mutex_t,
06715                                      ACE_TSS_BASE_LOCK)
06716           if (ACE_OS::recursive_mutex_init
06717               // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06718               (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_BASE_LOCK])) != 0)
06719             ACE_OS_Object_Manager::print_error_message (
06720               __LINE__, ACE_LIB_TEXT ("ACE_TSS_BASE_LOCK"));
06721 #     endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
06722 #   endif /* ACE_HAS_TSS_EMULATION */
06723 # endif /* ACE_MT_SAFE */
06724 
06725           // Open Winsock (no-op on other platforms).
06726           ACE_OS::socket_init (ACE_WSOCK_VERSION);
06727 
06728           // Register the exit hook, for use by ACE_OS::exit ().
06729           ACE_OS::set_exit_hook (&ACE_OS_Object_Manager_Internal_Exit_Hook);
06730         }
06731 
06732       ACE_NEW_RETURN (default_mask_, sigset_t, -1);
06733       ACE_OS::sigfillset (default_mask_);
06734 
06735       // Finally, indicate that the ACE_OS_Object_Manager instance has
06736       // been initialized.
06737       object_manager_state_ = OBJ_MAN_INITIALIZED;
06738 
06739 # if defined (ACE_WIN32)
06740       ACE_OS::win32_versioninfo_.dwOSVersionInfoSize =
06741         sizeof (OSVERSIONINFO);
06742       ::GetVersionEx (&ACE_OS::win32_versioninfo_);
06743 # endif /* ACE_WIN32 */
06744       return 0;
06745     } else {
06746       // Had already initialized.
06747       return 1;
06748     }
06749 }
06750 
06751 // Clean up an ACE_OS_Object_Manager.  There can be instances of this object
06752 // other than The Instance.  This can happen if a user creates one for some
06753 // reason.  All objects clean up their per-object information and managed
06754 // objects, but only The Instance cleans up the static preallocated objects.
06755 int
06756 ACE_OS_Object_Manager::fini (void)
06757 {
06758   if (instance_ == 0  ||  shutting_down_i ())
06759     // Too late.  Or, maybe too early.  Either fini () has already
06760     // been called, or init () was never called.
06761     return object_manager_state_ == OBJ_MAN_SHUT_DOWN  ?  1  :  -1;
06762 
06763   // No mutex here.  Only the main thread should destroy the singleton
06764   // ACE_OS_Object_Manager instance.
06765 
06766   // Indicate that the ACE_OS_Object_Manager instance is being shut
06767   // down.  This object manager should be the last one to be shut
06768   // down.
06769   object_manager_state_ = OBJ_MAN_SHUTTING_DOWN;
06770 
06771   // If another Object_Manager has registered for termination, do it.
06772   if (next_)
06773     {
06774       next_->fini ();
06775       next_ = 0;  // Protect against recursive calls.
06776     }
06777 
06778   // Call all registered cleanup hooks, in reverse order of
06779   // registration.
06780   exit_info_.call_hooks ();
06781 
06782   // Only clean up preallocated objects when the singleton Instance is being
06783   // destroyed.
06784   if (this == instance_)
06785     {
06786       // Close down Winsock (no-op on other platforms).
06787       ACE_OS::socket_fini ();
06788 
06789 #if ! defined (ACE_HAS_STATIC_PREALLOCATION)
06790       // Cleanup the dynamically preallocated objects.
06791 # if defined (ACE_MT_SAFE) && (ACE_MT_SAFE != 0)
06792 #   if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
06793       if (ACE_OS::thread_mutex_destroy
06794           // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06795           (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_OS_MONITOR_LOCK])) != 0)
06796         ACE_OS_Object_Manager::print_error_message (
06797           __LINE__, ACE_LIB_TEXT ("ACE_OS_MONITOR_LOCK"));
06798 #   endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
06799       ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t,
06800                                          ACE_OS_MONITOR_LOCK)
06801 #   if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
06802       if (ACE_OS::recursive_mutex_destroy
06803           // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06804           (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_CLEANUP_LOCK])) != 0)
06805         ACE_OS_Object_Manager::print_error_message (
06806           __LINE__, ACE_LIB_TEXT ("ACE_TSS_CLEANUP_LOCK"));
06807 #   endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
06808       ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t,
06809                                          ACE_TSS_CLEANUP_LOCK)
06810 #   if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
06811       if (ACE_OS::thread_mutex_destroy
06812           // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06813           (ACE_reinterpret_cast (ACE_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object [ACE_LOG_MSG_INSTANCE_LOCK])) != 0)
06814         ACE_OS_Object_Manager::print_error_message (
06815           __LINE__, ACE_LIB_TEXT ("ACE_LOG_MSG_INSTANCE_LOCK "));
06816 #   endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
06817       ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_thread_mutex_t,
06818                                          ACE_LOG_MSG_INSTANCE_LOCK)
06819 #   if defined (ACE_HAS_TSS_EMULATION)
06820 #     if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
06821         if (ACE_OS::recursive_mutex_destroy
06822             // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06823             (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_KEY_LOCK])) != 0)
06824           ACE_OS_Object_Manager::print_error_message (
06825             __LINE__, ACE_LIB_TEXT ("ACE_TSS_KEY_LOCK"));
06826 #     endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
06827       ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t,
06828                                          ACE_TSS_KEY_LOCK)
06829 #     if defined (ACE_HAS_THREAD_SPECIFIC_STORAGE)
06830 #       if !defined(ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK)
06831           if (ACE_OS::recursive_mutex_destroy
06832               // This line must not be broken to avoid tickling a bug with SunC++'s preprocessor.
06833               (ACE_reinterpret_cast (ACE_recursive_thread_mutex_t *, ACE_OS_Object_Manager::preallocated_object[ACE_TSS_BASE_LOCK])) != 0)
06834             ACE_OS_Object_Manager::print_error_message (
06835               __LINE__, ACE_LIB_TEXT ("ACE_TSS_BASE_LOCK"));
06836 #       endif /* ! ACE_HAS_BROKEN_PREALLOCATED_OBJECTS_AFTER_FORK */
06837       ACE_OS_DELETE_PREALLOCATED_OBJECT (ACE_recursive_thread_mutex_t,
06838                                          ACE_TSS_BASE_LOCK)
06839 #     endif /* ACE_HAS_THREAD_SPECIFIC_STORAGE */
06840 #   endif /* ACE_HAS_TSS_EMULATION */
06841 #   if defined (ACE_HAS_WINCE_BROKEN_ERRNO)
06842           ACE_CE_Errno::fini ();
06843 #   endif /* ACE_HAS_WINCE_BROKEN_ERRNO */
06844 # endif /* ACE_MT_SAFE */
06845 #endif /* ! ACE_HAS_STATIC_PREALLOCATION */
06846     }
06847 
06848   delete default_mask_;
06849   default_mask_ = 0;
06850 
06851   // Indicate that this ACE_OS_Object_Manager instance has been shut down.
06852   object_manager_state_ = OBJ_MAN_SHUT_DOWN;
06853 
06854   if (dynamically_allocated_)
06855     {
06856       delete this;
06857     }
06858 
06859   if (this == instance_)
06860     instance_ = 0;
06861 
06862   return 0;
06863 }
06864 
06865 int ace_exit_hook_marker = 0;
06866 
06867 int
06868 ACE_OS_Object_Manager::at_exit (ACE_EXIT_HOOK func)
06869 {
06870   return exit_info_.at_exit_i (&ace_exit_hook_marker,
06871                                ACE_reinterpret_cast (ACE_CLEANUP_FUNC, func),
06872                                0);
06873 }
06874 
06875 void
06876 ACE_OS_Object_Manager::print_error_message (u_int line_number,
06877                                             const ACE_TCHAR *message)
06878 {
06879   // To avoid duplication of these const strings in OS.o.
06880 #if !defined (ACE_HAS_WINCE)
06881   fprintf (stderr, "ace/OS.cpp, line %u: %s ",
06882            line_number,
06883            message);
06884   perror ("failed");
06885 #else
06886   // @@ Need to use the following information.
06887   ACE_UNUSED_ARG (line_number);
06888   ACE_UNUSED_ARG (message);
06889 
06890   ACE_TCHAR *lpMsgBuf = 0;
06891   ::FormatMessage (FORMAT_MESSAGE_ALLOCATE_BUFFER |
06892                    FORMAT_MESSAGE_FROM_SYSTEM,
06893                    0,
06894                    ::GetLastError (),
06895                    MAKELANGID (LANG_NEUTRAL,
06896                                SUBLANG_DEFAULT),
06897                    // Default language
06898                    (ACE_TCHAR *) &lpMsgBuf,
06899                    0,
06900                    0);
06901   ::MessageBox (NULL,
06902                 lpMsgBuf,
06903                 ACE_LIB_TEXT ("ACE_OS error"),
06904                 MB_OK);
06905 #endif
06906 }
06907 
06908 int
06909 ACE_OS_Object_Manager::starting_up (void)
06910 {
06911   return ACE_OS_Object_Manager::instance_
06912     ? instance_->starting_up_i ()
06913     : 1;
06914 }
06915 
06916 int
06917 ACE_OS_Object_Manager::shutting_down (void)
06918 {
06919   return ACE_OS_Object_Manager::instance_
06920     ? instance_->shutting_down_i ()
06921     : 1;
06922 }
06923 
06924 #if !defined (ACE_HAS_NONSTATIC_OBJECT_MANAGER)
06925 /**
06926  * @class ACE_OS_Object_Manager_Manager
06927  *
06928  * @brief Ensure that the <ACE_OS_Object_Manager> gets initialized at
06929  * program startup, and destroyed at program termination.
06930  *
06931  * Without ACE_HAS_NONSTATIC_OBJECT_MANAGER, a static instance of this
06932  * class is created.  Therefore, it gets created before main ()
06933  * is called.  And it gets destroyed after main () returns.
06934  */
06935 class ACE_OS_Object_Manager_Manager
06936 {
06937 public:
06938   /// Constructor.
06939   ACE_OS_Object_Manager_Manager (void);
06940 
06941   /// Destructor.
06942   ~ACE_OS_Object_Manager_Manager (void);
06943 
06944 private:
06945   /// Save the main thread ID, so that destruction can be suppressed.
06946   ACE_thread_t saved_main_thread_id_;
06947 };
06948 
06949 ACE_OS_Object_Manager_Manager::ACE_OS_Object_Manager_Manager (void)
06950   : saved_main_thread_id_ (ACE_OS::thr_self ())
06951 {
06952   // Ensure that the Object_Manager gets initialized before any
06953   // application threads have been spawned.  Because this will be called
06954   // during construction of static objects, that should always be the
06955   // case.
06956   (void) ACE_OS_Object_Manager::instance ();
06957 }
06958 
06959 ACE_OS_Object_Manager_Manager::~ACE_OS_Object_Manager_Manager (void)
06960 {
06961   if (ACE_OS::thr_equal (ACE_OS::thr_self (),
06962                          saved_main_thread_id_))
06963     {
06964       delete ACE_OS_Object_Manager::instance_;
06965       ACE_OS_Object_Manager::instance_ = 0;
06966     }
06967   // else if this destructor is not called by the main thread, then do
06968   // not delete the ACE_OS_Object_Manager.  That causes problems, on
06969   // WIN32 at least.
06970 }
06971 
06972 static ACE_OS_Object_Manager_Manager ACE_OS_Object_Manager_Manager_instance;
06973 #endif /* ! ACE_HAS_NONSTATIC_OBJECT_MANAGER */
06974 
06975 # if defined (ACE_HAS_WINCE)
06976 ACE_CE_ARGV::ACE_CE_ARGV(ACE_TCHAR* cmdLine)
06977 : ce_argv_(0)
06978 , ce_argc_(0)
06979 {
06980   // Note: ACE has argv parser and processor; however, they cannot be
06981   // used because of dependency.  ACE_OS is now separate from ACE, and
06982   // ACE depends on ACE_OS. Still, using all this array and complicated
06983   // pointer manipulation should be considered to be replaced and use STL
06984   // (or something) for better readability and code management.  Also,
06985   // string_to_argv() does not work well for CE argv because of incorrect
06986   // '"' identification.
06987   const ACE_TCHAR* dummyArgv = ACE_TEXT("root");  // dummy for the first argv
06988   const ACE_TCHAR* separator = ACE_TEXT(" ");     // blank space is a separator
06989 
06990   int formattedCmdLineLength =
06991     ACE_OS::strlen(dummyArgv) + ACE_OS::strlen(separator) + 1;  // for 0 term.
06992   if (ACE_OS::strlen(cmdLine) > 0)
06993     {
06994       formattedCmdLineLength += ACE_OS::strlen(cmdLine);
06995       formattedCmdLineLength += ACE_OS::strlen(separator);
06996     }
06997 
06998   // formattedCmdLine will have dummyArgv and a separator at the beginning
06999   // of cmdLine and a separator at the end to generalize format and reduce
07000   // the amount of code.
07001   ACE_TCHAR* formattedCmdLine = 0;
07002   ACE_NEW(formattedCmdLine, ACE_TCHAR[formattedCmdLineLength]);
07003 
07004   ACE_OS::strcpy(formattedCmdLine, dummyArgv);
07005   ACE_OS::strcat(formattedCmdLine, separator);
07006 
07007   // start with 1 because of the dummyArgv at the beginning
07008   int max_possible_argc = 1;
07009   if (ACE_OS::strlen(cmdLine) > 0)
07010     {
07011       int formattedPos  = ACE_OS::strlen(formattedCmdLine);
07012       int cmdLineLength = ACE_OS::strlen(cmdLine);
07013 
07014       // Inside of this for loop, it does same thing as strcat except it
07015       // checks and puts only one single white space between two argv entries.
07016       for (int i = 0; i < cmdLineLength; ++i)
07017         {
07018           if (iswspace(cmdLine[i]) != 0)
07019             ++max_possible_argc;  // counting the number of white spaces
07020 
07021           formattedCmdLine[formattedPos++] = cmdLine[i];
07022 
07023           if (iswspace(cmdLine[i]) != 0)
07024             {
07025               // make sure there is only one white space between two
07026               // argv entries.
07027               while ((i < cmdLineLength) && (iswspace(cmdLine[i + 1]) != 0))
07028                 ++i;
07029             }
07030         }
07031 
07032       formattedCmdLine[formattedPos] = 0;
07033       // make sure formattedCmdLine ends with a blank
07034       ACE_OS::strcat (formattedCmdLine, separator);
07035     }
07036 
07037   int formattedCmdLength = ACE_OS::strlen(formattedCmdLine);
07038 
07039   int insideQuotation = 0;
07040   int* argv_strlen = 0;
07041   int entry_size = 0;
07042   ACE_NEW (argv_strlen, int[max_possible_argc]);
07043 
07044   // determine argc
07045   for (int i = 0; i < formattedCmdLength; ++i)
07046     {
07047       if (formattedCmdLine[i] == '\\')
07048         {
07049           ++i; // ignore the following character
07050           ++entry_size;
07051         }
07052       else if (formattedCmdLine[i] == '"')
07053         {
07054           insideQuotation = (insideQuotation ? 0 : 1);
07055         }
07056       else if ((!insideQuotation) && (iswspace(formattedCmdLine[i]) != 0))
07057         {
07058           // new argv entry end found
07059           argv_strlen[ce_argc_++] = entry_size;  // cache this entry size
07060           entry_size = 0;
07061         }
07062       else
07063         {
07064           ++entry_size;
07065         }
07066     }
07067 
07068     ACE_NEW (ce_argv_, ACE_TCHAR*[ce_argc_ + 1]);
07069     ce_argv_[ce_argc_] = 0;  // Last command line entry is a NULL.
07070 
07071     for (int j = 0, cmdLinePos = 0; j < ce_argc_; ++j, ++cmdLinePos)
07072       {
07073         int length = argv_strlen[j];
07074 
07075         ACE_NEW (ce_argv_[j], ACE_TCHAR[length + 1]);
07076         ce_argv_[j][length] = 0;  // string termination null
07077 
07078         if (iswspace (formattedCmdLine[cmdLinePos]) != 0)
07079           {
07080             // This is where prior argv has trailing '"' at the end.
07081             ++cmdLinePos;
07082           }
07083 
07084         for (int n = 0; n < length; ++n, ++cmdLinePos)
07085           {
07086             if ((formattedCmdLine[cmdLinePos] == '\\') ||
07087                 (formattedCmdLine[cmdLinePos] == '"')     )
07088               {
07089                 ++cmdLinePos;
07090               }
07091 
07092             ce_argv_[j][n] = formattedCmdLine[cmdLinePos];
07093           }
07094       }
07095 
07096     delete argv_strlen;
07097     delete formattedCmdLine;
07098 }
07099 
07100 ACE_CE_ARGV::~ACE_CE_ARGV(void)
07101 {
07102     for (int i = 0; i < ce_argc_; ++i)
07103       delete [] ce_argv_[i];
07104 
07105     delete [] ce_argv_;
07106 }
07107 # endif // ACE_HAS_WINCE
07108 
07109 // You may be asking yourself, why are we doing this?  Well, in winbase.h,
07110 // MS didn't follow their normal Api_FunctionA and Api_FunctionW style,
07111 // so we have to #undef their define to get access to the unicode version.
07112 // And because we don't want to #undef this for the users code, we keep
07113 // this method in the .cpp file.
07114 #if defined (ACE_WIN32) && defined (UNICODE) && !defined (ACE_USES_TCHAR)
07115 #undef GetEnvironmentStrings
07116 #endif /* ACE_WIN32 && UNICODE !ACE_USES_TCHAR */
07117 
07118 ACE_TCHAR *
07119 ACE_OS::getenvstrings (void)
07120 {
07121 #if defined (ACE_LACKS_ENV)
07122   ACE_NOTSUP_RETURN (0);
07123 #elif defined (ACE_WIN32)
07124 # if defined (ACE_USES_WCHAR)
07125   return ::GetEnvironmentStringsW ();
07126 # else /* ACE_USES_WCHAR */
07127   return ::GetEnvironmentStrings ();
07128 # endif /* ACE_USES_WCHAR */
07129 #else /* ACE_WIN32 */
07130   ACE_NOTSUP_RETURN (0);
07131 #endif /* ACE_WIN32 */
07132 }
07133 
07134 #if defined (ACE_HAS_STRPTIME)
07135 char *
07136 ACE_OS::strptime (char *buf, const char *format, struct tm *tm)
07137 {
07138 #if !defined (ACE_HAS_WINCE)
07139 #if defined (ACE_LACKS_NATIVE_STRPTIME)
07140   int bi = 0;
07141   int fi = 0;
07142   int percent = 0;
07143 
07144   if (!buf || !format)
07145     return 0;
07146 
07147   while (format[fi] != '\0')
07148     {
07149       if (percent)
07150         {
07151           percent = 0;
07152           switch (format[fi])
07153             {
07154             case '%':                        // an escaped %
07155               if (buf[bi] == '%')
07156                 {
07157                   fi++; bi++;
07158                 }
07159               else
07160                 return buf + bi;
07161               break;
07162 
07163               /* not supported yet: weekday via locale long/short names
07164                  case 'a':                        / * weekday via locale * /
07165                  / * FALL THROUGH * /
07166                  case 'A':                        / * long/short names * /
07167                  break;
07168                  */
07169 
07170               /* not supported yet:
07171                  case 'b':                        / * month via locale * /
07172                  / * FALL THROUGH * /
07173                  case 'B':                        / * long/short names * /
07174                  / * FALL THROUGH * /
07175                  case 'h':
07176                  break;
07177                  */
07178 
07179               /* not supported yet:
07180                  case 'c':                        / * %x %X * /
07181                  break;
07182                  */
07183 
07184               /* not supported yet:
07185                  case 'C':                        / * date & time -  * /
07186                  / * locale long format * /
07187                  break;
07188                  */
07189 
07190             case 'd':                        /* day of month (1-31) */
07191               /* FALL THROUGH */
07192             case 'e':
07193               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31))
07194                 return buf + bi;
07195 
07196               break;
07197 
07198             case 'D':                        /* %m/%d/%y */
07199               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12))
07200                 return buf + bi;
07201 
07202               fi--;
07203               tm->tm_mon--;
07204 
07205               if (buf[bi] != '/')
07206                 return buf + bi;
07207 
07208               bi++;
07209 
07210               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mday, &bi, &fi, 1, 31))
07211                 return buf + bi;
07212 
07213               fi--;
07214               if (buf[bi] != '/')
07215                 return buf + bi;
07216               bi++;
07217               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 99))
07218                 return buf + bi;
07219               if (tm->tm_year < 69)
07220                 tm->tm_year += 100;
07221               break;
07222 
07223             case 'H':                        /* hour (0-23) */
07224               /* FALL THROUGH */
07225             case 'k':
07226               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
07227                 return buf + bi;
07228               break;
07229 
07230               /* not supported yet:
07231                  case 'I':                        / * hour (0-12) * /
07232                  / * FALL THROUGH * /
07233                  case 'l':
07234                  break;
07235                  */
07236 
07237             case 'j':                        /* day of year (0-366) */
07238               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_yday, &bi, &fi, 1, 366))
07239                 return buf + bi;
07240 
07241               tm->tm_yday--;
07242               break;
07243 
07244             case 'm':                        /* an escaped % */
07245               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_mon, &bi, &fi, 1, 12))
07246                 return buf + bi;
07247 
07248               tm->tm_mon--;
07249               break;
07250 
07251             case 'M':                        /* minute (0-59) */
07252               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
07253                 return buf + bi;
07254 
07255               break;
07256 
07257               /* not supported yet:
07258                  case 'p':                        / * am or pm for locale * /
07259                  break;
07260                  */
07261 
07262               /* not supported yet:
07263                  case 'r':                        / * %I:%M:%S %p * /
07264                  break;
07265                  */
07266 
07267             case 'R':                        /* %H:%M */
07268               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
07269                 return buf + bi;
07270 
07271               fi--;
07272               if (buf[bi] != ':')
07273                 return buf + bi;
07274               bi++;
07275               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
07276                 return buf + bi;
07277 
07278               break;
07279 
07280             case 'S':                        /* seconds (0-61) */
07281               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61))
07282                 return buf + bi;
07283               break;
07284 
07285             case 'T':                        /* %H:%M:%S */
07286               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_hour, &bi, &fi, 0, 23))
07287                 return buf + bi;
07288 
07289               fi--;
07290               if (buf[bi] != ':')
07291                 return buf + bi;
07292               bi++;
07293               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_min, &bi, &fi, 0, 59))
07294                 return buf + bi;
07295 
07296               fi--;
07297               if (buf[bi] != ':')
07298                 return buf + bi;
07299               bi++;
07300               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_sec, &bi, &fi, 0, 61))
07301                 return buf + bi;
07302 
07303               break;
07304 
07305             case 'w':                        /* day of week (0=Sun-6) */
07306               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_wday, &bi, &fi, 0, 6))
07307                 return buf + bi;
07308 
07309               break;
07310 
07311               /* not supported yet: date, based on locale
07312                  case 'x':                        / * date, based on locale * /
07313                  break;
07314                  */
07315 
07316               /* not supported yet:
07317                  case 'X':                        / * time, based on locale * /
07318                  break;
07319                  */
07320 
07321             case 'y':                        /* the year - 1900 (0-99) */
07322               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 99))
07323                 return buf + bi;
07324 
07325               if (tm->tm_year < 69)
07326                 tm->tm_year += 100;
07327               break;
07328 
07329             case 'Y':                        /* the full year (1999) */
07330               if (!ACE_OS::strptime_getnum (buf + bi, &tm->tm_year, &bi, &fi, 0, 0))
07331                 return buf + bi;
07332 
07333               tm->tm_year -= 1900;
07334               break;
07335 
07336             default:                        /* unrecognised */
07337               return buf + bi;
07338             } /* switch (format[fi]) */
07339 
07340         }
07341       else
07342         { /* if (percent) */
07343           if (format[fi] == '%')
07344             {
07345               percent = 1;
07346               fi++;
07347             }
07348           else
07349             {
07350               if (format[fi] == buf[bi])
07351                 {
07352                   fi++;
07353                   bi++;
07354                 }
07355               else
07356                 return buf + bi;
07357             }
07358         } /* if (percent) */
07359     } /* while (format[fi] */
07360 
07361   return buf + bi;
07362 #else  /* ! ACE_LACKS_NATIVE_STRPTIME */
07363   return ::strptime (buf,
07364                      format,
07365                      tm);
07366 #endif /* ! ACE_LACKS_NATIVE_STRPTIME */
07367 #else /* ! ACE_HAS_WINCE */
07368   ACE_UNUSED_ARG (buf);
07369   ACE_UNUSED_ARG (format);
07370   ACE_UNUSED_ARG (tm);
07371 
07372   ACE_NOTSUP_RETURN (0);
07373 #endif /* ! ACE_HAS_WINCE */
07374 }
07375 
07376 # if defined (ACE_LACKS_NATIVE_STRPTIME)
07377 int
07378 ACE_OS::strptime_getnum (char *buf,
07379                          int *num,
07380                          int *bi,
07381                          int *fi,
07382                          int min,
07383                          int max)
07384 {
07385   int i = 0, tmp = 0;
07386 
07387   while (isdigit (buf[i]))
07388     {
07389       tmp = (tmp * 10) + (buf[i] - '0');
07390       if (max && (tmp > max))
07391         return 0;
07392       i++;
07393     }
07394 
07395   if (tmp < min)
07396     return 0;
07397   else if (i)
07398     {
07399       *num = tmp;
07400       (*fi)++;
07401       *bi += i;
07402       return 1;
07403     }
07404   else
07405     return 0;
07406 }
07407 # endif /* ACE_LACKS_NATIVE_STRPTIME */
07408 #endif /* ACE_HAS_STRPTIME */
07409 
07410 #if !defined (ACE_HAS_WINCE)
07411 ACE_HANDLE
07412 ACE_OS::accept (ACE_HANDLE handle,
07413                 struct sockaddr *addr,
07414                 int *addrlen,
07415                 const ACE_Accept_QoS_Params &qos_params)
07416 {
07417 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
07418   ACE_SOCKCALL_RETURN (::WSAAccept ((ACE_SOCKET) handle,
07419                                     addr,
07420                                     (ACE_SOCKET_LEN *) addrlen,
07421                                     (LPCONDITIONPROC) qos_params.qos_condition_callback (),
07422                                     qos_params.callback_data ()),
07423                        ACE_HANDLE,
07424                        ACE_INVALID_HANDLE);
07425 # else
07426   ACE_UNUSED_ARG (qos_params);
07427   return ACE_OS::accept (handle,
07428                          addr,
07429                          addrlen);
07430 # endif /* ACE_HAS_WINSOCK2 */
07431 }
07432 
07433 ACE_HANDLE
07434 ACE_OS::join_leaf (ACE_HANDLE socket,
07435                    const sockaddr *name,
07436                    int namelen,
07437                    const ACE_QoS_Params &qos_params)
07438 {
07439 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
07440 
07441   QOS qos;
07442   // Construct the WinSock2 QOS structure.
07443 
07444   qos.SendingFlowspec = *(qos_params.socket_qos ()->sending_flowspec ());
07445   qos.ReceivingFlowspec = *(qos_params.socket_qos ()->receiving_flowspec ());
07446   qos.ProviderSpecific = (WSABUF) qos_params.socket_qos ()->provider_specific ();
07447 
07448   ACE_SOCKCALL_RETURN (::WSAJoinLeaf ((ACE_SOCKET) socket,
07449                                       name,
07450                                       namelen,
07451                                       (WSABUF *) qos_params.caller_data (),
07452                                       (WSABUF *) qos_params.callee_data (),
07453                                       &qos,
07454                                       (QOS *) qos_params.group_socket_qos (),
07455                                       qos_params.flags ()),
07456                        ACE_HANDLE,
07457                        ACE_INVALID_HANDLE);
07458 
07459 # else
07460   ACE_UNUSED_ARG (socket);
07461   ACE_UNUSED_ARG (name);
07462   ACE_UNUSED_ARG (namelen);
07463   ACE_UNUSED_ARG (qos_params);
07464   ACE_NOTSUP_RETURN (ACE_INVALID_HANDLE);
07465 # endif /* ACE_HAS_WINSOCK2 */
07466 }
07467 
07468 int
07469 ACE_OS::ioctl (ACE_HANDLE socket,
07470                u_long io_control_code,
07471                void *in_buffer_p,
07472                u_long in_buffer,
07473                void *out_buffer_p,
07474                u_long out_buffer,
07475                u_long *bytes_returned,
07476                ACE_OVERLAPPED *overlapped,
07477                ACE_OVERLAPPED_COMPLETION_FUNC func)
07478 {
07479 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
07480   ACE_SOCKCALL_RETURN (::WSAIoctl ((ACE_SOCKET) socket,
07481                                    io_control_code,
07482                                    in_buffer_p,
07483                                    in_buffer,
07484                                    out_buffer_p,
07485                                    out_buffer,
07486                                    bytes_returned,
07487                                    (WSAOVERLAPPED *) overlapped,
07488                                    func),
07489                        int,
07490                        SOCKET_ERROR);
07491 # else
07492   ACE_UNUSED_ARG (socket);
07493   ACE_UNUSED_ARG (io_control_code);
07494   ACE_UNUSED_ARG (in_buffer_p);
07495   ACE_UNUSED_ARG (in_buffer);
07496   ACE_UNUSED_ARG (out_buffer_p);
07497   ACE_UNUSED_ARG (out_buffer);
07498   ACE_UNUSED_ARG (bytes_returned);
07499   ACE_UNUSED_ARG (overlapped);
07500   ACE_UNUSED_ARG (func);
07501   ACE_NOTSUP_RETURN (-1);
07502 # endif /* ACE_HAS_WINSOCK2 */
07503 }
07504 
07505 
07506 int
07507 ACE_OS::ioctl (ACE_HANDLE socket,
07508                u_long io_control_code,
07509                ACE_QoS &ace_qos,
07510                u_long *bytes_returned,
07511                void *buffer_p,
07512                u_long buffer,
07513                ACE_OVERLAPPED *overlapped,
07514                ACE_OVERLAPPED_COMPLETION_FUNC func)
07515 {
07516 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
07517 
07518   QOS qos;
07519   u_long qos_len = sizeof (QOS);
07520 
07521   if (io_control_code == SIO_SET_QOS)
07522     {
07523       qos.SendingFlowspec = *(ace_qos.sending_flowspec ());
07524       qos.ReceivingFlowspec = *(ace_qos.receiving_flowspec ());
07525       qos.ProviderSpecific = (WSABUF) ace_qos.provider_specific ();
07526 
07527       qos_len += ace_qos.provider_specific ().iov_len;
07528 
07529       ACE_SOCKCALL_RETURN (::WSAIoctl ((ACE_SOCKET) socket,
07530                                        io_control_code,
07531                                        &qos,
07532                                        qos_len,
07533                                        buffer_p,
07534                                        buffer,
07535                                        bytes_returned,
07536                                        (WSAOVERLAPPED *) overlapped,
07537                                        func),
07538                            int,
07539                            SOCKET_ERROR);
07540     }
07541   else
07542     {
07543       u_long dwBufferLen = 0;
07544 
07545       // Query for the buffer size.
07546       int result = ::WSAIoctl ((ACE_SOCKET) socket,
07547                                 io_control_code,
07548                                 NULL,
07549                                 0,
07550                                 &dwBufferLen,
07551                                 sizeof (dwBufferLen),
07552                                 bytes_returned,
07553                                 NULL,
07554                                 NULL);
07555 
07556 
07557       if (result == SOCKET_ERROR)
07558           {
07559                 u_long dwErr = ::WSAGetLastError ();
07560 
07561                 if (dwErr == WSAEWOULDBLOCK)
07562                 {
07563                         errno = dwErr;
07564                         return -1;
07565                 }
07566                 else
07567                         if (dwErr != WSAENOBUFS)
07568                         {
07569                                 errno = dwErr;
07570                                 return -1;
07571                         }
07572           }
07573 
07574     char *qos_buf;
07575         ACE_NEW_RETURN (qos_buf,
07576                                         char [dwBufferLen],
07577                                         -1);
07578 
07579         QOS *qos = ACE_reinterpret_cast (QOS*,
07580                                                                          qos_buf);
07581 
07582         result = ::WSAIoctl ((ACE_SOCKET) socket,
07583                                    io_control_code,
07584                        NULL,
07585                        0,
07586                        qos,
07587                        dwBufferLen,
07588                        bytes_returned,
07589                        NULL,
07590                        NULL);
07591 
07592     if (result == SOCKET_ERROR)
07593                 return result;
07594 
07595     ACE_Flow_Spec sending_flowspec (qos->SendingFlowspec.TokenRate,
07596                                     qos->SendingFlowspec.TokenBucketSize,
07597                                     qos->SendingFlowspec.PeakBandwidth,
07598                                     qos->SendingFlowspec.Latency,
07599                                     qos->SendingFlowspec.DelayVariation,
07600 #  if defined(ACE_HAS_WINSOCK2_GQOS)
07601                                     qos->SendingFlowspec.ServiceType,
07602                                     qos->SendingFlowspec.MaxSduSize,
07603                                     qos->SendingFlowspec.MinimumPolicedSize,
07604 #  else /* ACE_HAS_WINSOCK2_GQOS */
07605                                     0,
07606                                     0,
07607                                     0,
07608 #  endif /* ACE_HAS_WINSOCK2_GQOS */
07609                                     0,
07610                                     0);
07611 
07612     ACE_Flow_Spec receiving_flowspec (qos->ReceivingFlowspec.TokenRate,
07613                                       qos->ReceivingFlowspec.TokenBucketSize,
07614                                       qos->ReceivingFlowspec.PeakBandwidth,
07615                                       qos->ReceivingFlowspec.Latency,
07616                                       qos->ReceivingFlowspec.DelayVariation,
07617 #  if defined(ACE_HAS_WINSOCK2_GQOS)
07618                                       qos->ReceivingFlowspec.ServiceType,
07619                                       qos->ReceivingFlowspec.MaxSduSize,
07620                                       qos->ReceivingFlowspec.MinimumPolicedSize,
07621 #  else /* ACE_HAS_WINSOCK2_GQOS */
07622                                       0,
07623                                       0,
07624                                       0,
07625 #  endif /* ACE_HAS_WINSOCK2_GQOS */
07626                                       0,
07627                                       0);
07628 
07629        ace_qos.sending_flowspec (&sending_flowspec);
07630        ace_qos.receiving_flowspec (&receiving_flowspec);
07631        ace_qos.provider_specific (*((struct iovec *) (&qos->ProviderSpecific)));
07632 
07633 
07634       return result;
07635     }
07636 
07637 # else
07638   ACE_UNUSED_ARG (socket);
07639   ACE_UNUSED_ARG (io_control_code);
07640   ACE_UNUSED_ARG (ace_qos);
07641   ACE_UNUSED_ARG (bytes_returned);
07642   ACE_UNUSED_ARG (buffer_p);
07643   ACE_UNUSED_ARG (buffer);
07644   ACE_UNUSED_ARG (overlapped);
07645   ACE_UNUSED_ARG (func);
07646   ACE_NOTSUP_RETURN (-1);
07647 # endif /* ACE_HAS_WINSOCK2 */
07648 }
07649 
07650 int
07651 ACE_OS::connect (ACE_HANDLE handle,
07652                  const sockaddr *addr,
07653                  int addrlen,
07654                  const ACE_QoS_Params &qos_params)
07655 {
07656   ACE_OS_TRACE ("ACE_OS::connect");
07657 # if defined (ACE_HAS_WINSOCK2) && (ACE_HAS_WINSOCK2 != 0)
07658   ACE_SOCKCALL_RETURN (::WSAConnect ((ACE_SOCKET) handle,
07659                                      (const sockaddr *) addr,
07660                                      (ACE_SOCKET_LEN) addrlen,
07661                                      (WSABUF *) qos_params.caller_data (),
07662                                      (WSABUF *) qos_params.callee_data (),
07663                                      (QOS *) qos_params.socket_qos (),
07664                                      (QOS *) qos_params.group_socket_qos ()),
07665                        int, -1);
07666 # else
07667   ACE_UNUSED_ARG (qos_params);
07668   return ACE_OS::connect (handle,
07669                           (sockaddr *) addr,
07670                           addrlen);
07671 # endif /* ACE_HAS_WINSOCK2 */
07672 }
07673 #endif  // ACE_HAS_WINCE
07674 
07675 long
07676 ACE_OS::num_processors (void)
07677 {
07678   ACE_OS_TRACE ("ACE_OS::num_processors");
07679 
07680 #if defined (ACE_WIN32) || defined (ACE_WIN64)
07681   SYSTEM_INFO sys_info;
07682   ::GetSystemInfo (&sys_info);
07683   return sys_info.dwNumberOfProcessors;
07684 #elif defined (linux) || defined (sun)
07685   return ::sysconf (_SC_NPROCESSORS_CONF);
07686 #else
07687   ACE_NOTSUP_RETURN (-1);
07688 #endif
07689 }
07690 
07691 long
07692 ACE_OS::num_processors_online (void)
07693 {
07694   ACE_OS_TRACE ("ACE_OS::num_processors_online");
07695 
07696 #if defined (ACE_WIN32) || defined (ACE_WIN64)
07697   SYSTEM_INFO sys_info;
07698   ::GetSystemInfo (&sys_info);
07699   return sys_info.dwNumberOfProcessors;
07700 #elif defined (linux) || defined (sun)
07701   return ::sysconf (_SC_NPROCESSORS_ONLN);
07702 #elif defined (__hpux)
07703   struct pst_dynamic psd;
07704   if (::pstat_getdynamic (&psd, sizeof (psd), (size_t) 1, 0) != -1)
07705     return psd.psd_proc_cnt;
07706   else
07707     return -1;
07708 #else
07709   ACE_NOTSUP_RETURN (-1);
07710 #endif
07711 }

Generated on Mon Jun 16 11:20:36 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002