1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    The code included in this file is provided under the terms of the ISC license
11    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12    To use, copy, modify, and/or distribute this software for any purpose with or
13    without fee is hereby granted provided that the above copyright notice and
14    this permission notice appear in all copies.
15 
16    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18    DISCLAIMED.
19 
20   ==============================================================================
21 */
22 
23 #if defined(__FreeBSD__) || defined(__DragonFly__)
24 #include <sys/sysinfo.h>
25 #endif
26 
27 #if JUCE_BELA
28 extern "C" int cobalt_thread_mode();
29 #endif
30 
31 namespace juce
32 {
33 
outputDebugString(const String & text)34 void Logger::outputDebugString (const String& text)
35 {
36     std::cerr << text << std::endl;
37 }
38 
39 //==============================================================================
getOperatingSystemType()40 SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
41 {
42     return Linux;
43 }
44 
getOperatingSystemName()45 String SystemStats::getOperatingSystemName()
46 {
47     return "Linux";
48 }
49 
isOperatingSystem64Bit()50 bool SystemStats::isOperatingSystem64Bit()
51 {
52    #if JUCE_64BIT
53     return true;
54    #else
55     //xxx not sure how to find this out?..
56     return false;
57    #endif
58 }
59 
60 //==============================================================================
getCpuInfo(const char * key)61 static String getCpuInfo (const char* key)
62 {
63     return readPosixConfigFileValue ("/proc/cpuinfo", key);
64 }
65 
getDeviceDescription()66 String SystemStats::getDeviceDescription()
67 {
68     return getCpuInfo ("Hardware");
69 }
70 
getDeviceManufacturer()71 String SystemStats::getDeviceManufacturer()
72 {
73     return {};
74 }
75 
getCpuVendor()76 String SystemStats::getCpuVendor()
77 {
78     auto v = getCpuInfo ("vendor_id");
79 
80     if (v.isEmpty())
81         v = getCpuInfo ("model name");
82 
83     return v;
84 }
85 
getCpuModel()86 String SystemStats::getCpuModel()
87 {
88     return getCpuInfo ("model name");
89 }
90 
getCpuSpeedInMegahertz()91 int SystemStats::getCpuSpeedInMegahertz()
92 {
93     return roundToInt (getCpuInfo ("cpu MHz").getFloatValue());
94 }
95 
getMemorySizeInMegabytes()96 int SystemStats::getMemorySizeInMegabytes()
97 {
98     struct sysinfo sysi;
99 
100     if (sysinfo (&sysi) == 0)
101         return (int) (sysi.totalram * sysi.mem_unit / (1024 * 1024));
102 
103     return 0;
104 }
105 
getPageSize()106 int SystemStats::getPageSize()
107 {
108     return (int) sysconf (_SC_PAGESIZE);
109 }
110 
111 //==============================================================================
getLogonName()112 String SystemStats::getLogonName()
113 {
114     if (auto user = getenv ("USER"))
115         return String::fromUTF8 (user);
116 
117     if (auto pw = getpwuid (getuid()))
118         return String::fromUTF8 (pw->pw_name);
119 
120     return {};
121 }
122 
getFullUserName()123 String SystemStats::getFullUserName()
124 {
125     return getLogonName();
126 }
127 
getComputerName()128 String SystemStats::getComputerName()
129 {
130     char name[256] = {};
131 
132     if (gethostname (name, sizeof (name) - 1) == 0)
133         return name;
134 
135     return {};
136 }
137 
getLocaleValue(nl_item key)138 static String getLocaleValue (nl_item key)
139 {
140     auto oldLocale = ::setlocale (LC_ALL, "");
141     auto result = String::fromUTF8 (nl_langinfo (key));
142     ::setlocale (LC_ALL, oldLocale);
143     return result;
144 }
145 
146 #if JUCE_BSD
getUserLanguage()147 String SystemStats::getUserLanguage()     { return String(); }
getUserRegion()148 String SystemStats::getUserRegion()       { return String(); }
149 #else
getUserLanguage()150 String SystemStats::getUserLanguage()     { return getLocaleValue (_NL_IDENTIFICATION_LANGUAGE); }
getUserRegion()151 String SystemStats::getUserRegion()       { return getLocaleValue (_NL_IDENTIFICATION_TERRITORY); }
152 #endif
getDisplayLanguage()153 String SystemStats::getDisplayLanguage()  { return getUserLanguage() + "-" + getUserRegion(); }
154 
155 //==============================================================================
initialise()156 void CPUInformation::initialise() noexcept
157 {
158     auto flags = getCpuInfo ("flags");
159 
160     hasMMX             = flags.contains ("mmx");
161     hasFMA3            = flags.contains ("fma");
162     hasFMA4            = flags.contains ("fma4");
163     hasSSE             = flags.contains ("sse");
164     hasSSE2            = flags.contains ("sse2");
165     hasSSE3            = flags.contains ("sse3");
166     has3DNow           = flags.contains ("3dnow");
167     hasSSSE3           = flags.contains ("ssse3");
168     hasSSE41           = flags.contains ("sse4_1");
169     hasSSE42           = flags.contains ("sse4_2");
170     hasAVX             = flags.contains ("avx");
171     hasAVX2            = flags.contains ("avx2");
172     hasAVX512F         = flags.contains ("avx512f");
173     hasAVX512BW        = flags.contains ("avx512bw");
174     hasAVX512CD        = flags.contains ("avx512cd");
175     hasAVX512DQ        = flags.contains ("avx512dq");
176     hasAVX512ER        = flags.contains ("avx512er");
177     hasAVX512IFMA      = flags.contains ("avx512ifma");
178     hasAVX512PF        = flags.contains ("avx512pf");
179     hasAVX512VBMI      = flags.contains ("avx512vbmi");
180     hasAVX512VL        = flags.contains ("avx512vl");
181     hasAVX512VPOPCNTDQ = flags.contains ("avx512_vpopcntdq");
182 
183     numLogicalCPUs  = getCpuInfo ("processor").getIntValue() + 1;
184 
185     // Assume CPUs in all sockets have the same number of cores
186     numPhysicalCPUs = getCpuInfo ("cpu cores").getIntValue() * (getCpuInfo ("physical id").getIntValue() + 1);
187 
188     if (numPhysicalCPUs <= 0)
189         numPhysicalCPUs = numLogicalCPUs;
190 }
191 
192 //==============================================================================
juce_millisecondsSinceStartup()193 uint32 juce_millisecondsSinceStartup() noexcept
194 {
195     return (uint32) (Time::getHighResolutionTicks() / 1000);
196 }
197 
getHighResolutionTicks()198 int64 Time::getHighResolutionTicks() noexcept
199 {
200     timespec t;
201 
202    #if JUCE_BELA
203     if (cobalt_thread_mode() == 0x200 /*XNRELAX*/)
204         clock_gettime (CLOCK_MONOTONIC, &t);
205     else
206         __wrap_clock_gettime (CLOCK_MONOTONIC, &t);
207    #else
208     clock_gettime (CLOCK_MONOTONIC, &t);
209    #endif
210 
211     return (t.tv_sec * (int64) 1000000) + (t.tv_nsec / 1000);
212 }
213 
getHighResolutionTicksPerSecond()214 int64 Time::getHighResolutionTicksPerSecond() noexcept
215 {
216     return 1000000;  // (microseconds)
217 }
218 
getMillisecondCounterHiRes()219 double Time::getMillisecondCounterHiRes() noexcept
220 {
221     return (double) getHighResolutionTicks() * 0.001;
222 }
223 
setSystemTimeToThisTime() const224 bool Time::setSystemTimeToThisTime() const
225 {
226     timeval t;
227     t.tv_sec = decltype (timeval::tv_sec) (millisSinceEpoch / 1000);
228     t.tv_usec = decltype (timeval::tv_usec) ((millisSinceEpoch - t.tv_sec * 1000) * 1000);
229 
230     return settimeofday (&t, nullptr) == 0;
231 }
232 
juce_isRunningUnderDebugger()233 JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() noexcept
234 {
235    #if JUCE_BSD
236     return false;
237    #else
238     return readPosixConfigFileValue ("/proc/self/status", "TracerPid").getIntValue() > 0;
239    #endif
240 }
241 
242 } // namespace juce
243