sysinfos.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. /**
  2. * Unit to read cpu informations
  3. *
  4. * tpruvot 2014
  5. */
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "miner.h"
  11. #ifndef WIN32
  12. #define HWMON_PATH \
  13. "/sys/devices/platform/coretemp.0/hwmon/hwmon1/temp1_input"
  14. #define HWMON_ALT \
  15. "/sys/class/hwmon/hwmon1/temp1_input"
  16. #define HWMON_ALT2 \
  17. "/sys/class/hwmon/hwmon0/temp1_input"
  18. #define HWMON_ALT3 \
  19. "/sys/devices/platform/coretemp.0/hwmon/hwmon0/temp2_input"
  20. #define HWMON_ALT4 \
  21. "/sys/class/hwmon/hwmon0/temp2_input"
  22. #define HWMON_ALT5 \
  23. "/sys/class/hwmon/hwmon0/device/temp1_input"
  24. #define HWMON_ALT6 \
  25. "/sys/class/thermal/thermal_zone0/temp"
  26. static float linux_cputemp(int core)
  27. {
  28. float tc = 0.0;
  29. FILE *fd = fopen(HWMON_PATH, "r");
  30. uint32_t val = 0;
  31. if (!fd)
  32. fd = fopen(HWMON_ALT, "r");
  33. if (!fd)
  34. fd = fopen(HWMON_ALT2, "r");
  35. if (!fd)
  36. fd = fopen(HWMON_ALT3, "r");
  37. if (!fd)
  38. fd = fopen(HWMON_ALT4, "r");
  39. if (!fd)
  40. fd = fopen(HWMON_ALT5, "r");
  41. if (!fd)
  42. fd = fopen(HWMON_ALT6, "r");
  43. if (!fd)
  44. return tc;
  45. if (fscanf(fd, "%d", &val))
  46. tc = val / 1000.0;
  47. fclose(fd);
  48. return tc;
  49. }
  50. #define CPUFREQ_PATH \
  51. "/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_cur_freq"
  52. static uint32_t linux_cpufreq(int core)
  53. {
  54. FILE *fd = fopen(CPUFREQ_PATH, "r");
  55. uint32_t freq = 0;
  56. if (!fd)
  57. return freq;
  58. if (!fscanf(fd, "%d", &freq))
  59. return freq;
  60. fclose(fd);
  61. return freq;
  62. }
  63. #else /* WIN32 */
  64. static float win32_cputemp(int core)
  65. {
  66. // todo
  67. return 0.0;
  68. }
  69. #endif /* !WIN32 */
  70. /* exports */
  71. float cpu_temp(int core)
  72. {
  73. #ifdef WIN32
  74. return win32_cputemp(core);
  75. #else
  76. return linux_cputemp(core);
  77. #endif
  78. }
  79. uint32_t cpu_clock(int core)
  80. {
  81. #ifdef WIN32
  82. return 0;
  83. #else
  84. return linux_cpufreq(core);
  85. #endif
  86. }
  87. int cpu_fanpercent()
  88. {
  89. return 0;
  90. }
  91. #if !defined(__arm__) && !defined(__aarch64__)
  92. static inline void cpuid(int functionnumber, int output[4]) {
  93. #ifdef _MSC_VER
  94. // Microsoft compiler, intrin.h included
  95. __cpuidex(output, functionnumber, 0);
  96. #elif defined(__INTEL_COMPILER)
  97. __cpuid(output, functionnumber);
  98. #elif defined(__GNUC__) || defined(__clang__)
  99. // use inline assembly, Gnu/AT&T syntax
  100. int a, b, c, d;
  101. asm volatile("cpuid" : "=a"(a), "=b"(b), "=c"(c), "=d"(d) : "a"(functionnumber), "c"(0));
  102. output[0] = a;
  103. output[1] = b;
  104. output[2] = c;
  105. output[3] = d;
  106. #else
  107. // unknown platform. try inline assembly with masm/intel syntax
  108. __asm {
  109. mov eax, functionnumber
  110. xor ecx, ecx
  111. cpuid;
  112. mov esi, output
  113. mov[esi], eax
  114. mov[esi + 4], ebx
  115. mov[esi + 8], ecx
  116. mov[esi + 12], edx
  117. }
  118. #endif
  119. }
  120. #else /* !__arm__ */
  121. #define cpuid(fn, out) out[0] = 0;
  122. #endif
  123. // For the i7-5775C will output : Intel(R) Core(TM) i7-5775C CPU @ 3.30GHz
  124. void cpu_getname(char *outbuf, size_t maxsz)
  125. {
  126. memset(outbuf, 0, maxsz);
  127. #ifdef WIN32
  128. char brand[0xC0] = { 0 };
  129. int output[4] = { 0 }, ext;
  130. cpuid(0x80000000, output);
  131. ext = output[0];
  132. if (ext >= 0x80000004) {
  133. for (int i = 2; i <= (ext & 0xF); i++) {
  134. cpuid(0x80000000+i, output);
  135. memcpy(&brand[(i-2) * 4*sizeof(int)], output, 4*sizeof(int));
  136. }
  137. snprintf(outbuf, maxsz, "%s", brand);
  138. } else {
  139. // Fallback, for the i7-5775C will output
  140. // Intel64 Family 6 Model 71 Stepping 1, GenuineIntel
  141. snprintf(outbuf, maxsz, "%s", getenv("PROCESSOR_IDENTIFIER"));
  142. }
  143. #else
  144. // Intel(R) Xeon(R) CPU E3-1245 V2 @ 3.40GHz
  145. FILE *fd = fopen("/proc/cpuinfo", "rb");
  146. char *buf = NULL, *p, *eol;
  147. size_t size = 0;
  148. if (!fd) return;
  149. while(getdelim(&buf, &size, 0, fd) != -1) {
  150. if (buf && (p = strstr(buf, "model name\t")) && strstr(p, ":")) {
  151. p = strstr(p, ":");
  152. if (p) {
  153. p += 2;
  154. eol = strstr(p, "\n"); if (eol) *eol = '\0';
  155. snprintf(outbuf, maxsz, "%s", p);
  156. }
  157. break;
  158. }
  159. }
  160. free(buf);
  161. fclose(fd);
  162. #endif
  163. }
  164. void cpu_getmodelid(char *outbuf, size_t maxsz)
  165. {
  166. memset(outbuf, 0, maxsz);
  167. #ifdef WIN32
  168. // For the i7-5775C will output 6:4701:8
  169. snprintf(outbuf, maxsz, "%s:%s:%s", getenv("PROCESSOR_LEVEL"), // hexa ?
  170. getenv("PROCESSOR_REVISION"), getenv("NUMBER_OF_PROCESSORS"));
  171. #else
  172. FILE *fd = fopen("/proc/cpuinfo", "rb");
  173. char *buf = NULL, *p, *eol;
  174. int cpufam = 0, model = 0, stepping = 0;
  175. size_t size = 0;
  176. if (!fd) return;
  177. while(getdelim(&buf, &size, 0, fd) != -1) {
  178. if (buf && (p = strstr(buf, "cpu family\t")) && strstr(p, ":")) {
  179. p = strstr(p, ":");
  180. if (p) {
  181. p += 2;
  182. cpufam = atoi(p);
  183. }
  184. }
  185. if (buf && (p = strstr(buf, "model\t")) && strstr(p, ":")) {
  186. p = strstr(p, ":");
  187. if (p) {
  188. p += 2;
  189. model = atoi(p);
  190. }
  191. }
  192. if (buf && (p = strstr(buf, "stepping\t")) && strstr(p, ":")) {
  193. p = strstr(p, ":");
  194. if (p) {
  195. p += 2;
  196. stepping = atoi(p);
  197. }
  198. }
  199. if (cpufam && model && stepping) {
  200. snprintf(outbuf, maxsz, "%x:%02x%02x:%d", cpufam, model, stepping, num_cpus);
  201. outbuf[maxsz-1] = '\0';
  202. break;
  203. }
  204. }
  205. free(buf);
  206. fclose(fd);
  207. #endif
  208. }
  209. // http://en.wikipedia.org/wiki/CPUID
  210. #define OSXSAVE_Flag (1 << 27)
  211. #define AVX1_Flag ((1 << 28)|OSXSAVE_Flag)
  212. #define XOP_Flag (1 << 11)
  213. #define FMA3_Flag ((1 << 12)|AVX1_Flag|OSXSAVE_Flag)
  214. #define AES_Flag (1 << 25)
  215. #define SSE42_Flag (1 << 20)
  216. #define SSE_Flag (1 << 25) // EDX
  217. #define SSE2_Flag (1 << 26) // EDX
  218. #define AVX2_Flag (1 << 5) // ADV EBX
  219. bool has_aes_ni()
  220. {
  221. #if defined(__arm__) || defined(__aarch64__)
  222. return false;
  223. #else
  224. int cpu_info[4] = { 0 };
  225. cpuid(1, cpu_info);
  226. return cpu_info[2] & AES_Flag;
  227. #endif
  228. }
  229. void cpu_bestfeature(char *outbuf, size_t maxsz)
  230. {
  231. #if defined(__arm__) || defined(__aarch64__)
  232. sprintf(outbuf, "ARM");
  233. #else
  234. int cpu_info[4] = { 0 };
  235. int cpu_info_adv[4] = { 0 };
  236. cpuid(1, cpu_info);
  237. cpuid(7, cpu_info_adv);
  238. if ((cpu_info[2] & AVX1_Flag) && (cpu_info_adv[1] & AVX2_Flag))
  239. sprintf(outbuf, "AVX2");
  240. else if (cpu_info[2] & AVX1_Flag)
  241. sprintf(outbuf, "AVX");
  242. else if (cpu_info[2] & FMA3_Flag)
  243. sprintf(outbuf, "FMA3");
  244. else if (cpu_info[2] & XOP_Flag)
  245. sprintf(outbuf, "XOP");
  246. else if (cpu_info[2] & SSE42_Flag)
  247. sprintf(outbuf, "SSE42");
  248. else if (cpu_info[3] & SSE2_Flag)
  249. sprintf(outbuf, "SSE2");
  250. else if (cpu_info[3] & SSE_Flag)
  251. sprintf(outbuf, "SSE");
  252. else
  253. *outbuf = '\0';
  254. #endif
  255. }