cpucount.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #include "cpucount.h"
  2. #ifndef BSD
  3. # ifndef __linux__
  4. // FreeBSD
  5. # ifdef __FreeBSD__
  6. # undef BSD
  7. # define BSD
  8. # endif
  9. // OpenBSD
  10. # ifdef __OpenBSD__
  11. # undef BSD
  12. # define BSD
  13. # endif
  14. // NetBSD
  15. # ifdef __NetBSD__
  16. # undef BSD
  17. # define BSD
  18. # endif
  19. // DragonFly
  20. # ifdef __DragonFly__
  21. # undef BSD
  22. # define BSD
  23. # endif
  24. # endif // __linux__
  25. // sys/param.h may have its own define
  26. # ifdef BSD
  27. # undef BSD
  28. # include <sys/param.h>
  29. # define SYS_PARAM_INCLUDED
  30. # ifndef BSD
  31. # define BSD
  32. # endif
  33. # endif
  34. #endif // BSD
  35. #ifdef BSD
  36. # ifndef SYS_PARAM_INCLUDED
  37. # include <sys/param.h>
  38. # endif
  39. # include <sys/sysctl.h>
  40. #endif
  41. #include <string.h>
  42. #ifndef _WIN32
  43. #include <unistd.h>
  44. #else
  45. #define UNICODE 1
  46. #include <windows.h>
  47. #endif
  48. #ifdef __linux__
  49. #include <stdio.h>
  50. #include <stdlib.h>
  51. #include <strings.h>
  52. static int parsecpuinfo(void)
  53. {
  54. unsigned char cpubitmap[128];
  55. memset(cpubitmap,0,sizeof(cpubitmap));
  56. FILE *f = fopen("/proc/cpuinfo","r");
  57. if (!f)
  58. return -1;
  59. char buf[8192];
  60. while (fgets(buf,sizeof(buf),f)) {
  61. // we don't like newlines
  62. for (char *p = buf;*p;++p) {
  63. if (*p == '\n') {
  64. *p = 0;
  65. break;
  66. }
  67. }
  68. // split ':'
  69. char *v = 0;
  70. for (char *p = buf;*p;++p) {
  71. if (*p == ':') {
  72. *p = 0;
  73. v = p + 1;
  74. break;
  75. }
  76. }
  77. // key padding
  78. size_t kl = strlen(buf);
  79. while (kl > 0 && (buf[kl - 1] == '\t' || buf[kl - 1] == ' ')) {
  80. --kl;
  81. buf[kl] = 0;
  82. }
  83. // space before value
  84. if (v) {
  85. while (*v && (*v == ' ' || *v == '\t'))
  86. ++v;
  87. }
  88. // check what we need
  89. if (strcasecmp(buf,"processor") == 0 && v) {
  90. char *endp = 0;
  91. long n = strtol(v,&endp,10);
  92. if (endp && endp > v && n >= 0 && (size_t)n < sizeof(cpubitmap) * 8)
  93. cpubitmap[n / 8] |= 1 << (n % 8);
  94. }
  95. }
  96. fclose(f);
  97. // count bits in bitmap
  98. int ncpu = 0;
  99. for (size_t n = 0;n < sizeof(cpubitmap) * 8;++n)
  100. if (cpubitmap[n / 8] & (1 << (n % 8)))
  101. ++ncpu;
  102. return ncpu;
  103. }
  104. #endif
  105. int cpucount(void)
  106. {
  107. int ncpu;
  108. #ifdef _SC_NPROCESSORS_ONLN
  109. ncpu = (int)sysconf(_SC_NPROCESSORS_ONLN);
  110. if (ncpu > 0)
  111. return ncpu;
  112. #endif
  113. #ifdef __linux__
  114. // try parsing /proc/cpuinfo
  115. // NOTE seems cygwin can provide this too, idk if need tho
  116. ncpu = parsecpuinfo();
  117. if (ncpu > 0)
  118. return ncpu;
  119. #endif
  120. #ifdef BSD
  121. const int ctlname[2] = {CTL_HW,HW_NCPU};
  122. size_t ctllen = sizeof(ncpu);
  123. if (sysctl(ctlname,2,&ncpu,&ctllen,0,0) < 0)
  124. ncpu = -1;
  125. if (ncpu > 0)
  126. return ncpu;
  127. #endif
  128. #ifdef _WIN32
  129. SYSTEM_INFO sysinfo;
  130. GetSystemInfo(&sysinfo);
  131. ncpu = (int)sysinfo.dwNumberOfProcessors;
  132. if (ncpu > 0)
  133. return ncpu;
  134. #endif
  135. (void) ncpu;
  136. return -1;
  137. }