ncbi_system.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:15k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: ncbi_system.cpp,v $
  4.  * PRODUCTION Revision 1000.3  2004/06/01 19:08:44  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.38
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: ncbi_system.cpp,v 1000.3 2004/06/01 19:08:44 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Authors:  Vladimir Ivanov, Denis Vakatov, Anton Lavrentiev
  35.  *
  36.  * File Description:  System functions
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbimtx.hpp>
  41. #include <corelib/ncbi_system.hpp>
  42. #if defined(NCBI_OS_MAC)
  43. #  include <OpenTransport.h>
  44. #endif
  45. #if defined(NCBI_OS_UNIX)
  46. #  include <sys/time.h>
  47. #  include <sys/resource.h>
  48. #  include <sys/times.h>
  49. #  include <limits.h>
  50. #  include <unistd.h>
  51. #  if defined(NCBI_OS_BSD) || defined(NCBI_OS_DARWIN)
  52. #    include <sys/sysctl.h>
  53. #  endif
  54. #  define USE_SETHEAPLIMIT
  55. #  define USE_SETCPULIMIT
  56. #endif
  57. #if defined(NCBI_OS_DARWIN)
  58. extern "C" {
  59. #  if defined(NCBI_COMPILER_MW_MSL)
  60. #    include <ncbi_mslextras.h>
  61. #  endif
  62. #  include <mach/mach.h>
  63. #  include <mach/mach_host.h>
  64. #  include <mach/host_info.h>
  65. }
  66. #endif
  67. #if defined(USE_SETCPULIMIT)
  68. #  include <signal.h>
  69. #endif
  70. BEGIN_NCBI_SCOPE
  71. // MIPSpro 7.3 workarounds:
  72. //   1) it declares set_new_handler() in both global and std:: namespaces;
  73. //   2) it apparently gets totally confused by `extern "C"' inside a namespace.
  74. #if defined(NCBI_COMPILER_MIPSPRO)
  75. #  define set_new_handler std::set_new_handler
  76. #else
  77. extern "C" {
  78.     static void s_ExitHandler(void);
  79.     static void s_SignalHandler(int sig);
  80. }
  81. #endif  /* NCBI_COMPILER_MIPSPRO */
  82. #ifdef NCBI_OS_UNIX
  83. DEFINE_STATIC_FAST_MUTEX(s_ExitHandler_Mutex);
  84. static bool                  s_ExitHandlerIsSet  = false;
  85. static ELimitsExitCode       s_ExitCode          = eLEC_None;
  86. static CTime                 s_TimeSet;
  87. static size_t                s_HeapLimit         = 0;
  88. static size_t                s_CpuTimeLimit      = 0;
  89. static char*                 s_ReserveMemory     = 0;
  90. static TLimitsPrintHandler   s_PrintHandler      = 0;
  91. static TLimitsPrintParameter s_PrintHandlerParam = 0;
  92. #if !defined(CLK_TCK)  &&  defined(CLOCKS_PER_SEC)
  93. #  define CLK_TCK CLOCKS_PER_SEC
  94. #endif
  95. // Routine to be called at the exit from application
  96. //
  97. static void s_ExitHandler(void)
  98. {
  99.     CFastMutexGuard LOCK(s_ExitHandler_Mutex);
  100.     // Free reserved memory
  101.     if ( s_ReserveMemory ) {
  102.         delete[] s_ReserveMemory;
  103.         s_ReserveMemory = 0;
  104.     }
  105.     // User defined dump
  106.     if ( s_PrintHandler ) {
  107.         size_t limit_size; 
  108.         switch ( s_ExitCode ) {
  109.         case eLEC_Memory: {
  110.             limit_size = s_HeapLimit;
  111.             break;
  112.         }
  113.         case eLEC_Cpu: {
  114.             limit_size = s_CpuTimeLimit;
  115.             break;
  116.         }
  117.         default:
  118.             return;
  119.         }
  120.         // Call user's print handler
  121.         (*s_PrintHandler)(s_ExitCode, limit_size, s_TimeSet, 
  122.                           s_PrintHandlerParam);
  123.         return;
  124.     }
  125.     // Standard dump
  126.     switch ( s_ExitCode ) {
  127.         
  128.     case eLEC_Memory:
  129.         {
  130.             ERR_POST("Memory heap limit exceeded in allocating memory " 
  131.                      "by operator new (" << s_HeapLimit << " bytes)");
  132.             break;
  133.         }
  134.         
  135.     case eLEC_Cpu: 
  136.         {
  137.             ERR_POST("CPU time limit exceeded (" << s_CpuTimeLimit << " sec)");
  138.             tms buffer;
  139.             if (times(&buffer) == (clock_t)(-1)) {
  140.                 ERR_POST("Error in getting CPU time consumed by program");
  141.                 break;
  142.             }
  143.             LOG_POST("tuser CPU time   : " << 
  144.                      buffer.tms_utime/CLK_TCK << " sec");
  145.             LOG_POST("tsystem CPU time : " << 
  146.                      buffer.tms_stime/CLK_TCK << " sec");
  147.             LOG_POST("ttotal CPU time  : " << 
  148.                      (buffer.tms_stime + buffer.tms_utime)/CLK_TCK << " sec");
  149.             break;
  150.         }
  151.     default:
  152.         return;
  153.     }
  154.     
  155.     // Write program's time
  156.     CTime ct(CTime::eCurrent);
  157.     CTime et(2000, 1, 1);
  158.     et.AddSecond((int) (ct.GetTimeT() - s_TimeSet.GetTimeT()));
  159.     LOG_POST("Program's time: " << Endm <<
  160.              "tstart limit - " << s_TimeSet.AsString() << Endm <<
  161.              "ttermination - " << ct.AsString() << Endm);
  162.     et.SetFormat("h:m:s");
  163.     LOG_POST("texecution   - " << et.AsString());
  164. }
  165. // Set routine to be called at the exit from application
  166. //
  167. static bool s_SetExitHandler(TLimitsPrintHandler handler, 
  168.                              TLimitsPrintParameter parameter)
  169. {
  170.     // Set exit routine if it not set yet
  171.     CFastMutexGuard LOCK(s_ExitHandler_Mutex);
  172.     if ( !s_ExitHandlerIsSet ) {
  173.         if (atexit(s_ExitHandler) != 0) {
  174.             return false;
  175.         }
  176.         s_ExitHandlerIsSet = true;
  177.         s_TimeSet.SetCurrent();
  178.         // Store print handler and parameter
  179.         s_PrintHandler = handler;
  180.         s_PrintHandlerParam = parameter;
  181.         // Reserve some memory (10Kb)
  182.         s_ReserveMemory = new char[10000];
  183.     }
  184.     return true;
  185. }
  186.     
  187. #endif /* NCBI_OS_UNIX */
  188. /////////////////////////////////////////////////////////////////////////////
  189. //
  190. // SetHeapLimit
  191. //
  192. #ifdef USE_SETHEAPLIMIT
  193. // Handler for operator new
  194. static void s_NewHandler(void)
  195. {
  196.     s_ExitCode = eLEC_Memory;
  197.     exit(-1);
  198. }
  199. bool SetHeapLimit(size_t max_heap_size,
  200.                   TLimitsPrintHandler handler, 
  201.                   TLimitsPrintParameter parameter)
  202. {
  203.     if (s_HeapLimit == max_heap_size) 
  204.         return true;
  205.     
  206.     if ( !s_SetExitHandler(handler, parameter) )
  207.         return false;
  208.     // Set new heap limit
  209.     CFastMutexGuard LOCK(s_ExitHandler_Mutex);
  210.     rlimit rl;
  211.     if ( max_heap_size ) {
  212.         set_new_handler(s_NewHandler);
  213.         rl.rlim_cur = rl.rlim_max = max_heap_size;
  214.     }
  215.     else {
  216.         // Set off heap limit
  217.         set_new_handler(0);
  218.         rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
  219.     }
  220.     if (setrlimit(RLIMIT_DATA, &rl) != 0) 
  221.         return false;
  222.     s_HeapLimit = max_heap_size;
  223.     return true;
  224. }
  225. #else
  226. bool SetHeapLimit(size_t max_heap_size, 
  227.                   TLimitsPrintHandler handler, 
  228.                   TLimitsPrintParameter parameter)
  229. {
  230.   return false;
  231. }
  232. #endif /* USE_SETHEAPLIMIT */
  233. /////////////////////////////////////////////////////////////////////////////
  234. //
  235. // SetCpuTimeLimit
  236. //
  237. #ifdef USE_SETCPULIMIT
  238. static void s_SignalHandler(int _DEBUG_ARG(sig))
  239. {
  240.     _ASSERT(sig == SIGXCPU);
  241.     _VERIFY(signal(SIGXCPU, SIG_IGN) != SIG_ERR);
  242.     s_ExitCode = eLEC_Cpu;
  243.     exit(-1);
  244. }
  245. bool SetCpuTimeLimit(size_t max_cpu_time,
  246.                      TLimitsPrintHandler handler, 
  247.                      TLimitsPrintParameter parameter)
  248. {
  249.     if (s_CpuTimeLimit == max_cpu_time) 
  250.         return true;
  251.     
  252.     if ( !s_SetExitHandler(handler, parameter) )
  253.         return false;
  254.     
  255.     // Set new CPU time limit
  256.     CFastMutexGuard LOCK(s_ExitHandler_Mutex);
  257.     struct rlimit rl;
  258.     if ( max_cpu_time ) {
  259.         rl.rlim_cur = rl.rlim_max = max_cpu_time;
  260.     }
  261.     else {
  262.         // Set off CPU time limit
  263.         rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
  264.     }
  265.     if (setrlimit(RLIMIT_CPU, &rl) != 0) {
  266.         return false;
  267.     }
  268.     s_CpuTimeLimit = max_cpu_time;
  269.     // Set signal handler for SIGXCPU
  270.     if (signal(SIGXCPU, s_SignalHandler) == SIG_ERR) {
  271.         return false;
  272.     }
  273.     return true;
  274. }
  275. #else
  276. bool SetCpuTimeLimit(size_t max_cpu_time,
  277.                   TLimitsPrintHandler handler, 
  278.                   TLimitsPrintParameter parameter)
  279. {
  280.     return false;
  281. }
  282. #endif /* USE_SETCPULIMIT */
  283. /////////////////////////////////////////////////////////////////////////////
  284. //
  285. // GetCpuCount
  286. //
  287. unsigned int GetCpuCount(void)
  288. {
  289. #if defined(NCBI_OS_MSWIN)
  290.     SYSTEM_INFO sysInfo;
  291.     GetSystemInfo(&sysInfo);
  292.     return (unsigned int) sysInfo.dwNumberOfProcessors;
  293. #elif defined(NCBI_OS_DARWIN)
  294.     host_basic_info_data_t hinfo;
  295.     mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
  296.     kern_return_t rc;
  297.     rc = host_info(mach_host_self(), HOST_BASIC_INFO,
  298.                    (host_info_t)&hinfo, &hinfo_count);
  299.     if (rc != KERN_SUCCESS) {
  300.         return 1;
  301.     }
  302.     return hinfo.avail_cpus;
  303. #elif defined(NCBI_OS_UNIX)
  304.     long nproc = 0;
  305. # if defined(_SC_NPROC_ONLN)
  306.     nproc = sysconf(_SC_NPROC_ONLN);
  307. # elif defined(_SC_NPROCESSORS_ONLN)
  308.     nproc = sysconf(_SC_NPROCESSORS_ONLN);
  309. # elif defined(NCBI_OS_BSD) || defined(NCBI_OS_DAWRIN)
  310.     size_t len = sizeof(nproc);
  311.     int mib[2];
  312.     mib[0] = CTL_HW;
  313.     mib[1] = HW_NCPU;
  314.     if (sysctl(mib, 2, &nproc, &len, 0, 0) < 0 || len != sizeof(nproc))
  315.         nproc = -1;
  316. # endif /*UNIX_FLAVOR*/
  317.     return nproc <= 0 ? 1 : (unsigned int) nproc;
  318. #else
  319.     return 1;
  320. #endif /*OS_TYPE*/
  321. }
  322. /////////////////////////////////////////////////////////////////////////////
  323. //
  324. // Sleep
  325. //
  326. void SleepMicroSec(unsigned long mc_sec)
  327. {
  328. #if defined(NCBI_OS_MSWIN)
  329.     Sleep(mc_sec / 1000);
  330. #elif defined(NCBI_OS_UNIX)
  331.     struct timeval delay;
  332.     delay.tv_sec  = mc_sec / kMicroSecondsPerSecond;
  333.     delay.tv_usec = mc_sec % kMicroSecondsPerSecond;
  334.     select(0, (fd_set*)NULL, (fd_set*)NULL, (fd_set*)NULL, &delay);
  335. #elif defined(NCBI_OS_MAC)
  336.     OTDelay(mc_sec / 1000);
  337. #endif
  338. }
  339. void SleepMilliSec(unsigned long ml_sec)
  340. {
  341. #if defined(NCBI_OS_MSWIN)
  342.     Sleep(ml_sec);
  343. #else
  344.     SleepMicroSec(ml_sec * kMilliSecondsPerSecond);
  345. #endif
  346. }
  347. void SleepSec(unsigned long sec)
  348. {
  349.     SleepMicroSec(sec * kMicroSecondsPerSecond);
  350. }
  351. END_NCBI_SCOPE
  352. /*
  353.  * ===========================================================================
  354.  * $Log: ncbi_system.cpp,v $
  355.  * Revision 1000.3  2004/06/01 19:08:44  gouriano
  356.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.38
  357.  *
  358.  * Revision 1.38  2004/05/18 17:57:21  ucko
  359.  * GetCpuCount(): return 1 rather than -1 (-> UINT_MAX !) if host_info
  360.  * fails on Darwin.
  361.  *
  362.  * Revision 1.37  2004/05/14 13:59:26  gorelenk
  363.  * Added include of ncbi_pch.hpp
  364.  *
  365.  * Revision 1.36  2004/02/11 18:06:28  lavr
  366.  * Fix typo (nrproc->nproc)
  367.  *
  368.  * Revision 1.35  2004/02/11 13:36:14  lavr
  369.  * Added code for figuring out CPU count on *BSD/Darwin
  370.  *
  371.  * Revision 1.34  2003/11/10 17:13:52  vakatov
  372.  * - #include <connect/ncbi_core.h>
  373.  *
  374.  * Revision 1.33  2003/09/25 16:54:07  ivanov
  375.  * CPIDGuard class moved to ncbi_process.cpp.
  376.  *
  377.  * Revision 1.32  2003/09/23 21:13:53  ucko
  378.  * +CPIDGuard::UpdatePID (code mostly factored out of constructor)
  379.  *
  380.  * Revision 1.31  2003/08/12 17:24:58  ucko
  381.  * Add support for PID files.
  382.  *
  383.  * Revision 1.30  2003/05/19 21:07:51  vakatov
  384.  * s_SignalHandler() -- get rid of "unused func arg" compilation warning
  385.  *
  386.  * Revision 1.29  2003/04/04 16:02:37  lavr
  387.  * Lines wrapped at 79th column; some minor reformatting
  388.  *
  389.  * Revision 1.28  2003/04/03 14:15:48  rsmith
  390.  * combine pp symbols NCBI_COMPILER_METROWERKS & _MSL_USING_MW_C_HEADERS
  391.  * into NCBI_COMPILER_MW_MSL
  392.  *
  393.  * Revision 1.27  2003/04/02 16:22:33  rsmith
  394.  * clean up metrowerks ifdefs.
  395.  *
  396.  * Revision 1.26  2003/04/02 13:29:29  rsmith
  397.  * include ncbi_mslextras.h when compiling with MSL libs in Codewarrior.
  398.  *
  399.  * Revision 1.25  2003/03/06 23:46:50  ucko
  400.  * Move extra NCBI_OS_DARWIN headers up with the rest, and surround them
  401.  * with extern "C" because they seem to lack it.
  402.  *
  403.  * Revision 1.24  2003/03/06 15:46:46  ivanov
  404.  * Added George Coulouris's GetCpuCount() implementation for NCBI_OS_DARWIN
  405.  *
  406.  * Revision 1.23  2002/09/19 20:05:42  vasilche
  407.  * Safe initialization of static mutexes
  408.  *
  409.  * Revision 1.22  2002/07/19 18:39:02  lebedev
  410.  * NCBI_OS_MAC: SleepMicroSec implementation added
  411.  *
  412.  * Revision 1.21  2002/07/16 13:37:48  ivanov
  413.  * Little modification and optimization of the Sleep* functions
  414.  *
  415.  * Revision 1.20  2002/07/15 21:43:04  ivanov
  416.  * Added functions SleepMicroSec, SleepMilliSec, SleepSec
  417.  *
  418.  * Revision 1.19  2002/04/11 21:08:00  ivanov
  419.  * CVS log moved to end of the file
  420.  *
  421.  * Revision 1.18  2002/04/01 18:52:49  ivanov
  422.  * Cosmetic changes
  423.  *
  424.  * Revision 1.17  2002/03/25 18:11:08  ucko
  425.  * Include <sys/time.h> before <sys/resource.h> for FreeBSD build.
  426.  *
  427.  * Revision 1.16  2001/12/09 06:27:39  vakatov
  428.  * GetCpuCount() -- get rid of warning (in 64-bit mode), change ret.val. type
  429.  *
  430.  * Revision 1.15  2001/11/16 16:39:58  ivanov
  431.  * Typo, fixed NCBI_OS_WIN -> NCBI_OS_MSWIN
  432.  *
  433.  * Revision 1.14  2001/11/16 16:34:34  ivanov
  434.  * Added including "windows.h" under MS Windows
  435.  *
  436.  * Revision 1.13  2001/11/09 16:22:16  ivanov
  437.  * Polish source code of GetCpuCount()
  438.  *
  439.  * Revision 1.12  2001/11/08 21:31:44  ivanov
  440.  * Renamed GetCPUNumber() -> GetCpuCount()
  441.  *
  442.  * Revision 1.11  2001/11/08 21:10:04  ivanov
  443.  * Added function GetCPUNumber()
  444.  *
  445.  * Revision 1.10  2001/09/10 17:15:51  grichenk
  446.  * Added definition of CLK_TCK (absent on some systems).
  447.  *
  448.  * Revision 1.9  2001/07/24 13:19:14  ivanov
  449.  * Remove semicolon after functions header (for NCBI_OS_WIN)
  450.  *
  451.  * Revision 1.8  2001/07/23 16:09:26  ivanov
  452.  * Added possibility using user defined dump print handler (fix comment)
  453.  *
  454.  * Revision 1.7  2001/07/23 15:23:58  ivanov
  455.  * Added possibility using user defined dump print handler
  456.  *
  457.  * Revision 1.6  2001/07/05 22:09:07  vakatov
  458.  * s_ExitHandler() -- do not printout the final statistics if the process
  459.  * has terminated "normally"
  460.  *
  461.  * Revision 1.5  2001/07/05 05:27:49  vakatov
  462.  * Get rid of the redundant <ncbireg.hpp>.
  463.  * Added workarounds for the capricious IRIX MIPSpro 7.3 compiler.
  464.  *
  465.  * Revision 1.4  2001/07/04 20:03:37  vakatov
  466.  * Added missing header <unistd.h>.
  467.  * Check for the exit code of the signal() function calls.
  468.  *
  469.  * Revision 1.3  2001/07/02 21:33:07  vakatov
  470.  * Fixed against SIGXCPU during the signal handling.
  471.  * Increase the amount of reserved memory for the memory limit handler
  472.  * to 10K (to fix for the 64-bit WorkShop compiler).
  473.  * Use standard C++ arg.processing (ncbiargs) in the test suite.
  474.  * Cleaned up the code. Get rid of the "Ncbi_" prefix.
  475.  *
  476.  * Revision 1.2  2001/07/02 18:45:14  ivanov
  477.  * Added #include <sys/resource.h> and extern "C" to handlers
  478.  *
  479.  * Revision 1.1  2001/07/02 16:45:35  ivanov
  480.  * Initialization
  481.  *
  482.  * ===========================================================================
  483.  */