blob: 5f97b1cde1d4e7d294493d25a34f0194f97173e1 [file] [log] [blame]
Rohit Jainf881ee82018-10-11 12:52:19 -07001/*
2 * Copyright (c) 2016-present, Przemyslaw Skibinski, Yann Collet, Facebook, Inc.
3 * All rights reserved.
4 *
5 * This source code is licensed under both the BSD-style license (found in the
6 * LICENSE file in the root directory of this source tree) and the GPLv2 (found
7 * in the COPYING file in the root directory of this source tree).
8 * You may select, at your option, one of the above-listed licenses.
9 */
10
11#if defined (__cplusplus)
12extern "C" {
13#endif
14
15
16/*-****************************************
17* Dependencies
18******************************************/
Yann Colletffba1422018-12-20 14:30:30 -080019#include "util.h" /* note : ensure that platform.h is included first ! */
Yann Collet173ef9d2018-12-19 18:30:57 -080020#include <errno.h>
Yann Collet72dbf1b2018-12-20 12:27:12 -080021#include <assert.h>
Yann Collet173ef9d2018-12-19 18:30:57 -080022
Rohit Jainf881ee82018-10-11 12:52:19 -070023
Yann Collet173ef9d2018-12-19 18:30:57 -080024int UTIL_fileExist(const char* filename)
25{
26 stat_t statbuf;
Yann Collet105fa952018-12-20 09:16:40 -080027#if defined(_MSC_VER)
28 int const stat_error = _stat64(filename, &statbuf);
29#else
30 int const stat_error = stat(filename, &statbuf);
31#endif
32 return !stat_error;
Yann Collet173ef9d2018-12-19 18:30:57 -080033}
34
Rohit Jaind6d240f2018-10-11 15:07:12 -070035int UTIL_isRegularFile(const char* infilename)
36{
37 stat_t statbuf;
38 return UTIL_getFileStat(infilename, &statbuf); /* Only need to know whether it is a regular file */
39}
40
41int UTIL_getFileStat(const char* infilename, stat_t *statbuf)
42{
43 int r;
44#if defined(_MSC_VER)
45 r = _stat64(infilename, statbuf);
46 if (r || !(statbuf->st_mode & S_IFREG)) return 0; /* No good... */
47#else
48 r = stat(infilename, statbuf);
49 if (r || !S_ISREG(statbuf->st_mode)) return 0; /* No good... */
50#endif
51 return 1;
52}
53
54int UTIL_setFileStat(const char *filename, stat_t *statbuf)
55{
56 int res = 0;
Rohit Jaind6d240f2018-10-11 15:07:12 -070057
58 if (!UTIL_isRegularFile(filename))
59 return -1;
60
W. Felix Handtee1ec8002019-09-12 16:27:05 -040061 /* set access and modification times */
Rosen Penev41e90652019-07-30 17:17:07 -070062#if defined(_WIN32) || (PLATFORM_POSIX_VERSION < 200809L)
W. Felix Handtee1ec8002019-09-12 16:27:05 -040063 {
64 struct utimbuf timebuf;
65 timebuf.actime = time(NULL);
66 timebuf.modtime = statbuf->st_mtime;
67 res += utime(filename, &timebuf);
68 }
Rosen Penev41e90652019-07-30 17:17:07 -070069#else
W. Felix Handtee1ec8002019-09-12 16:27:05 -040070 {
71 /* (atime, mtime) */
72 struct timespec timebuf[2] = { {0, UTIME_NOW}, statbuf->st_mtim };
73 res += utimensat(AT_FDCWD, filename, timebuf, 0);
74 }
Rosen Penev41e90652019-07-30 17:17:07 -070075#endif
Rohit Jaind6d240f2018-10-11 15:07:12 -070076
77#if !defined(_WIN32)
78 res += chown(filename, statbuf->st_uid, statbuf->st_gid); /* Copy ownership */
79#endif
80
81 res += chmod(filename, statbuf->st_mode & 07777); /* Copy file permissions */
82
83 errno = 0;
84 return -res; /* number of errors is returned */
85}
Rohit Jainf881ee82018-10-11 12:52:19 -070086
87U32 UTIL_isDirectory(const char* infilename)
88{
89 int r;
90 stat_t statbuf;
91#if defined(_MSC_VER)
92 r = _stat64(infilename, &statbuf);
93 if (!r && (statbuf.st_mode & _S_IFDIR)) return 1;
94#else
95 r = stat(infilename, &statbuf);
96 if (!r && S_ISDIR(statbuf.st_mode)) return 1;
97#endif
98 return 0;
99}
100
shakeelraoe5811e52019-03-23 19:04:56 -0700101int UTIL_isSameFile(const char* file1, const char* file2)
102{
103#if defined(_MSC_VER)
104 /* note : Visual does not support file identification by inode.
105 * The following work-around is limited to detecting exact name repetition only,
106 * aka `filename` is considered different from `subdir/../filename` */
107 return !strcmp(file1, file2);
108#else
109 stat_t file1Stat;
110 stat_t file2Stat;
111 return UTIL_getFileStat(file1, &file1Stat)
112 && UTIL_getFileStat(file2, &file2Stat)
113 && (file1Stat.st_dev == file2Stat.st_dev)
114 && (file1Stat.st_ino == file2Stat.st_ino);
115#endif
116}
117
Bimba Shrestha8a397482019-10-22 15:23:22 -0700118U32 UTIL_isFIFO(const char* infilename)
119{
120/* macro guards, as defined in : https://linux.die.net/man/2/lstat */
121#if PLATFORM_POSIX_VERSION >= 200112L
122 stat_t statbuf;
123 int r = UTIL_getFileStat(infilename, &statbuf);
124 if (!r && S_ISFIFO(statbuf.st_mode)) return 1;
125#endif
126 (void)infilename;
127 return 0;
128}
129
130
Rohit Jainf881ee82018-10-11 12:52:19 -0700131U32 UTIL_isLink(const char* infilename)
132{
133/* macro guards, as defined in : https://linux.die.net/man/2/lstat */
W. Felix Handted2c48042019-06-07 15:31:33 -0400134#if PLATFORM_POSIX_VERSION >= 200112L
Rohit Jainf881ee82018-10-11 12:52:19 -0700135 int r;
136 stat_t statbuf;
137 r = lstat(infilename, &statbuf);
138 if (!r && S_ISLNK(statbuf.st_mode)) return 1;
139#endif
Rohit Jainf881ee82018-10-11 12:52:19 -0700140 (void)infilename;
141 return 0;
142}
143
144U64 UTIL_getFileSize(const char* infilename)
145{
146 if (!UTIL_isRegularFile(infilename)) return UTIL_FILESIZE_UNKNOWN;
147 { int r;
148#if defined(_MSC_VER)
149 struct __stat64 statbuf;
150 r = _stat64(infilename, &statbuf);
151 if (r || !(statbuf.st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;
152#elif defined(__MINGW32__) && defined (__MSVCRT__)
153 struct _stati64 statbuf;
154 r = _stati64(infilename, &statbuf);
155 if (r || !(statbuf.st_mode & S_IFREG)) return UTIL_FILESIZE_UNKNOWN;
156#else
157 struct stat statbuf;
158 r = stat(infilename, &statbuf);
159 if (r || !S_ISREG(statbuf.st_mode)) return UTIL_FILESIZE_UNKNOWN;
160#endif
161 return (U64)statbuf.st_size;
162 }
163}
164
165
166U64 UTIL_getTotalFileSize(const char* const * const fileNamesTable, unsigned nbFiles)
167{
168 U64 total = 0;
169 int error = 0;
170 unsigned n;
171 for (n=0; n<nbFiles; n++) {
172 U64 const size = UTIL_getFileSize(fileNamesTable[n]);
173 error |= (size == UTIL_FILESIZE_UNKNOWN);
174 total += size;
175 }
176 return error ? UTIL_FILESIZE_UNKNOWN : total;
177}
178
Rohit Jainc7251e52018-10-11 18:05:15 -0700179#ifdef _WIN32
Rohit Jain705e0b12018-10-11 15:51:57 -0700180int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
181{
182 char* path;
183 int dirLength, fnameLength, pathLength, nbFiles = 0;
184 WIN32_FIND_DATAA cFile;
185 HANDLE hFile;
186
187 dirLength = (int)strlen(dirName);
188 path = (char*) malloc(dirLength + 3);
189 if (!path) return 0;
190
191 memcpy(path, dirName, dirLength);
192 path[dirLength] = '\\';
193 path[dirLength+1] = '*';
194 path[dirLength+2] = 0;
195
196 hFile=FindFirstFileA(path, &cFile);
197 if (hFile == INVALID_HANDLE_VALUE) {
198 UTIL_DISPLAYLEVEL(1, "Cannot open directory '%s'\n", dirName);
199 return 0;
200 }
201 free(path);
202
203 do {
204 fnameLength = (int)strlen(cFile.cFileName);
205 path = (char*) malloc(dirLength + fnameLength + 2);
206 if (!path) { FindClose(hFile); return 0; }
207 memcpy(path, dirName, dirLength);
208 path[dirLength] = '\\';
209 memcpy(path+dirLength+1, cFile.cFileName, fnameLength);
210 pathLength = dirLength+1+fnameLength;
211 path[pathLength] = 0;
212 if (cFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
Yann Collet72dbf1b2018-12-20 12:27:12 -0800213 if ( strcmp (cFile.cFileName, "..") == 0
214 || strcmp (cFile.cFileName, ".") == 0 )
215 continue;
216 /* Recursively call "UTIL_prepareFileList" with the new path. */
217 nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks);
Rohit Jain705e0b12018-10-11 15:51:57 -0700218 if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
Yann Collet72dbf1b2018-12-20 12:27:12 -0800219 } else if ( (cFile.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)
220 || (cFile.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE)
221 || (cFile.dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) ) {
Rohit Jain705e0b12018-10-11 15:51:57 -0700222 if (*bufStart + *pos + pathLength >= *bufEnd) {
Yann Collet72dbf1b2018-12-20 12:27:12 -0800223 ptrdiff_t const newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
Rohit Jain705e0b12018-10-11 15:51:57 -0700224 *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
Rohit Jain705e0b12018-10-11 15:51:57 -0700225 if (*bufStart == NULL) { free(path); FindClose(hFile); return 0; }
Yann Collet72dbf1b2018-12-20 12:27:12 -0800226 *bufEnd = *bufStart + newListSize;
Rohit Jain705e0b12018-10-11 15:51:57 -0700227 }
228 if (*bufStart + *pos + pathLength < *bufEnd) {
Yann Collet72dbf1b2018-12-20 12:27:12 -0800229 memcpy(*bufStart + *pos, path, pathLength+1 /* include final \0 */);
Rohit Jain705e0b12018-10-11 15:51:57 -0700230 *pos += pathLength + 1;
231 nbFiles++;
232 }
233 }
234 free(path);
235 } while (FindNextFileA(hFile, &cFile));
236
237 FindClose(hFile);
238 return nbFiles;
239}
240
241#elif defined(__linux__) || (PLATFORM_POSIX_VERSION >= 200112L) /* opendir, readdir require POSIX.1-2001 */
242
243int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
244{
245 DIR *dir;
246 struct dirent *entry;
247 char* path;
248 int dirLength, fnameLength, pathLength, nbFiles = 0;
249
250 if (!(dir = opendir(dirName))) {
251 UTIL_DISPLAYLEVEL(1, "Cannot open directory '%s': %s\n", dirName, strerror(errno));
252 return 0;
253 }
254
255 dirLength = (int)strlen(dirName);
256 errno = 0;
257 while ((entry = readdir(dir)) != NULL) {
258 if (strcmp (entry->d_name, "..") == 0 ||
259 strcmp (entry->d_name, ".") == 0) continue;
260 fnameLength = (int)strlen(entry->d_name);
261 path = (char*) malloc(dirLength + fnameLength + 2);
262 if (!path) { closedir(dir); return 0; }
263 memcpy(path, dirName, dirLength);
264
265 path[dirLength] = '/';
266 memcpy(path+dirLength+1, entry->d_name, fnameLength);
267 pathLength = dirLength+1+fnameLength;
268 path[pathLength] = 0;
269
270 if (!followLinks && UTIL_isLink(path)) {
271 UTIL_DISPLAYLEVEL(2, "Warning : %s is a symbolic link, ignoring\n", path);
LeeYoung624793b94b2019-07-25 21:07:57 +0800272 free(path);
Rohit Jain705e0b12018-10-11 15:51:57 -0700273 continue;
274 }
275
276 if (UTIL_isDirectory(path)) {
277 nbFiles += UTIL_prepareFileList(path, bufStart, pos, bufEnd, followLinks); /* Recursively call "UTIL_prepareFileList" with the new path. */
278 if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
279 } else {
280 if (*bufStart + *pos + pathLength >= *bufEnd) {
281 ptrdiff_t newListSize = (*bufEnd - *bufStart) + LIST_SIZE_INCREASE;
282 *bufStart = (char*)UTIL_realloc(*bufStart, newListSize);
283 *bufEnd = *bufStart + newListSize;
284 if (*bufStart == NULL) { free(path); closedir(dir); return 0; }
285 }
286 if (*bufStart + *pos + pathLength < *bufEnd) {
Yann Collet72dbf1b2018-12-20 12:27:12 -0800287 memcpy(*bufStart + *pos, path, pathLength + 1); /* with final \0 */
Rohit Jain705e0b12018-10-11 15:51:57 -0700288 *pos += pathLength + 1;
289 nbFiles++;
290 }
291 }
292 free(path);
293 errno = 0; /* clear errno after UTIL_isDirectory, UTIL_prepareFileList */
294 }
295
296 if (errno != 0) {
297 UTIL_DISPLAYLEVEL(1, "readdir(%s) error: %s\n", dirName, strerror(errno));
298 free(*bufStart);
299 *bufStart = NULL;
300 }
301 closedir(dir);
302 return nbFiles;
303}
304
305#else
306
307int UTIL_prepareFileList(const char *dirName, char** bufStart, size_t* pos, char** bufEnd, int followLinks)
308{
309 (void)bufStart; (void)bufEnd; (void)pos; (void)followLinks;
310 UTIL_DISPLAYLEVEL(1, "Directory %s ignored (compiled without _WIN32 or _POSIX_C_SOURCE)\n", dirName);
311 return 0;
312}
313
314#endif /* #ifdef _WIN32 */
315
316/*
317 * UTIL_createFileList - takes a list of files and directories (params: inputNames, inputNamesNb), scans directories,
318 * and returns a new list of files (params: return value, allocatedBuffer, allocatedNamesNb).
319 * After finishing usage of the list the structures should be freed with UTIL_freeFileList(params: return value, allocatedBuffer)
320 * In case of error UTIL_createFileList returns NULL and UTIL_freeFileList should not be called.
321 */
322const char**
323UTIL_createFileList(const char **inputNames, unsigned inputNamesNb,
324 char** allocatedBuffer, unsigned* allocatedNamesNb,
325 int followLinks)
326{
327 size_t pos;
328 unsigned i, nbFiles;
329 char* buf = (char*)malloc(LIST_SIZE_INCREASE);
330 char* bufend = buf + LIST_SIZE_INCREASE;
331 const char** fileTable;
332
333 if (!buf) return NULL;
334
335 for (i=0, pos=0, nbFiles=0; i<inputNamesNb; i++) {
336 if (!UTIL_isDirectory(inputNames[i])) {
337 size_t const len = strlen(inputNames[i]);
338 if (buf + pos + len >= bufend) {
339 ptrdiff_t newListSize = (bufend - buf) + LIST_SIZE_INCREASE;
340 buf = (char*)UTIL_realloc(buf, newListSize);
341 bufend = buf + newListSize;
342 if (!buf) return NULL;
343 }
344 if (buf + pos + len < bufend) {
Yann Collet72dbf1b2018-12-20 12:27:12 -0800345 memcpy(buf+pos, inputNames[i], len+1); /* with final \0 */
Rohit Jain705e0b12018-10-11 15:51:57 -0700346 pos += len + 1;
347 nbFiles++;
348 }
349 } else {
350 nbFiles += UTIL_prepareFileList(inputNames[i], &buf, &pos, &bufend, followLinks);
351 if (buf == NULL) return NULL;
352 } }
353
354 if (nbFiles == 0) { free(buf); return NULL; }
355
356 fileTable = (const char**)malloc((nbFiles+1) * sizeof(const char*));
357 if (!fileTable) { free(buf); return NULL; }
358
359 for (i=0, pos=0; i<nbFiles; i++) {
360 fileTable[i] = buf + pos;
361 pos += strlen(fileTable[i]) + 1;
362 }
363
364 if (buf + pos > bufend) { free(buf); free((void*)fileTable); return NULL; }
365
366 *allocatedBuffer = buf;
367 *allocatedNamesNb = nbFiles;
368
369 return fileTable;
370}
371
Yann Collet59a71162019-04-10 12:37:03 -0700372
Rohit Jaind6d240f2018-10-11 15:07:12 -0700373/*-****************************************
Rohit Jaina47f6e62018-10-11 16:51:29 -0700374* Console log
375******************************************/
376int g_utilDisplayLevel;
377
Yann Collet72dbf1b2018-12-20 12:27:12 -0800378
Yann Collet59a71162019-04-10 12:37:03 -0700379
Rohit Jaina47f6e62018-10-11 16:51:29 -0700380/*-****************************************
Yann Collet59a71162019-04-10 12:37:03 -0700381* count the number of physical cores
Rohit Jaind6d240f2018-10-11 15:07:12 -0700382******************************************/
Rohit Jainc7251e52018-10-11 18:05:15 -0700383
Rohit Jain91b2fed2018-10-11 17:34:47 -0700384#if defined(_WIN32) || defined(WIN32)
385
386#include <windows.h>
387
388typedef BOOL(WINAPI* LPFN_GLPI)(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD);
389
390int UTIL_countPhysicalCores(void)
391{
392 static int numPhysicalCores = 0;
393 if (numPhysicalCores != 0) return numPhysicalCores;
394
395 { LPFN_GLPI glpi;
396 BOOL done = FALSE;
397 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL;
398 PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL;
399 DWORD returnLength = 0;
400 size_t byteOffset = 0;
401
402 glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")),
403 "GetLogicalProcessorInformation");
404
405 if (glpi == NULL) {
406 goto failed;
407 }
408
409 while(!done) {
410 DWORD rc = glpi(buffer, &returnLength);
411 if (FALSE == rc) {
412 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
413 if (buffer)
414 free(buffer);
415 buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc(returnLength);
416
417 if (buffer == NULL) {
418 perror("zstd");
419 exit(1);
420 }
421 } else {
422 /* some other error */
423 goto failed;
424 }
425 } else {
426 done = TRUE;
427 }
428 }
429
430 ptr = buffer;
431
432 while (byteOffset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= returnLength) {
433
434 if (ptr->Relationship == RelationProcessorCore) {
435 numPhysicalCores++;
436 }
437
438 ptr++;
439 byteOffset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION);
440 }
441
442 free(buffer);
443
444 return numPhysicalCores;
445 }
446
447failed:
448 /* try to fall back on GetSystemInfo */
449 { SYSTEM_INFO sysinfo;
450 GetSystemInfo(&sysinfo);
451 numPhysicalCores = sysinfo.dwNumberOfProcessors;
452 if (numPhysicalCores == 0) numPhysicalCores = 1; /* just in case */
453 }
454 return numPhysicalCores;
455}
456
457#elif defined(__APPLE__)
458
459#include <sys/sysctl.h>
460
461/* Use apple-provided syscall
462 * see: man 3 sysctl */
463int UTIL_countPhysicalCores(void)
464{
465 static S32 numPhysicalCores = 0; /* apple specifies int32_t */
466 if (numPhysicalCores != 0) return numPhysicalCores;
467
468 { size_t size = sizeof(S32);
469 int const ret = sysctlbyname("hw.physicalcpu", &numPhysicalCores, &size, NULL, 0);
470 if (ret != 0) {
471 if (errno == ENOENT) {
472 /* entry not present, fall back on 1 */
473 numPhysicalCores = 1;
474 } else {
475 perror("zstd: can't get number of physical cpus");
476 exit(1);
477 }
478 }
479
480 return numPhysicalCores;
481 }
482}
483
484#elif defined(__linux__)
485
486/* parse /proc/cpuinfo
487 * siblings / cpu cores should give hyperthreading ratio
488 * otherwise fall back on sysconf */
489int UTIL_countPhysicalCores(void)
490{
491 static int numPhysicalCores = 0;
492
493 if (numPhysicalCores != 0) return numPhysicalCores;
494
495 numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
496 if (numPhysicalCores == -1) {
497 /* value not queryable, fall back on 1 */
498 return numPhysicalCores = 1;
499 }
500
501 /* try to determine if there's hyperthreading */
502 { FILE* const cpuinfo = fopen("/proc/cpuinfo", "r");
503#define BUF_SIZE 80
504 char buff[BUF_SIZE];
505
506 int siblings = 0;
507 int cpu_cores = 0;
508 int ratio = 1;
509
510 if (cpuinfo == NULL) {
511 /* fall back on the sysconf value */
512 return numPhysicalCores;
513 }
514
515 /* assume the cpu cores/siblings values will be constant across all
516 * present processors */
517 while (!feof(cpuinfo)) {
518 if (fgets(buff, BUF_SIZE, cpuinfo) != NULL) {
519 if (strncmp(buff, "siblings", 8) == 0) {
520 const char* const sep = strchr(buff, ':');
LeeYoung624c5caaf52019-07-29 17:05:50 +0800521 if (sep == NULL || *sep == '\0') {
Rohit Jain91b2fed2018-10-11 17:34:47 -0700522 /* formatting was broken? */
523 goto failed;
524 }
525
526 siblings = atoi(sep + 1);
527 }
528 if (strncmp(buff, "cpu cores", 9) == 0) {
529 const char* const sep = strchr(buff, ':');
LeeYoung624c5caaf52019-07-29 17:05:50 +0800530 if (sep == NULL || *sep == '\0') {
Rohit Jain91b2fed2018-10-11 17:34:47 -0700531 /* formatting was broken? */
532 goto failed;
533 }
534
535 cpu_cores = atoi(sep + 1);
536 }
537 } else if (ferror(cpuinfo)) {
538 /* fall back on the sysconf value */
539 goto failed;
540 }
541 }
542 if (siblings && cpu_cores) {
543 ratio = siblings / cpu_cores;
544 }
545failed:
546 fclose(cpuinfo);
547 return numPhysicalCores = numPhysicalCores / ratio;
548 }
549}
550
Conrad Meyerfe826372019-01-04 11:57:12 -0800551#elif defined(__FreeBSD__)
Rohit Jain91b2fed2018-10-11 17:34:47 -0700552
Conrad Meyerfe826372019-01-04 11:57:12 -0800553#include <sys/param.h>
554#include <sys/sysctl.h>
555
556/* Use physical core sysctl when available
557 * see: man 4 smp, man 3 sysctl */
558int UTIL_countPhysicalCores(void)
559{
560 static int numPhysicalCores = 0; /* freebsd sysctl is native int sized */
561 if (numPhysicalCores != 0) return numPhysicalCores;
562
563#if __FreeBSD_version >= 1300008
564 { size_t size = sizeof(numPhysicalCores);
565 int ret = sysctlbyname("kern.smp.cores", &numPhysicalCores, &size, NULL, 0);
566 if (ret == 0) return numPhysicalCores;
567 if (errno != ENOENT) {
568 perror("zstd: can't get number of physical cpus");
569 exit(1);
570 }
571 /* sysctl not present, fall through to older sysconf method */
572 }
573#endif
574
575 numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
576 if (numPhysicalCores == -1) {
577 /* value not queryable, fall back on 1 */
578 numPhysicalCores = 1;
579 }
580 return numPhysicalCores;
581}
582
583#elif defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
584
585/* Use POSIX sysconf
586 * see: man 3 sysconf */
Rohit Jain91b2fed2018-10-11 17:34:47 -0700587int UTIL_countPhysicalCores(void)
588{
589 static int numPhysicalCores = 0;
590
591 if (numPhysicalCores != 0) return numPhysicalCores;
592
593 numPhysicalCores = (int)sysconf(_SC_NPROCESSORS_ONLN);
594 if (numPhysicalCores == -1) {
595 /* value not queryable, fall back on 1 */
596 return numPhysicalCores = 1;
597 }
598 return numPhysicalCores;
599}
600
601#else
602
603int UTIL_countPhysicalCores(void)
604{
605 /* assume 1 */
606 return 1;
607}
608
609#endif
610
Rohit Jainf881ee82018-10-11 12:52:19 -0700611#if defined (__cplusplus)
612}
613#endif