NCBI C++ ToolKit
ncbi_system.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: ncbi_system.cpp 101756 2024-02-07 02:20:24Z lavr $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * Authors: Vladimir Ivanov, Denis Vakatov, Anton Lavrentiev
27  *
28  * File Description: System functions
29  *
30  */
31 
32 #include <ncbi_pch.hpp>
33 
34 #ifdef NCBI_OS_MSWIN
35 # include <windows.h>
36 # include <crtdbg.h>
37 # include <stdlib.h>
38 #endif //NCBI_OS_MSWIN
39 
40 #include <corelib/ncbimtx.hpp>
41 #include <corelib/ncbi_system.hpp>
43 #include <corelib/error_codes.hpp>
44 #include <corelib/ncbierror.hpp>
45 #include "ncbisys.hpp"
46 #include <array>
47 
48 #define NCBI_USE_ERRCODE_X Corelib_System
49 
50 #if defined(NCBI_OS_UNIX)
51 # include <sys/mman.h>
52 # if defined(NCBI_OS_SOLARIS)
53 # include <corelib/ncbifile.hpp>
54 # ifndef VALID_ATTR // correlated with madvise() prototype
55 extern "C" {
56  extern int madvise(caddr_t, size_t, int);
57 }
58 # endif
59 # endif //NCBI_OS_SOLARIS
60 # include <sys/time.h>
61 # include <sys/resource.h>
62 # include <sys/times.h>
63 # include <sys/types.h>
64 # include <dirent.h>
65 # include <limits.h>
66 # include <time.h>
67 # include <unistd.h>
68 # include <fcntl.h>
69 # if defined(NCBI_OS_BSD) || defined(NCBI_OS_DARWIN)
70 # include <sys/sysctl.h>
71 # endif //NCBI_OS_BSD || NCBI_OS_DARWIN
72 # if defined(NCBI_OS_IRIX)
73 # include <sys/sysmp.h>
74 # endif //NCBI_OS_IRIX
75 # include "ncbi_os_unix_p.hpp"
76 # define USE_SETMEMLIMIT
77 # define USE_SETCPULIMIT
78 # define HAVE_MADVISE 1
79 #endif //NCBI_OS_UNIX
80 
81 #if defined(NCBI_OS_LINUX)
82 # include <sched.h>
83 #endif
84 
85 #ifdef NCBI_OS_DARWIN
86 extern "C" {
87 # include <mach/mach.h>
88 # include <mach/mach_host.h>
89 # include <mach/host_info.h>
90 } /* extern "C" */
91 #endif //NCBI_OS_DARWIN
92 
93 #ifdef USE_SETCPULIMIT
94 # include <signal.h>
95 #endif //USE_SETCPULIMIT
96 
97 #ifdef NCBI_OS_MSWIN
98 # include <corelib/ncbidll.hpp>
99 # include "ncbi_os_mswin_p.hpp"
100 # include <dbghelp.h>
101 # include <intrin.h>
102 #endif //NCBI_OS_MSWIN
103 
104 
106 
107 
108 // MIPSpro 7.3 workarounds:
109 // 1) it declares set_new_handler() in both global and std:: namespaces;
110 // 2) it apparently gets totally confused by `extern "C"' inside a namespace.
111 #if defined(NCBI_COMPILER_MIPSPRO)
112 # define set_new_handler std::set_new_handler
113 #else
114 extern "C" {
115  static void s_ExitHandler(void);
116  [[noreturn]] static void s_SignalHandler(int sig);
117 }
118 #endif //NCBI_COMPILER_MIPSPRO
119 
120 
121 #ifdef NCBI_OS_UNIX
122 
123 DEFINE_STATIC_FAST_MUTEX(s_ExitHandler_Mutex);
124 static bool s_ExitHandlerIsSet = false;
127 static size_t s_MemoryLimitSoft = 0;
128 static size_t s_MemoryLimitHard = 0;
129 static size_t s_CpuTimeLimit = 0;
130 static char* s_ReserveMemory = 0;
133 
134 
135 #if !defined(CLK_TCK) && defined(CLOCKS_PER_SEC)
136 # define CLK_TCK CLOCKS_PER_SEC
137 #endif
138 
139 
140 // Routine to be called at the exit from application
141 // It is not async-safe, so using it with SetCpuLimits() can lead to coredump
142 // and program crash. Be aware.
143 //
144 static void s_ExitHandler(void)
145 {
146  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
147 
148  // Free reserved memory
149  if ( s_ReserveMemory ) {
150  delete[] s_ReserveMemory;
151  s_ReserveMemory = 0;
152  }
153 
154  // User defined dump
155  if ( s_PrintHandler ) {
156  size_t limit_size;
157 
158  switch ( s_ExitCode ) {
159  case eLEC_Memory: {
160  limit_size = s_MemoryLimitSoft;
161  break;
162  }
163  case eLEC_Cpu: {
164  limit_size = s_CpuTimeLimit;
165  break;
166  }
167  default:
168  return;
169  }
170  // Call user's print handler
171  (*s_PrintHandler)(s_ExitCode, limit_size, s_TimeSet.Get(),
173  return;
174  }
175 
176  // Standard dump
177  switch ( s_ExitCode ) {
178 
179  case eLEC_Memory:
180  {
181  ERR_POST_X(1, "Memory heap limit exceeded in allocating memory " \
182  "by operator new (" << s_MemoryLimitSoft << " bytes)");
183  break;
184  }
185 
186  case eLEC_Cpu:
187  {
188  ERR_POST_X(2, "CPU time limit exceeded (" << s_CpuTimeLimit << " sec)");
189  tms buffer;
190  if (times(&buffer) == (clock_t)(-1)) {
191  ERR_POST_X(3, "Error in getting CPU time consumed by program");
192  break;
193  }
194  clock_t tick = sysconf(_SC_CLK_TCK);
195 #if defined(CLK_TCK)
196  if (!tick || tick == (clock_t)(-1))
197  tick = CLK_TCK;
198 #elif defined(CLOCKS_PER_SEC)
199  if (!tick || tick == (clock_t)(-1))
200  tick = CLOCKS_PER_SEC;
201 #endif
202  if (tick == (clock_t)(-1))
203  tick = 0;
204  ERR_POST_X(4, Note << "\tuser CPU time : " <<
205  buffer.tms_utime/(tick ? tick : 1) <<
206  (tick ? " sec" : " tick"));
207  ERR_POST_X(5, Note << "\tsystem CPU time : " <<
208  buffer.tms_stime/(tick ? tick : 1) <<
209  (tick ? " sec" : " tick"));
210  ERR_POST_X(6, Note << "\ttotal CPU time : " <<
211  (buffer.tms_stime + buffer.tms_utime)/(tick ? tick : 1) <<
212  (tick ? " sec" : " tick"));
213  break;
214  }
215 
216  default:
217  return;
218  }
219 
220  // Write program's time
222  CTime et(2000, 1, 1);
223  et.AddSecond((int) (ct.GetTimeT() - s_TimeSet->GetTimeT()));
224  ERR_POST_X(7, Note << "Program's time: " << Endm <<
225  "\tstart limit - " << s_TimeSet->AsString() << Endm <<
226  "\ttermination - " << ct.AsString() << Endm);
227  et.SetFormat("h:m:s");
228  ERR_POST_X(8, Note << "\texecution - " << et.AsString());
229 }
230 
231 
232 // Set routine to be called at the exit from application
233 //
235  TLimitsPrintParameter parameter)
236 
237 {
238  // Set exit routine if it not set yet
239  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
240  if ( !s_ExitHandlerIsSet ) {
241  if (atexit(s_ExitHandler) != 0) {
242  return false;
243  }
244  s_ExitHandlerIsSet = true;
245  s_TimeSet->SetCurrent();
246 
247  // Store new print handler and its parameter
249  s_PrintHandlerParam = parameter;
250 
251  // Reserve some memory (10Kb) to allow the diagnostic API
252  // print messages on exit if memory limit is set.
253  s_ReserveMemory = new char[10*1024];
254  }
255  return true;
256 }
257 
258 #endif //NCBI_OS_UNIX
259 
260 
261 
262 /////////////////////////////////////////////////////////////////////////////
263 //
264 // Memory limits
265 //
266 
267 #ifdef USE_SETMEMLIMIT
268 
269 // Handler for operator new
270 [[noreturn]] static void s_NewHandler(void)
271 {
273  // _exit() does not go over atexit() chain, so just call registered
274  // handler directly.
275  if (s_ExitHandlerIsSet) {
276  s_ExitHandler();
277  }
278  _exit(-1);
279 }
280 
281 
282 bool SetMemoryLimit(size_t max_size,
284  TLimitsPrintParameter parameter)
285 {
286  if (s_MemoryLimitSoft == max_size) {
287  return true;
288  }
289  if (!s_SetExitHandler(handler, parameter)) {
290  return false;
291  }
292  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
293 
294  rlimit rl;
295  if ( max_size ) {
296  set_new_handler(s_NewHandler);
297  rl.rlim_cur = rl.rlim_max = max_size;
298  } else {
299  set_new_handler(0);
300  rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
301  }
302  if (setrlimit(RLIMIT_DATA, &rl) != 0) {
304  return false;
305  }
306 # if !defined(NCBI_OS_SOLARIS)
307  if (setrlimit(RLIMIT_AS, &rl) != 0) {
309  return false;
310  }
311 # endif //NCBI_OS_SOLARIS
312 
313  s_MemoryLimitSoft = max_size;
314  s_MemoryLimitHard = max_size;
315  if ( max_size ) {
316  set_new_handler(s_NewHandler);
317  } else {
318  set_new_handler(0);
319  }
320  return true;
321 }
322 
323 
324 bool SetMemoryLimitSoft(size_t max_size,
326  TLimitsPrintParameter parameter)
327 {
328  if (s_MemoryLimitSoft == max_size) {
329  return true;
330  }
331  if (!s_SetExitHandler(handler, parameter)) {
332  return false;
333  }
334  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
335 
336  rlimit rl;
337  if (getrlimit(RLIMIT_DATA, &rl) != 0) {
339  return false;
340  }
341  if ( max_size ) {
342  rl.rlim_cur = max_size;
343  } else {
344  rl.rlim_cur = RLIM_INFINITY;
345  }
346  if (setrlimit(RLIMIT_DATA, &rl) != 0) {
348  return false;
349  }
350 # if !defined(NCBI_OS_SOLARIS)
351  rlimit rlas;
352  if (getrlimit(RLIMIT_AS, &rlas) != 0) {
354  return false;
355  }
356  rl.rlim_max = rlas.rlim_max;
357  if (setrlimit(RLIMIT_AS, &rl) != 0) {
359  return false;
360  }
361 # endif //NCBI_OS_SOLARIS
362 
363  s_MemoryLimitSoft = max_size;
364  if ( max_size ) {
365  set_new_handler(s_NewHandler);
366  } else {
367  set_new_handler(0);
368  }
369  return true;
370 }
371 
372 
373 bool SetMemoryLimitHard(size_t max_size,
375  TLimitsPrintParameter parameter)
376 {
377  if (s_MemoryLimitHard == max_size) {
378  return true;
379  }
380  if (!s_SetExitHandler(handler, parameter)) {
381  return false;
382  }
383  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
384 
385  size_t cur_soft_limit = 0;
386  rlimit rl;
387  if (getrlimit(RLIMIT_DATA, &rl) != 0) {
389  return false;
390  }
391  if ( max_size ) {
392  rl.rlim_max = max_size;
393  if (rl.rlim_cur > max_size) {
394  rl.rlim_cur = max_size;
395  }
396  cur_soft_limit = rl.rlim_cur;
397  } else {
398  rl.rlim_max = RLIM_INFINITY;
399  }
400  if (setrlimit(RLIMIT_DATA, &rl) != 0) {
402  return false;
403  }
404 # if !defined(NCBI_OS_SOLARIS)
405  rlimit rlas;
406  if (getrlimit(RLIMIT_AS, &rlas) != 0) {
408  return false;
409  }
410  if ( max_size ) {
411  rlas.rlim_max = max_size;
412  // Decrease current soft limit of the virtual memory
413  // to the size of data segment -- min(DATA,AS).
414  if (rlas.rlim_cur > cur_soft_limit) {
415  rlas.rlim_cur = cur_soft_limit;
416  }
417  // And use this size as current value for the soft limit
418  // in the print handler
419  cur_soft_limit = rlas.rlim_cur;
420  } else {
421  rlas.rlim_max = RLIM_INFINITY;
422  }
423  if (setrlimit(RLIMIT_AS, &rlas) != 0) {
425  return false;
426  }
427 # endif //NCBI_OS_SOLARIS
428 
429  s_MemoryLimitSoft = cur_soft_limit;
430  s_MemoryLimitHard = max_size;
431  if ( max_size ) {
432  set_new_handler(s_NewHandler);
433  } else {
434  set_new_handler(0);
435  }
436  return true;
437 }
438 
439 
440 // @deprecated
441 bool SetHeapLimit(size_t max_size,
443  TLimitsPrintParameter parameter)
444 {
445  if (s_MemoryLimitSoft == max_size) {
446  return true;
447  }
448  if (!s_SetExitHandler(handler, parameter)) {
449  return false;
450  }
451  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
452 
453  rlimit rl;
454  if ( max_size ) {
455  rl.rlim_cur = rl.rlim_max = max_size;
456  } else {
457  rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
458  }
459  if (setrlimit(RLIMIT_DATA, &rl) != 0) {
461  return false;
462  }
463  s_MemoryLimitSoft = max_size;
464  if ( max_size ) {
465  set_new_handler(s_NewHandler);
466  } else {
467  set_new_handler(0);
468  }
469  return true;
470 }
471 
472 
474 {
475  // Query limits from kernel, s_MemoryLimit* values can not reflect real limits.
476  rlimit rl = {0,0};
477 # if !defined(NCBI_OS_SOLARIS)
478  if (getrlimit(RLIMIT_AS, &rl) != 0) {
480  return 0;
481  }
482  if (rl.rlim_cur == RLIM_INFINITY) {
483  return 0;
484  }
485 #else
487 #endif
488  return rl.rlim_cur;
489 }
490 
491 
493 {
494  // Query limits from kernel, s_MemoryLimit* values can not reflect real limits.
495  rlimit rl = {0,0};
496 # if !defined(NCBI_OS_SOLARIS)
497  if (getrlimit(RLIMIT_AS, &rl) != 0) {
499  return 0;
500  }
501  if (rl.rlim_max == RLIM_INFINITY) {
502  return 0;
503  }
504 #else
506 #endif
507  return rl.rlim_max;
508 }
509 
510 
511 #else
512 
513 bool SetMemoryLimit(size_t max_size,
515  TLimitsPrintParameter parameter)
516 {
518  return false;
519 }
520 
521 bool SetMemoryLimitSoft(size_t max_size,
523  TLimitsPrintParameter parameter)
524 {
526  return false;
527 }
528 
529 bool SetMemoryLimitHard(size_t max_size,
531  TLimitsPrintParameter parameter)
532 {
534  return false;
535 }
536 
537 bool SetHeapLimit(size_t max_size,
539  TLimitsPrintParameter parameter)
540 {
542  return false;
543 }
544 
545 size_t GetVirtualMemoryLimitSoft(void)
546 {
548  return 0;
549 }
550 
551 size_t GetVirtualMemoryLimitHard(void)
552 {
554  return 0;
555 }
556 
557 #endif //USE_SETMEMLIMIT
558 
559 
560 
561 /////////////////////////////////////////////////////////////////////////////
562 //
563 // SetCpuTimeLimit
564 //
565 
566 #ifdef USE_SETCPULIMIT
567 
568 [[noreturn]] static void s_SignalHandler(int _DEBUG_ARG(sig))
569 {
570  _ASSERT(sig == SIGXCPU);
571  _VERIFY(signal(SIGXCPU, SIG_IGN) != SIG_ERR);
573  // _exit() does not go over atexit() chain, so just call registered
574  // handler directly. Be aware that it should be async-safe!
575  if (s_ExitHandlerIsSet) {
576  s_ExitHandler();
577  }
578  _exit(-1);
579 }
580 
581 bool SetCpuTimeLimit(unsigned int max_cpu_time,
582  unsigned int terminate_delay_time,
584  TLimitsPrintParameter parameter)
585 {
586  if (s_CpuTimeLimit == max_cpu_time) {
587  return true;
588  }
589  if (!s_SetExitHandler(handler, parameter)) {
590  return false;
591  }
592  CFastMutexGuard LOCK(s_ExitHandler_Mutex);
593 
594  rlimit rl;
595  if ( max_cpu_time ) {
596  rl.rlim_cur = max_cpu_time;
597  rl.rlim_max = max_cpu_time + terminate_delay_time;
598  } else {
599  rl.rlim_cur = rl.rlim_max = RLIM_INFINITY;
600  }
601  if (setrlimit(RLIMIT_CPU, &rl) != 0) {
602  return false;
603  }
604  s_CpuTimeLimit = max_cpu_time;
605 
606  // Set signal handler for SIGXCPU
607  if (signal(SIGXCPU, s_SignalHandler) == SIG_ERR) {
608  return false;
609  }
610 
611  return true;
612 }
613 
614 #else
615 
616 bool SetCpuTimeLimit(unsigned int max_cpu_time,
617  unsigned int terminate_delay_time,
619  TLimitsPrintParameter parameter)
620 {
621  return false;
622 }
623 
624 #endif //USE_SETCPULIMIT
625 
626 
627 // @deprecated
628 bool SetCpuTimeLimit(size_t max_cpu_time,
630  TLimitsPrintParameter parameter,
631  size_t terminate_delay_time)
632 {
633  return SetCpuTimeLimit((unsigned int)max_cpu_time,
634  (unsigned int)terminate_delay_time,
635  handler, parameter);
636 }
637 
638 
639 
640 /////////////////////////////////////////////////////////////////////////////
641 //
642 // System information
643 //
644 
645 
647 {
648 #if defined(NCBI_OS_UNIX)
649  return CUnixFeature::GetUserNameByUID(geteuid());
650 #elif defined(NCBI_OS_MSWIN)
651  return CWinSecurity::GetUserName();
652 #else
653  return string();
654 #endif
655 }
656 
657 
658 unsigned int CSystemInfo::GetCpuCount(void)
659 {
660  static unsigned int cpu = 0;
661  if (!cpu) {
662 #if defined(NCBI_OS_MSWIN)
663  SYSTEM_INFO si;
664  GetSystemInfo(&si);
665  cpu = (unsigned int)si.dwNumberOfProcessors;
666 
667 #elif defined(NCBI_OS_DARWIN)
668  host_basic_info_data_t hinfo;
669  mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
670  kern_return_t rc;
671  rc = host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hinfo, &hinfo_count);
672  if (rc == KERN_SUCCESS) {
673  cpu = hinfo.avail_cpus;
674  }
675 
676 #elif defined(NCBI_OS_UNIX)
677  long x = 0;
678  #if defined(_SC_NPROC_ONLN)
679  x = sysconf(_SC_NPROC_ONLN);
680  #elif defined(_SC_NPROCESSORS_ONLN)
681  x = sysconf(_SC_NPROCESSORS_ONLN);
682  #elif defined(NCBI_OS_BSD) /*|| defined(NCBI_OS_DAWRIN)*/
683  int v;
684  size_t len = sizeof(v);
685  int mib[2] = { CTL_HW, HW_NCPU };
686  if (sysctl(mib, 2, &v, &len, NULL, 0) == 0) {
687  x = v;
688  }
689  #endif // UNIX_FLAVOR
690  cpu = (x <= 0 ? 1 : (unsigned int)x);
691 #endif //NCBI_OS_...
692 
693  // default assumption
694  if (!cpu) {
695  cpu = 1;
696  }
697  }
698  return cpu;
699 }
700 
701 
703 {
704 
705 #if defined(NCBI_OS_MSWIN)
706 
707  DWORD_PTR proc_mask = 0, sys_mask = 0;
708  if (!::GetProcessAffinityMask(::GetCurrentProcess(), &proc_mask, &sys_mask)) {
709  return 0;
710  }
711  unsigned int n = 0; // number of bits set in proc_mask
712  for (; proc_mask; proc_mask >>= 1) {
713  n += proc_mask & 1;
714  }
715  return n;
716 
717 #elif defined(NCBI_OS_LINUX)
718 
719  unsigned int total_cpus = CSystemInfo::GetCpuCount();
720  if (total_cpus == 1) {
721  // GetCpuCount() returns 1 if unable to get real number
722  return 1;
723  }
724  // Standard type cpu_set_t can be limited if used directly,
725  // so use dynamic allocation approach
726  cpu_set_t* cpuset_ptr = CPU_ALLOC(total_cpus);
727  if (cpuset_ptr == NULL) {
728  return 0;
729  }
730  size_t cpuset_size = CPU_ALLOC_SIZE(total_cpus);
731  CPU_ZERO_S(cpuset_size, cpuset_ptr);
732 
733  if (sched_getaffinity(getpid(), cpuset_size, cpuset_ptr) != 0) {
734  CPU_FREE(cpuset_ptr);
735  return 0;
736  }
737  int n = CPU_COUNT_S(cpuset_size, cpuset_ptr);
738  CPU_FREE(cpuset_ptr);
739  return (n < 0) ? 0 : static_cast<unsigned int>(n);
740 
741 #endif //NCBI_OS_...
742 
743  // TODO: add support for other UNIX versions where possible
744 
745  return 0;
746 }
747 
748 
750 {
751 #if defined(NCBI_OS_MSWIN)
752  return (double)GetTickCount64() / kMilliSecondsPerSecond;
753 
754 #elif defined(NCBI_OS_UNIX) && defined(CLOCK_UPTIME)
755  struct timespec ts;
756  if (clock_gettime(CLOCK_UPTIME, &ts) == 0) {
757  return ts.tv_sec + (double)ts.tv_nsec/kNanoSecondsPerSecond;
758  }
759 
760 #elif defined(NCBI_OS_LINUX)
761  // "/proc/uptime" provide more accurate information than
762  // sysinfo(), that is rounded to seconds
763  CNcbiIfstream is("/proc/uptime");
764  if (is) {
765  double ut;
766  is >> ut;
767  return ut;
768  }
769 
770 #elif defined(NCBI_OS_BSD) || defined(NCBI_OS_DAWRIN)
771  struct timeval boottime;
772  size_t len = sizeof(boottime);
773  int mib[2] = { CTL_KERN, KERN_BOOTTIME };
774  if (sysctl(mib, 2, &boottime, &len, NULL, 0) < 0) {
775  return -1.0;
776  }
777  return time(NULL) - boottime.tv_sec + (double)boottime.tv_usec/kMicroSecondsPerSecond;
778 
779 #endif
781  return -1.0;
782 }
783 
784 
786 {
787  static atomic<unsigned long> cached_value;
788  auto value = cached_value.load(memory_order_relaxed);
789  if ( value ) {
790  return value;
791  }
792 
793 #if defined(NCBI_OS_MSWIN)
794  SYSTEM_INFO si;
795  GetSystemInfo(&si);
796  value = (unsigned long) si.dwPageSize;
797 
798 #elif defined(NCBI_OS_UNIX)
799  long x = 0;
800  #if defined(HAVE_GETPAGESIZE)
801  x = getpagesize();
802  #elif defined(_SC_PAGESIZE)
803  x = sysconf(_SC_PAGESIZE);
804  #elif defined(_SC_PAGE_SIZE)
805  x = sysconf(_SC_PAGE_SIZE);
806  #endif
807  if (x <= 0) {
809  return 0;
810  }
811  value = x;
812 #else
814 #endif //NCBI_OS_...
815 
816  cached_value.store(value, memory_order_relaxed);
817  return value;
818 }
819 
820 
822 {
823  static atomic<unsigned long> cached_value;
824  auto value = cached_value.load(memory_order_relaxed);
825  if (!value) {
826 #if defined(NCBI_OS_MSWIN)
827  SYSTEM_INFO si;
828  GetSystemInfo(&si);
829  value = (unsigned long) si.dwAllocationGranularity;
830 #else
832 #endif
833  cached_value.store(value, memory_order_relaxed);
834  }
835  return value;
836 }
837 
838 
840 {
841  static atomic<Uint8> cached_value;
842  auto value = cached_value.load(memory_order_relaxed);
843  if (value) {
844  return value;
845  }
846 
847 #if defined(NCBI_OS_MSWIN)
848  MEMORYSTATUSEX st;
849  st.dwLength = sizeof(st);
850  if ( ::GlobalMemoryStatusEx(&st) ) {
851  value = st.ullTotalPhys;
852  }
853 
854 #elif defined(NCBI_OS_UNIX) && defined(_SC_PHYS_PAGES)
855  unsigned long num_pages = sysconf(_SC_PHYS_PAGES);
856  if (long(num_pages) != -1L) {
857  value = GetVirtualMemoryPageSize() * Uint8(num_pages);
858  }
859 
860 #elif defined(NCBI_OS_BSD) || defined(NCBI_OS_DARWIN)
861  int mib[2];
862  mib[0] = CTL_HW;
863  #ifdef HW_MEMSIZE
864  uint64_t physmem;
865  mib[1] = HW_MEMSIZE;
866  #else
867  // Native BSD, may be truncated
868  int physmem;
869  mib[1] = HW_PHYSMEM;
870  #endif
871  size_t len = sizeof(physmem);
872  if (sysctl(mib, 2, &physmem, &len, NULL, 0) == 0 && len == sizeof(physmem)){
873  value = Uint8(physmem);
874  }
875  #if defined(NCBI_OS_DARWIN)
876  {
877  // heavier fallback
878  struct vm_statistics vm_stat;
879  mach_port_t my_host = mach_host_self();
880  mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
881  if (host_statistics(my_host, HOST_VM_INFO,
882  (integer_t*) &vm_stat, &count) == KERN_SUCCESS) {
884  ( Uint8(vm_stat.free_count) +
885  Uint8(vm_stat.active_count) +
886  Uint8(vm_stat.inactive_count) +
887  Uint8(vm_stat.wire_count) );
888  }
889  }
890  #endif //NCBI_OS_DARWIN
891 
892 #elif defined(NCBI_OS_IRIX)
893  struct rminfo rmi;
894  if (sysmp(MP_SAGET, MPSA_RMINFO, &rmi, sizeof(rmi)) >= 0) {
895  value = GetVirtualMemoryPageSize() * Uint8(rmi.physmem);
896  }
897 
898 #else
900 #endif
901  cached_value.store(value, memory_order_relaxed);
902  return value;
903 }
904 
905 
907 {
908 #if defined(NCBI_OS_MSWIN)
909  MEMORYSTATUSEX st;
910  st.dwLength = sizeof(st);
911  if ( ::GlobalMemoryStatusEx(&st) ) {
912  return st.ullAvailPhys;
913  }
914 
915 #elif defined(NCBI_OS_UNIX) && defined(_SC_AVPHYS_PAGES)
916  unsigned long num_pages = sysconf(_SC_AVPHYS_PAGES);
917  if (long(num_pages) != -1L) {
918  return GetVirtualMemoryPageSize() * Uint8(num_pages);
919  }
920 
921 #elif (defined(NCBI_OS_BSD) || defined(NCBI_OS_DARWIN)) && defined(HW_USERMEM)
922  int mib[2] = { CTL_HW, HW_USERMEM };
923  uint64_t mem;
924  size_t len = sizeof(mem);
925  if (sysctl(mib, 2, &mem, &len, NULL, 0) == 0 && len == sizeof(mem)){
926  return Uint8(mem);
927  }
928  #if defined(NCBI_OS_DARWIN)
929  {
930  // heavier fallback
931  struct vm_statistics vm_stat;
932  mach_port_t my_host = mach_host_self();
933  mach_msg_type_number_t count = HOST_VM_INFO_COUNT;
934  if (host_statistics(my_host, HOST_VM_INFO,
935  (integer_t*) &vm_stat, &count) == KERN_SUCCESS) {
936  return GetVirtualMemoryPageSize() * Uint8(vm_stat.free_count);
937  }
938  }
939  #endif //NCBI_OS_DARWIN
940 
941 #elif defined(NCBI_OS_IRIX)
942  struct rminfo rmi;
943  if (sysmp(MP_SAGET, MPSA_RMINFO, &rmi, sizeof(rmi)) >= 0) {
944  return GetVirtualMemoryPageSize() * Uint8(rmi.availrmem);
945  }
946 
947 #else
949 #endif
950  return 0;
951 }
952 
953 
955 {
956 #if defined(NCBI_OS_MSWIN)
957  return CLOCKS_PER_SEC;
958 
959 #elif defined(NCBI_OS_UNIX)
960  static atomic<clock_t> cached_value;
961  auto value = cached_value.load(memory_order_relaxed);
962  if ( value ) {
963  return value;
964  }
965  clock_t t = sysconf(_SC_CLK_TCK);
966  #if defined(CLK_TCK)
967  if (!t || t == (clock_t)(-1)) t = CLK_TCK;
968  #elif defined(CLOCKS_PER_SEC)
969  if (!t || t == (clock_t)(-1)) t = CLOCKS_PER_SEC;
970  #endif
971  if (t && t != (clock_t)(-1)) {
972  value = t;
973  cached_value.store(value, memory_order_relaxed);
974  return value;
975  }
977 
978 #else
980 #endif
981  return 0;
982 }
983 
984 
985 // @deprecated
986 bool GetMemoryUsage(size_t* total, size_t* resident, size_t* shared)
987 {
988  size_t scratch;
989  if ( !total ) { total = &scratch; }
990  if ( !resident ) { resident = &scratch; }
991  if ( !shared ) { shared = &scratch; }
992 
993 #if defined(NCBI_OS_MSWIN)
995  {
996  DWORD size;
997  DWORD page_fault_count;
998  SIZE_T peak_working_set_size;
999  SIZE_T working_set_size;
1000  SIZE_T quota_peak_paged_pool_usage;
1001  SIZE_T quota_paged_pool_usage;
1002  SIZE_T quota_peak_nonpaged_pool_usage;
1003  SIZE_T quota_nonpaged_pool_usage;
1004  SIZE_T pagefile_usage;
1005  SIZE_T peak_pagefile_usage;
1006  };
1007  try {
1008  // Load PSAPI dynamic library -- it should exist on MS-Win NT/2000/XP
1009  CDll psapi_dll("psapi.dll", CDll::eLoadNow, CDll::eAutoUnload);
1010  BOOL (STDMETHODCALLTYPE FAR * dllGetProcessMemoryInfo)
1011  (HANDLE process, SProcessMemoryCounters& counters, DWORD size) = 0;
1012  dllGetProcessMemoryInfo = psapi_dll.GetEntryPoint_Func("GetProcessMemoryInfo", &dllGetProcessMemoryInfo);
1013  if (dllGetProcessMemoryInfo) {
1014  SProcessMemoryCounters counters;
1015  dllGetProcessMemoryInfo(GetCurrentProcess(), counters, sizeof(counters));
1016  *total = counters.quota_paged_pool_usage +
1017  counters.quota_nonpaged_pool_usage;
1018  *resident = counters.working_set_size;
1019  *shared = 0;
1020  return true;
1021  }
1022  } catch (CException) {
1023  // Just catch all exceptions from CDll
1024  }
1025 
1026 #elif defined(NCBI_OS_LINUX)
1027  CNcbiIfstream statm("/proc/self/statm");
1028  if (statm) {
1029  unsigned long page_size = CSystemInfo::GetVirtualMemoryPageSize();
1030  statm >> *total >> *resident >> *shared;
1031  *total *= page_size;
1032  *resident *= page_size;
1033  *shared *= page_size;
1034  return true;
1035  }
1036 
1037 #elif defined(NCBI_OS_SOLARIS)
1038  Int8 len = CFile("/proc/self/as").GetLength();
1039  if (len > 0) {
1040  *total = (size_t) len;
1041  *resident = (size_t) len; // conservative estimate
1042  *shared = 0; // does this info exist anywhere?
1043  return true;
1044  }
1045 
1046 #elif defined(HAVE_GETRUSAGE)
1047  #define _DIV0(a, b) ((a) / ((b) ? (b) : 1))
1048  // BIG FAT NOTE: getrusage() seems to use different size units
1049  struct rusage ru;
1050  memset(&ru, '\0', sizeof(ru));
1051  if (getrusage(RUSAGE_SELF, &ru) == 0 && ru.ru_maxrss > 0) {
1052  struct tms t;
1053  memset(&t, '\0', sizeof(t));
1054  if (times(&t) != (clock_t)(-1)) {
1055  clock_t ticks = t.tms_utime + t.tms_stime;
1056  *resident = _DIV0(ru.ru_idrss, ticks);
1057  *shared = _DIV0(ru.ru_ixrss, ticks);
1058  *total = _DIV0(ru.ru_ixrss + ru.ru_idrss + ru.ru_isrss, ticks);
1059  #ifdef NCBI_OS_DARWIN
1060  if (*total > 0)
1061  #endif
1062  return true;
1063  }
1064  }
1065  #undef _DIV0
1066 
1067  #if defined(NCBI_OS_DARWIN)
1068  #ifdef MACH_TASK_BASIC_INFO
1069  task_flavor_t flavor = MACH_TASK_BASIC_INFO;
1070  struct mach_task_basic_info t_info;
1071  mach_msg_type_number_t t_info_count = MACH_TASK_BASIC_INFO_COUNT;
1072  #else
1073  task_flavor_t flavor = TASK_BASIC_INFO;
1074  struct task_basic_info t_info;
1075  mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT;
1076  #endif
1077  if (task_info(mach_task_self(), flavor, (task_info_t)&t_info, &t_info_count) == KERN_SUCCESS) {
1078  *total = *resident = t_info.resident_size;
1079  *shared = 0; // unavailable, even with mach_task_basic_info
1080  return true;
1081  }
1082  #endif
1083 
1084 #else
1086 #endif
1087  return false;
1088 }
1089 
1090 
1091 /// @deprecated
1092 bool GetCurrentProcessTimes(double* user_time, double* system_time)
1093 {
1094 #if defined(NCBI_OS_MSWIN)
1095  // Each FILETIME structure contains the number of 100-nanosecond time units
1096  FILETIME ft_creation, ft_exit, ft_kernel, ft_user;
1097  if (!::GetProcessTimes(GetCurrentProcess(),
1098  &ft_creation, &ft_exit, &ft_kernel, &ft_user)) {
1099  return false;
1100  }
1101  if ( system_time ) {
1102  *system_time = (ft_kernel.dwLowDateTime +
1103  ((Uint8) ft_kernel.dwHighDateTime << 32)) * 1.0e-7;
1104  }
1105  if ( user_time ) {
1106  *user_time = (ft_user.dwLowDateTime +
1107  ((Uint8) ft_user.dwHighDateTime << 32)) * 1.0e-7;
1108  }
1109 
1110 #elif defined(NCBI_OS_UNIX)
1111 
1112  tms buf;
1113  clock_t t = times(&buf);
1114  if ( t == (clock_t)(-1) ) {
1115  return false;
1116  }
1117  clock_t tick = sysconf(_SC_CLK_TCK);
1118 #if defined(CLK_TCK)
1119  if (!tick || tick == (clock_t)(-1))
1120  tick = CLK_TCK;
1121 #elif defined(CLOCKS_PER_SEC)
1122  if (!tick || tick == (clock_t)(-1))
1123  tick = CLOCKS_PER_SEC;
1124 #endif
1125  if (tick == (clock_t)(-1)) {
1126  return false;
1127  }
1128  if ( system_time ) {
1129  *system_time = (double)buf.tms_stime / (double)tick;
1130  }
1131  if ( user_time ) {
1132  *user_time = (double)buf.tms_utime / (double)tick;
1133  }
1134 #endif
1135  return true;
1136 }
1137 
1138 
1139 /// @deprecated
1140 extern int GetProcessFDCount(int* soft_limit, int* hard_limit)
1141 {
1142 #ifdef NCBI_OS_UNIX
1143  int fd_count = 0;
1144  rlim_t cur_limit = -1;
1145  rlim_t max_limit = -1;
1146 
1147  struct rlimit rlim;
1148  if (getrlimit(RLIMIT_NOFILE, &rlim) == 0) {
1149  cur_limit = rlim.rlim_cur;
1150  max_limit = rlim.rlim_max;
1151  } else {
1152  // fallback to sysconf
1153  cur_limit = static_cast<rlim_t>(sysconf(_SC_OPEN_MAX));
1154  }
1155 
1156  DIR* dir = opendir("/proc/self/fd/");
1157  if (dir) {
1158  while (readdir(dir) != NULL) {
1159  ++fd_count;
1160  }
1161  closedir(dir);
1162  fd_count -= 3; // '.', '..' and the one for 'opendir'
1163  if (fd_count < 0) {
1164  fd_count = -1;
1165  }
1166  } else {
1167  // Fallback to analysis via looping over all fds
1168  if (cur_limit > 0) {
1169  int max_fd = static_cast<int>(cur_limit);
1170  if (cur_limit > INT_MAX) {
1171  max_fd = INT_MAX;
1172  }
1173  for (int fd = 0; fd < max_fd; ++fd) {
1174  if (fcntl(fd, F_GETFD, 0) == -1) {
1175  if (errno == EBADF) {
1176  continue;
1177  }
1178  }
1179  ++fd_count;
1180  }
1181  } else {
1182  fd_count = -1;
1183  }
1184  }
1185 
1186  if (soft_limit) {
1187  if (cur_limit > INT_MAX)
1188  *soft_limit = INT_MAX;
1189  else
1190  *soft_limit = static_cast<int>(cur_limit);
1191  }
1192  if (hard_limit) {
1193  if (max_limit > INT_MAX)
1194  *hard_limit = INT_MAX;
1195  else
1196  *hard_limit = static_cast<int>(max_limit);
1197  }
1198  return fd_count;
1199 
1200 #else
1201  if (soft_limit)
1202  *soft_limit = -1;
1203  if (hard_limit)
1204  *hard_limit = -1;
1205  return -1;
1206 
1207 #endif //NCBI_OS_UNIX
1208 }
1209 
1210 
1211 /// @deprecated
1212 extern int GetProcessThreadCount(void)
1213 {
1214 #ifdef NCBI_OS_LINUX
1215  int thread_count = 0;
1216 
1217  DIR* dir = opendir("/proc/self/task/");
1218  if (dir) {
1219  while (readdir(dir) != NULL)
1220  ++thread_count;
1221  closedir(dir);
1222  thread_count -= 2; // '.' and '..'
1223  if (thread_count <= 0)
1224  thread_count = -1;
1225  return thread_count;
1226  }
1227  return -1;
1228 #else
1229  return -1;
1230 #endif //NCBI_OS_LINUX
1231 }
1232 
1233 
1234 
1235 /////////////////////////////////////////////////////////////////////////////
1236 //
1237 // Memory advise
1238 //
1239 
1240 #ifndef HAVE_MADVISE
1241 
1242 bool MemoryAdvise(void*, size_t, EMemoryAdvise) {
1243  return false;
1244 }
1245 
1246 #else //HAVE_MADVISE
1247 
1248 bool MemoryAdvise(void* addr, size_t len, EMemoryAdvise advise)
1249 {
1250  if ( !addr /*|| !len*/ ) {
1251  ERR_POST_X(11, "Memory address is not specified");
1253  return false;
1254  }
1255  int adv;
1256  switch (advise) {
1257  case eMADV_Normal:
1258  adv = MADV_NORMAL; break;
1259  case eMADV_Random:
1260  adv = MADV_RANDOM; break;
1261  case eMADV_Sequential:
1262  adv = MADV_SEQUENTIAL; break;
1263  case eMADV_WillNeed:
1264  adv = MADV_WILLNEED; break;
1265  case eMADV_DontNeed:
1266  adv = MADV_DONTNEED; break;
1267  case eMADV_DontFork:
1268  #if defined(MADV_DONTFORK)
1269  adv = MADV_DONTFORK;
1270  break;
1271  #else
1272  ERR_POST_X_ONCE(12, Warning << "MADV_DONTFORK not supported");
1274  return false;
1275  #endif
1276  case eMADV_DoFork:
1277  #if defined(MADV_DOFORK)
1278  adv = MADV_DOFORK;
1279  break;
1280  #else
1281  ERR_POST_X_ONCE(12, Warning << "MADV_DOFORK not supported");
1283  return false;
1284  #endif
1285  case eMADV_Mergeable:
1286  #if defined(MADV_MERGEABLE)
1287  adv = MADV_MERGEABLE;
1288  break;
1289  #else
1290  ERR_POST_X_ONCE(12, Warning << "MADV_MERGEABLE not supported");
1292  return false;
1293  #endif
1294  case eMADV_Unmergeable:
1295  #if defined(MADV_UNMERGEABLE)
1296  adv = MADV_UNMERGEABLE;
1297  break;
1298  #else
1299  ERR_POST_X_ONCE(12, Warning << "MADV_UNMERGEABLE not supported");
1301  return false;
1302  #endif
1303  default:
1304  _TROUBLE;
1305  return false;
1306  }
1307  // Conversion type of "addr" to char* -- Sun Solaris fix
1308  if ( madvise((char*) addr, len, adv) != 0 ) {
1309  int x_errno = errno; \
1310  ERR_POST_X(13, "madvise() failed: " <<
1311  _T_STDSTRING(NcbiSys_strerror(x_errno)));
1312  CNcbiError::SetErrno(errno = x_errno);
1313  return false;
1314  }
1315  return true;
1316 }
1317 #endif //HAVE_MADVISE
1318 
1319 
1320 
1321 /////////////////////////////////////////////////////////////////////////////
1322 //
1323 // Sleep
1324 //
1325 
1326 void SleepMicroSec(unsigned long mc_sec, EInterruptOnSignal onsignal)
1327 {
1328 #if defined(NCBI_OS_MSWIN)
1329 
1330  // Unlike some of its (buggy) Unix counterparts, MS-Win's Sleep() is safe
1331  // to use with 0, which causes the current thread to sleep at most until
1332  // the end of the current timeslice (and only if the CPU is not idle).
1333  static const unsigned long kMicroSecondsPerMilliSecond = kMicroSecondsPerSecond / kMilliSecondsPerSecond;
1334  Sleep((mc_sec + (kMicroSecondsPerMilliSecond / 2)) / kMicroSecondsPerMilliSecond);
1335 
1336 #elif defined(NCBI_OS_UNIX)
1337 
1338 # if defined(HAVE_NANOSLEEP)
1339  struct timespec delay, unslept;
1340  memset(&unslept, 0, sizeof(unslept));
1341  delay.tv_sec = mc_sec / kMicroSecondsPerSecond;
1342  delay.tv_nsec = ((mc_sec % kMicroSecondsPerSecond) * (kNanoSecondsPerSecond / kMicroSecondsPerSecond));
1343  while (nanosleep(&delay, &unslept) < 0) {
1344  if (errno != EINTR || onsignal == eInterruptOnSignal) {
1345  break;
1346  }
1347  delay = unslept;
1348  memset(&unslept, 0, sizeof(unslept));
1349  }
1350 # elif defined(HAVE_USLEEP)
1351  unsigned int sec = mc_sec / kMicroSecondsPerSecond;
1352  unsigned int usec = mc_sec % kMicroSecondsPerSecond;
1353  if (sec) {
1354  while ((sec = sleep(sec)) > 0) {
1355  if (onsignal == eInterruptOnSignal) {
1356  return;
1357  }
1358  }
1359  }
1360  // usleep() detects errors (such as EINTR) but can't tell unslept time :-/
1361  usleep(usec);
1362 # else
1363  // Portable but ugly.
1364  // Most implementations of select() do not modify timeout to reflect
1365  // the amount of time unslept; but some (e.g. Linux) do. Also, on
1366  // some platforms it can be interrupted by a signal, but not on others.
1367  // OTOH, we don't want to sandwich this with gettimeofday(), either.
1368  struct timeval delay;
1369  delay.tv_sec = mc_sec / kMicroSecondsPerSecond;
1370  delay.tv_usec = mc_sec % kMicroSecondsPerSecond;
1371  while (select(0, (fd_set*) 0, (fd_set*) 0, (fd_set*) 0, &delay) < 0) {
1372 # ifdef SELECT_UPDATES_TIMEOUT
1373  if (errno != EINTR || onsignal == eInterruptOnSignal)
1374 # endif
1375  break;
1376  }
1377 # endif //HAVE FINE SLEEP API
1378 
1379 #endif //NCBI_OS_...
1380 }
1381 
1382 
1383 void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal)
1384 {
1385 #ifdef NCBI_OS_MSWIN
1386  Sleep(ml_sec);
1387 #else
1389 #endif //NCBI_OS_MSWIN
1390 }
1391 
1392 
1393 void SleepSec(unsigned long sec, EInterruptOnSignal onsignal)
1394 {
1395  SleepMicroSec(sec * kMicroSecondsPerSecond, onsignal);
1396 }
1397 
1398 
1399 
1400 /////////////////////////////////////////////////////////////////////////////
1401 ///
1402 /// Suppress Diagnostic Popup Messages (all MS-Win specific)
1403 ///
1404 
1405 #ifdef NCBI_OS_MSWIN
1406 
1410 
1411 // Handler for "Unhandled" exceptions
1412 static LONG CALLBACK _SEH_Handler(EXCEPTION_POINTERS* ep)
1413 {
1414 #ifdef _UNICODE
1415  wchar_t dumpname[64], tmp[64];
1416  wcscat( wcscat( wcscpy(dumpname, L"core."), _ltow(GetCurrentProcessId(), tmp, 10)), L".dmp");
1417 #else
1418  char dumpname[64], tmp[64];
1419  strcat( strcat( strcpy(dumpname, "core."), _ltoa(GetCurrentProcessId(), tmp, 10)), ".dmp");
1420 #endif
1421  HANDLE hf = CreateFile(dumpname,
1422  GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
1423  if (hf != INVALID_HANDLE_VALUE)
1424  {
1425  MINIDUMP_EXCEPTION_INFORMATION ei;
1426  ei.ThreadId = GetCurrentThreadId();
1427  ei.ExceptionPointers = ep;
1428  ei.ClientPointers = FALSE;
1429  MiniDumpWriteDump(
1430  GetCurrentProcess(), GetCurrentProcessId(),
1431  hf, MiniDumpNormal, &ei, NULL, NULL);
1432  CloseHandle(hf);
1433  cerr << "Unhandled exception: " << hex
1434  << ep->ExceptionRecord->ExceptionCode << " at "
1435  << ep->ExceptionRecord->ExceptionAddress << endl;
1436  }
1437  // Always terminate a program
1438  return EXCEPTION_EXECUTE_HANDLER;
1439 }
1440 
1441 #endif //NCBI_OS_MSWIN
1442 
1444 {
1445 #ifdef NCBI_OS_MSWIN
1447  return;
1448  }
1449  // System errors
1450  if ((mode & fSuppress_System) == fSuppress_System ) {
1451  SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX |
1452  SEM_NOOPENFILEERRORBOX);
1453  }
1454  // Runtime library
1455  if ( (mode & fSuppress_Runtime) == fSuppress_Runtime ) {
1456  _set_error_mode(_OUT_TO_STDERR);
1457  }
1458  // Debug library
1459  if ( !IsDebuggerPresent() ) {
1460  if ( (mode & fSuppress_Debug) == fSuppress_Debug ) {
1461  _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);
1462  _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
1463  _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR);
1464  _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
1465  _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR);
1466  _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
1468  }
1469  }
1470  // Exceptions
1472  SetUnhandledExceptionFilter(_SEH_Handler);
1473  }
1475 
1476 #else
1477  // dummy, to avoid compilation warning
1478  mode = 0;
1479 
1480 #endif
1481 }
1482 
1483 
1485 {
1486 #ifdef NCBI_OS_MSWIN
1488  ERR_POST_X(9, Critical << "SuppressSystemMessageBox() already called");
1489  }
1491 #endif //NCBI_OS_MSWIN
1492 }
1493 
1494 
1496 {
1497 #ifdef NCBI_OS_MSWIN
1499 #else
1500  return false;
1501 #endif //NCBI_OS_MSWIN
1502 }
1503 
1504 
1505 
1506 /////////////////////////////////////////////////////////////////////////////
1507 ///
1508 /// CPU
1509 ///
1510 
1511 // Code credit for CPU capabilities checks:
1512 // https://attractivechaos.wordpress.com/2017/09/04/on-cpu-dispatch/
1513 //
1514 bool VerifyCpuCompatibility(string* message)
1515 {
1516  // Compiles with SSE 4.2 support -- verify that CPU allow it
1517 
1518  #if defined(NCBI_SSE) && NCBI_SSE >= 42
1519 
1520  if (getenv("NCBI_RUN_UNDER_VALGRIND")) {
1521  // Skip if runs under Valgrind memory checker,
1522  // seems cpuid produce wrong results there, probably if running on VM
1523  return true;
1524  }
1525 
1526  unsigned eax, ebx, ecx, edx;
1527  #ifdef NCBI_OS_MSWIN
1528  int cpuid[4];
1529  __cpuid(cpuid, 1);
1530  eax = cpuid[0], ebx = cpuid[1], ecx = cpuid[2], edx = cpuid[3];
1531  #else
1532  asm volatile("cpuid" : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (1));
1533  #endif
1534  if ( !(ecx>>20 & 1) ) // SSE 4.2
1535  {
1536  if (message) {
1537  message->assign("Application requires a CPU with SSE 4.2 support");
1538  }
1539  return false;
1540  }
1541  #endif
1542 
1543  return true;
1544 }
1545 
1546 
1547 // Get all information on the first usage
1549 {
1550  static CCpuFeatures::InstructionSet* instruction_set = new CCpuFeatures::InstructionSet();
1551  return *instruction_set;
1552 }
1553 
1555  : f01_ECX_ { 0 },
1556  f01_EDX_ { 0 },
1557  f07_EBX_ { 0 },
1558  f07_ECX_ { 0 },
1559  f81_ECX_ { 0 },
1560  f81_EDX_ { 0 }
1561 {
1562 #if defined(__i386__) || defined(__x86_64__) || defined(_M_IX86) || defined(_M_X64)
1563  int nIds = 0;
1564  int nExIds = 0;
1565 
1566  using TRegisters = std::array<int,4>; // [EAX, EBX, ECX, EDX]
1567  TRegisters registers;
1568  vector<TRegisters> m_Data;
1569  vector<TRegisters> m_ExtData;
1570 
1571  // Local function
1572  auto CPUID = [](TRegisters& r, int func_id) {
1573  #ifdef NCBI_OS_MSWIN
1574  __cpuid(r.data(), func_id);
1575  #else
1576  asm volatile("cpuid" : "=a" (r[0]), "=b" (r[1]), "=c" (r[2]), "=d" (r[3]) : "a" (func_id));
1577  #endif
1578  };
1579  auto CPUID_EX = [](TRegisters& r, int func_id, int sub_id) {
1580  #ifdef NCBI_OS_MSWIN
1581  __cpuidex(r.data(), func_id, sub_id);
1582  #else
1583  asm volatile("cpuid" : "=a" (r[0]), "=b" (r[1]), "=c" (r[2]), "=d" (r[3]) : "a" (func_id), "c" (sub_id));
1584  #endif
1585  };
1586 
1587  // Calling __cpuid with 0x0 as the function_id argument
1588  // gets the number of the highest valid function ID.
1589  CPUID(registers, 0);
1590  nIds = registers[0];
1591 
1592  for (int i = 0; i <= nIds; ++i) {
1593  CPUID_EX(registers, i, 0);
1594  m_Data.push_back(registers);
1595  }
1596 
1597  // Capture vendor string
1598  char vendor[0x20];
1599  memset(vendor, 0, sizeof(vendor));
1600  *reinterpret_cast<int*>(vendor) = m_Data[0][1];
1601  *reinterpret_cast<int*>(vendor + 4) = m_Data[0][3];
1602  *reinterpret_cast<int*>(vendor + 8) = m_Data[0][2];
1603  m_VendorStr = vendor;
1604  if (m_VendorStr == "GenuineIntel") {
1605  m_Vendor = eIntel;
1606  }
1607  else if (m_VendorStr == "AuthenticAMD") {
1608  m_Vendor = eAMD;
1609  }
1610 
1611  // Load bitset with flags for function 0x00000001
1612  if (nIds >= 1) {
1613  f01_ECX_ = m_Data[1][2];
1614  f01_EDX_ = m_Data[1][3];
1615  }
1616  // Load bitset with flags for function 0x00000007
1617  if (nIds >= 7) {
1618  f07_EBX_ = m_Data[7][1];
1619  f07_ECX_ = m_Data[7][2];
1620  }
1621 
1622  // Calling cpuid with 0x80000000 as the function_id argument
1623  // gets the number of the highest valid extended ID.
1624  CPUID(registers, 0x80000000);
1625  nExIds = registers[0];
1626  //
1627  for (int i = 0x80000000; i <= nExIds; ++i) {
1628  CPUID_EX(registers, i, 0);
1629  m_ExtData.push_back(registers);
1630  }
1631 
1632  // Load bitset with flags for function 0x80000001
1633  if (nExIds >= (int)0x80000001) {
1634  f81_ECX_ = m_ExtData[1][2];
1635  f81_EDX_ = m_ExtData[1][3];
1636  }
1637 
1638  // Interpret CPU brand string if reported
1639  if (nExIds >= (int)0x80000004) {
1640  char brand[0x40];
1641  memset(brand, 0, sizeof(brand));
1642  memcpy(brand, m_ExtData[2].data(), sizeof(registers));
1643  memcpy(brand + 16, m_ExtData[3].data(), sizeof(registers));
1644  memcpy(brand + 32, m_ExtData[4].data(), sizeof(registers));
1645  m_BrandStr = brand;
1646  }
1647 #endif
1648 };
1649 
1650 
1652 {
1653  list<string> supported;
1654  list<string> unsupported;
1655 
1656  auto check = [&supported,&unsupported](string feature, bool is_supported) {
1657  if (is_supported) {
1658  supported.push_back(feature);
1659  } else {
1660  unsupported.push_back(feature);
1661  }
1662  };
1663 
1664  // sorted order
1665 
1666  check( "_3DNOW", CCpuFeatures::_3DNOW() );
1667  check( "_3DNOWEXT", CCpuFeatures::_3DNOWEXT() );
1668  check( "ABM", CCpuFeatures::ABM() );
1669  check( "ADX", CCpuFeatures::ADX() );
1670  check( "AES", CCpuFeatures::AES() );
1671  check( "AVX", CCpuFeatures::AVX() );
1672  check( "AVX2", CCpuFeatures::AVX2() );
1673  check( "AVX512CD", CCpuFeatures::AVX512CD() );
1674  check( "AVX512ER", CCpuFeatures::AVX512ER() );
1675  check( "AVX512F", CCpuFeatures::AVX512F() );
1676  check( "AVX512PF", CCpuFeatures::AVX512PF() );
1677  check( "BMI1", CCpuFeatures::BMI1() );
1678  check( "BMI2", CCpuFeatures::BMI2() );
1679  check( "CLFSH", CCpuFeatures::CLFSH() );
1680  check( "CMPXCHG16B", CCpuFeatures::CMPXCHG16B() );
1681  check( "CX8", CCpuFeatures::CX8() );
1682  check( "ERMS", CCpuFeatures::ERMS() );
1683  check( "F16C", CCpuFeatures::F16C() );
1684  check( "FMA", CCpuFeatures::FMA() );
1685  check( "FSGSBASE", CCpuFeatures::FSGSBASE() );
1686  check( "FXSR", CCpuFeatures::FXSR() );
1687  check( "HLE", CCpuFeatures::HLE() );
1688  check( "INVPCID", CCpuFeatures::INVPCID() );
1689  check( "LAHF", CCpuFeatures::LAHF() );
1690  check( "LZCNT", CCpuFeatures::LZCNT() );
1691  check( "MMX", CCpuFeatures::MMX() );
1692  check( "MMXEXT", CCpuFeatures::MMXEXT() );
1693  check( "MONITOR", CCpuFeatures::MONITOR() );
1694  check( "MOVBE", CCpuFeatures::MOVBE() );
1695  check( "MSR", CCpuFeatures::MSR() );
1696  check( "OSXSAVE", CCpuFeatures::OSXSAVE() );
1697  check( "PCLMULQDQ", CCpuFeatures::PCLMULQDQ() );
1698  check( "POPCNT", CCpuFeatures::POPCNT() );
1699  check( "PREFETCHWT1", CCpuFeatures::PREFETCHWT1());
1700  check( "RDRAND", CCpuFeatures::RDRAND() );
1701  check( "RDSEED", CCpuFeatures::RDSEED() );
1702  check( "RDTSCP", CCpuFeatures::RDTSCP() );
1703  check( "RTM", CCpuFeatures::RTM() );
1704  check( "SEP", CCpuFeatures::SEP() );
1705  check( "SHA", CCpuFeatures::SHA() );
1706  check( "SSE", CCpuFeatures::SSE() );
1707  check( "SSE2", CCpuFeatures::SSE2() );
1708  check( "SSE3", CCpuFeatures::SSE3() );
1709  check( "SSE4.1", CCpuFeatures::SSE41() );
1710  check( "SSE4.2", CCpuFeatures::SSE42() );
1711  check( "SSE4a", CCpuFeatures::SSE4a() );
1712  check( "SSSE3", CCpuFeatures::SSSE3() );
1713  check( "SYSCALL", CCpuFeatures::SYSCALL() );
1714  check( "TBM", CCpuFeatures::TBM() );
1715  check( "XOP", CCpuFeatures::XOP() );
1716  check( "XSAVE", CCpuFeatures::XSAVE() );
1717 
1718  cout << "CPU vendor ID : " << CCpuFeatures::VendorStr() << endl;
1719  cout << "CPU brand string : " << CCpuFeatures::BrandStr() << endl;
1720 
1721  cout << endl << "Supported features:" << endl;
1722  for (auto feature : supported) {
1723  cout << feature << " ";
1724  }
1725  cout << endl;
1726  cout << endl << "Not supported features:" << endl;
1727  for (auto feature : unsupported) {
1728  cout << feature << " ";
1729  }
1730  cout << endl;
1731 }
1732 
1733 
1734 
static string VendorStr(void)
static bool AES(void)
static bool LZCNT(void)
static bool BMI2(void)
static bool AVX512PF(void)
static bool AVX(void)
static bool CMPXCHG16B(void)
static bool MOVBE(void)
static bool _3DNOW(void)
static bool AVX512F(void)
static bool ABM(void)
static bool SSE41(void)
static bool SSSE3(void)
static bool PCLMULQDQ(void)
static bool SSE42(void)
static bool MMXEXT(void)
static bool LAHF(void)
static bool RDTSCP(void)
static bool RTM(void)
static bool CLFSH(void)
static bool SSE(void)
static bool SSE2(void)
static bool OSXSAVE(void)
static bool CX8(void)
static bool RDSEED(void)
static bool FXSR(void)
static bool MSR(void)
static string BrandStr(void)
static void Print(void)
Print human-readable list of supported and not supported CPU features.
static bool BMI1(void)
static bool SHA(void)
static bool AVX512CD(void)
static bool HLE(void)
static bool XSAVE(void)
static bool PREFETCHWT1(void)
static bool FSGSBASE(void)
static bool MMX(void)
static bool F16C(void)
static bool ERMS(void)
static bool SYSCALL(void)
static bool POPCNT(void)
static bool SSE3(void)
static bool AVX512ER(void)
static bool AVX2(void)
static bool XOP(void)
static bool ADX(void)
static const InstructionSet & IS(void)
static bool MONITOR(void)
static bool SSE4a(void)
static bool SEP(void)
static bool FMA(void)
static bool TBM(void)
static bool RDRAND(void)
static bool _3DNOWEXT(void)
static bool INVPCID(void)
CDll –.
Definition: ncbidll.hpp:107
CFile –.
Definition: ncbifile.hpp:1604
CSafeStatic<>::
static clock_t GetClockTicksPerSecond(void)
Get number of (statistics) clock ticks per second.
static unsigned int GetCpuCount(void)
Return number of active CPUs/cores (never less than 1).
static unsigned long GetVirtualMemoryPageSize(void)
Return virtual memory page size.
static unsigned int GetCpuCountAllowed(void)
Return number of allowed to use CPUs/cores for the current thread.
static Uint8 GetAvailPhysicalMemorySize(void)
Return the amount of physical memory currently available on the system ("free"), in bytes.
static unsigned long GetVirtualMemoryAllocationGranularity(void)
Return size of an allocation unit (usually it is a multiple of page size).
static double GetUptime(void)
Get system uptime in seconds.
static Uint8 GetTotalPhysicalMemorySize(void)
Return the amount of actual/total physical memory, in bytes.
static string GetUserName(void)
Get actual user name for the current process.
CTime –.
Definition: ncbitime.hpp:296
static string GetUserNameByUID(uid_t uid)
Look up user name by given numeric user ID.
static string GetUserName(void)
Get name of the current user.
void(*)(CSeq_entry_Handle seh, IWorkbench *wb, const CSerialObject &obj) handler
static const char si[8][64]
Definition: des.c:146
#define strcat(s, k)
#define check(s)
Definition: describecol2.c:21
static char tmp[3200]
Definition: utf8.c:42
char data[12]
Definition: iconv.c:80
Uint8 uint64_t
EInterruptOnSignal
Interrupt on signal mode.
Definition: ncbimisc.hpp:160
@ eInterruptOnSignal
Cancel operation if interrupted by a signal.
Definition: ncbimisc.hpp:161
string
Definition: cgiapp.hpp:687
#define NULL
Definition: ncbistd.hpp:225
#define FAR
Definition: ncbistd.hpp:278
#define _DEBUG_ARG(arg)
Definition: ncbidbg.hpp:134
#define _VERIFY(expr)
Definition: ncbidbg.hpp:161
#define ERR_POST_X_ONCE(err_subcode, message)
Error posting only once during program execution with default error code and given error subcode.
Definition: ncbidiag.hpp:621
#define ERR_POST_X(err_subcode, message)
Error posting with default error code and given error subcode.
Definition: ncbidiag.hpp:550
TFunc GetEntryPoint_Func(const string &name, TFunc *func)
Get DLLs entry point (function).
Definition: ncbidll.hpp:273
@ eAutoUnload
Definition: ncbidll.hpp:144
@ eLoadNow
Definition: ncbidll.hpp:138
void Critical(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1203
static void SetFromErrno(void)
Set last error using current "errno" code.
Definition: ncbierror.cpp:220
void Warning(CExceptionArgs_Base &args)
Definition: ncbiexpt.hpp:1191
static void Set(ECode code)
Set last error using native error code enum.
Definition: ncbierror.cpp:160
static void SetErrno(int errno_code)
Set last error using errno code.
Definition: ncbierror.cpp:190
Int8 GetLength(void) const
Get size of file.
Definition: ncbifile.cpp:3204
int64_t Int8
8-byte (64-bit) signed integer
Definition: ncbitype.h:104
uint64_t Uint8
8-byte (64-bit) unsigned integer
Definition: ncbitype.h:105
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
IO_PREFIX::ifstream CNcbiIfstream
Portable alias for ifstream.
Definition: ncbistre.hpp:439
#define _T_STDSTRING(x)
Definition: ncbistr.hpp:180
static void SetFormat(const CTimeFormat &fmt)
Set the current time format.
Definition: ncbitime.cpp:1267
CTime & AddSecond(TSeconds seconds=1, EDaylight adl=eDaylightDefault)
Add specified seconds.
Definition: ncbitime.cpp:1879
string AsString(const CTimeFormat &format=kEmptyStr, TSeconds out_tz=eCurrentTimeZone) const
Transform time to string.
Definition: ncbitime.cpp:1511
const long kMilliSecondsPerSecond
Number milliseconds in one second.
Definition: ncbitime.hpp:96
const long kMicroSecondsPerSecond
Number of microseconds in one second.
Definition: ncbitime.hpp:91
const long kNanoSecondsPerSecond
Number of nanoseconds in one second.
Definition: ncbitime.hpp:86
@ eCurrent
Use current time. See also CCurrentTime.
Definition: ncbitime.hpp:300
#define INVALID_HANDLE_VALUE
A value for an invalid file handle.
Definition: mdb.c:389
#define HANDLE
An abstraction for a file handle.
Definition: mdb.c:383
unsigned int
A callback function used to compare two keys in a database.
Definition: types.hpp:1210
Definition of all error codes used in corelib (xncbi.lib).
where both of them are integers Note
char * buf
int i
yy_size_t n
int len
static void hex(unsigned char c)
Definition: mdb_dump.c:56
mdb_mode_t mode
Definition: lmdb++.h:38
const struct ncbi::grid::netcache::search::fields::SIZE size
const GenericPointer< typename T::ValueType > T2 value
Definition: pointer.h:1227
EIPRangeType t
Definition: ncbi_localip.c:101
Defines MS Windows specific private functions and classes.
Private UNIX specific features.
Static variables safety - create on demand, destroy on application termination.
#define FALSE
bool replacment for C indicating false.
Definition: ncbi_std.h:101
static CSafeStatic< CTime > s_TimeSet
bool SetCpuTimeLimit(unsigned int max_cpu_time, unsigned int terminate_delay_time, TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
[UNIX only] Set CPU time usage limit.
bool MemoryAdvise(void *addr, size_t len, EMemoryAdvise advise)
[UNIX only] Advise on memory usage for specified memory region.
bool SetMemoryLimit(size_t max_size, TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
[UNIX only] Set memory limit.
static ELimitsExitCode s_ExitCode
bool SetMemoryLimitSoft(size_t max_size, TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
[UNIX only] Set soft memory limit.
void SleepMilliSec(unsigned long ml_sec, EInterruptOnSignal onsignal)
static TLimitsPrintParameter s_PrintHandlerParam
void SleepSec(unsigned long sec, EInterruptOnSignal onsignal)
Sleep.
static size_t s_MemoryLimitHard
static bool s_DoneSuppressSystemMessageBox
static size_t s_CpuTimeLimit
bool SetMemoryLimitHard(size_t max_size, TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
[UNIX only] Set hard memory limit.
bool IsSuppressedDebugSystemMessageBox(void)
Check if system message box has been suppressed for debug library.
static bool s_SuppressedDebugSystemMessageBox
size_t GetVirtualMemoryLimitHard(void)
[UNIX only] Get "hard" memory limit of the virtual memory (address space) in bytes for a current proc...
static bool s_ExitHandlerIsSet
bool GetCurrentProcessTimes(double *user_time, double *system_time)
void DisableSuppressSystemMessageBox(void)
Prevent run of SuppressSystemMessageBox().
static void s_ExitHandler(void)
bool GetMemoryUsage(size_t *total, size_t *resident, size_t *shared)
void SuppressSystemMessageBox(TSuppressSystemMessageBox mode)
Suppress popup messages on execution errors.
bool VerifyCpuCompatibility(string *message)
CPU.
static void s_NewHandler(void)
static void s_SignalHandler(int sig)
size_t GetVirtualMemoryLimitSoft(void)
[UNIX only] Get "soft" memory limit of the virtual memory (address space) in bytes for a current proc...
bool SetHeapLimit(size_t max_size, TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
[UNIX only] Set memory limit.
static size_t s_MemoryLimitSoft
DEFINE_STATIC_FAST_MUTEX(s_ExitHandler_Mutex)
int GetProcessFDCount(int *soft_limit, int *hard_limit)
static bool s_EnableSuppressSystemMessageBox
Suppress Diagnostic Popup Messages (all MS-Win specific)
int GetProcessThreadCount(void)
[Linux only] Provides the number of threads in the current process.
static char * s_ReserveMemory
static bool s_SetExitHandler(TLimitsPrintHandler handler, TLimitsPrintParameter parameter)
void SleepMicroSec(unsigned long mc_sec, EInterruptOnSignal onsignal)
static LONG CALLBACK _SEH_Handler(EXCEPTION_POINTERS *ep)
static TLimitsPrintHandler s_PrintHandler
int TSuppressSystemMessageBox
Binary OR of "ESuppressSystemMessageBox".
void * TLimitsPrintParameter
Type of parameter for print handler.
Definition: ncbi_system.hpp:70
EMemoryAdvise
Memory advise.
@ eMADV_WillNeed
Expect access in the near future.
@ eMADV_Mergeable
KSM may merge identical pages.
@ eMADV_Normal
No further special treatment – by default.
@ eMADV_Random
Expect random page references.
@ eMADV_DontNeed
Do not expect access in the near future.
@ eMADV_Sequential
Expect sequential page references.
@ eMADV_DoFork
Do inherit across fork() – by default.
@ eMADV_DontFork
Don't inherit across fork()
@ eMADV_Unmergeable
KSM may not merge identical pages – by default.
@ fSuppress_Debug
Debug library.
@ fSuppress_System
System errors.
@ fSuppress_Runtime
Runtime library.
@ fSuppress_Exception
Unhandled exceptions.
void(* TLimitsPrintHandler)(ELimitsExitCode, size_t, CTime &, TLimitsPrintParameter)
Type of handler for printing a dump information after generating any limitation event.
Definition: ncbi_system.hpp:84
ELimitsExitCode
Process limits.
Definition: ncbi_system.hpp:63
@ eLEC_None
Normal exit.
Definition: ncbi_system.hpp:64
@ eLEC_Cpu
CPU time usage limit.
Definition: ncbi_system.hpp:66
@ eLEC_Memory
Memory limit.
Definition: ncbi_system.hpp:65
#define NCBI_OS_UNIX
#define NCBI_OS_DARWIN
Define class Dll and for Portable DLL handling.
Defines NCBI C++ Toolkit portable error codes.
Defines classes: CDirEntry, CFile, CDir, CSymLink, CMemoryFile, CFileUtil, CFileLock,...
Multi-threading – mutexes; rw-locks; semaphore.
double r(size_t dimension_, const Int4 *score_, const double *prob_, double theta_)
#define BOOL
Definition: odbcinst.h:18
#define CLOCKS_PER_SEC
Definition: pcretest.c:1019
static pcre_uint8 * buffer
Definition: pcretest.c:1051
unsigned int DWORD
Definition: sqltypes.h:98
#define CALLBACK
Definition: sqltypes.h:65
#define NcbiSys_strerror
Definition: ncbisys.hpp:105
#define _TROUBLE
#define _ASSERT
Modified on Sun Apr 14 05:27:53 2024 by modify_doxy.py rev. 669887