1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*-  vi:set ts=8 sts=4 sw=4: */
2 
3 /*
4     Rubber Band Library
5     An audio time-stretching and pitch-shifting library.
6     Copyright 2007-2021 Particular Programs Ltd.
7 
8     This program is free software; you can redistribute it and/or
9     modify it under the terms of the GNU General Public License as
10     published by the Free Software Foundation; either version 2 of the
11     License, or (at your option) any later version.  See the file
12     COPYING included with this distribution for more information.
13 
14     Alternatively, if you have a valid commercial licence for the
15     Rubber Band Library obtained by agreement with the copyright
16     holders, you may redistribute and/or modify it under the terms
17     described in that licence.
18 
19     If you wish to distribute code using the Rubber Band Library
20     under terms other than those of the GNU General Public License,
21     you must obtain a valid commercial licence before doing so.
22 */
23 
24 #include "sysutils.h"
25 
26 #ifdef _WIN32
27 #include <windows.h>
28 #include <fcntl.h>
29 #include <io.h>
30 #else /* !_WIN32 */
31 #include <signal.h>
32 #include <unistd.h>
33 #ifdef __APPLE__
34 #include <sys/sysctl.h>
35 #include <mach/mach.h>
36 #include <mach/mach_time.h>
37 #else /* !__APPLE__, !_WIN32 */
38 #include <stdio.h>
39 #include <string.h>
40 #endif /* !__APPLE__, !_WIN32 */
41 #endif /* !_WIN32 */
42 
43 #ifdef __sun
44 #include <sys/processor.h>
45 #endif
46 
47 #include <cstdlib>
48 #include <iostream>
49 
50 #ifdef HAVE_IPP
51 #include <ippversion.h>
52 #include <ipp.h>
53 #endif
54 
55 #ifdef HAVE_VDSP
56 #include <Accelerate/Accelerate.h>
57 #include <fenv.h>
58 #endif
59 
60 #ifdef _WIN32
61 #include <fstream>
62 #endif
63 
64 
65 namespace RubberBand {
66 
67 const char *
system_get_platform_tag()68 system_get_platform_tag()
69 {
70 #ifdef _WIN32
71     return "win32";
72 #else /* !_WIN32 */
73 #ifdef __APPLE__
74     return "osx";
75 #else /* !__APPLE__ */
76 #ifdef __LINUX__
77     if (sizeof(long) == 8) {
78         return "linux64";
79     } else {
80         return "linux";
81     }
82 #else /* !__LINUX__ */
83     return "posix";
84 #endif /* !__LINUX__ */
85 #endif /* !__APPLE__ */
86 #endif /* !_WIN32 */
87 }
88 
89 bool
system_is_multiprocessor()90 system_is_multiprocessor()
91 {
92     static bool tested = false, mp = false;
93 
94     if (tested) return mp;
95     int count = 0;
96 
97 #ifdef _WIN32
98 
99     SYSTEM_INFO sysinfo;
100     GetSystemInfo(&sysinfo);
101     count = sysinfo.dwNumberOfProcessors;
102 
103 #else /* !_WIN32 */
104 #ifdef __APPLE__
105 
106     size_t sz = sizeof(count);
107     if (sysctlbyname("hw.ncpu", &count, &sz, NULL, 0)) {
108         count = 0;
109         mp = false;
110     } else {
111         mp = (count > 1);
112     }
113 
114 #else /* !__APPLE__, !_WIN32 */
115 #ifdef __sun
116 
117     processorid_t i, n;
118     n = sysconf(_SC_CPUID_MAX);
119     for (i = 0; i <= n; ++i) {
120         int status = p_online(i, P_STATUS);
121         if (status == P_ONLINE) {
122             ++count;
123         }
124         if (count > 1) break;
125     }
126 
127 #else /* !__sun, !__APPLE__, !_WIN32 */
128 
129     //...
130 
131     FILE *cpuinfo = fopen("/proc/cpuinfo", "r");
132     if (!cpuinfo) return false;
133 
134     char buf[256];
135     while (!feof(cpuinfo)) {
136         if (!fgets(buf, 256, cpuinfo)) break;
137         if (!strncmp(buf, "processor", 9)) {
138             ++count;
139         }
140         if (count > 1) break;
141     }
142 
143     fclose(cpuinfo);
144 
145 #endif /* !__sun, !__APPLE__, !_WIN32 */
146 #endif /* !__APPLE__, !_WIN32 */
147 #endif /* !_WIN32 */
148 
149     mp = (count > 1);
150     tested = true;
151     return mp;
152 }
153 
154 #ifdef _WIN32
155 
gettimeofday(struct timeval * tv,void * tz)156 void gettimeofday(struct timeval *tv, void *tz)
157 {
158     union {
159 	long long ns100;
160 	FILETIME ft;
161     } now;
162 
163     ::GetSystemTimeAsFileTime(&now.ft);
164     tv->tv_usec = (long)((now.ns100 / 10LL) % 1000000LL);
165     tv->tv_sec = (long)((now.ns100 - 116444736000000000LL) / 10000000LL);
166 }
167 
usleep(unsigned long usec)168 void usleep(unsigned long usec)
169 {
170     ::Sleep(usec == 0 ? 0 : usec < 1000 ? 1 : usec / 1000);
171 }
172 
173 #endif
174 
system_specific_initialise()175 void system_specific_initialise()
176 {
177 #if defined HAVE_IPP
178 #ifndef USE_IPP_DYNAMIC_LIBS
179 #if (IPP_VERSION_MAJOR < 9)
180     // This was removed in v9
181     ippStaticInit();
182 #endif
183 #endif
184     ippSetDenormAreZeros(1);
185 #elif defined HAVE_VDSP
186 #if defined __i386__ || defined __x86_64__
187     fesetenv(FE_DFL_DISABLE_SSE_DENORMS_ENV);
188 #elif defined __arm64__
189     fesetenv(FE_DFL_DISABLE_DENORMS_ENV);
190 #endif
191 #endif
192 #if defined __ARMEL__
193     // ARM32
194     static const unsigned int x = 0x04086060;
195     static const unsigned int y = 0x03000000;
196     int r;
197     asm volatile (
198         "fmrx	%0, fpscr   \n\t"
199         "and	%0, %0, %1  \n\t"
200         "orr	%0, %0, %2  \n\t"
201         "fmxr	fpscr, %0   \n\t"
202         : "=r"(r)
203         : "r"(x), "r"(y)
204 	);
205 #endif
206 }
207 
system_specific_application_initialise()208 void system_specific_application_initialise()
209 {
210 }
211 
212 
213 ProcessStatus
system_get_process_status(int pid)214 system_get_process_status(int pid)
215 {
216 #ifdef _WIN32
217     HANDLE handle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
218     if (!handle) {
219         return ProcessNotRunning;
220     } else {
221         CloseHandle(handle);
222         return ProcessRunning;
223     }
224 #else
225     if (kill(getpid(), 0) == 0) {
226         if (kill(pid, 0) == 0) {
227             return ProcessRunning;
228         } else {
229             return ProcessNotRunning;
230         }
231     } else {
232         return UnknownProcessStatus;
233     }
234 #endif
235 }
236 
237 #ifdef _WIN32
system_memorybarrier()238 void system_memorybarrier()
239 {
240 #ifdef _MSC_VER
241     MemoryBarrier();
242 #else /* (mingw) */
243     LONG Barrier = 0;
244     __asm__ __volatile__("xchgl %%eax,%0 "
245                          : "=r" (Barrier));
246 #endif
247 }
248 #else /* !_WIN32 */
249 #if (__GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1)
250 // Not required
251 #else
252 #include <pthread.h>
system_memorybarrier()253 void system_memorybarrier()
254 {
255     pthread_mutex_t dummy = PTHREAD_MUTEX_INITIALIZER;
256     pthread_mutex_lock(&dummy);
257     pthread_mutex_unlock(&dummy);
258 }
259 #endif
260 #endif
261 
262 }
263 
264 
265 
266