1 // Windows/System.cpp
2 
3 #include "StdAfx.h"
4 
5 #ifndef _WIN32
6 #include <unistd.h>
7 #ifdef __APPLE__
8 #include <sys/sysctl.h>
9 #else
10 #include <sys/sysinfo.h>
11 #endif
12 #endif
13 
14 #include "../Common/Defs.h"
15 // #include "../Common/MyWindows.h"
16 
17 // #include "../../C/CpuArch.h"
18 
19 #include "System.h"
20 
21 namespace NWindows {
22 namespace NSystem {
23 
24 #ifdef _WIN32
25 
CountAffinity(DWORD_PTR mask)26 UInt32 CountAffinity(DWORD_PTR mask)
27 {
28   UInt32 num = 0;
29   for (unsigned i = 0; i < sizeof(mask) * 8; i++)
30     num += (UInt32)((mask >> i) & 1);
31   return num;
32 }
33 
Get()34 BOOL CProcessAffinity::Get()
35 {
36   #ifndef UNDER_CE
37   return GetProcessAffinityMask(GetCurrentProcess(), &processAffinityMask, &systemAffinityMask);
38   #else
39   return FALSE;
40   #endif
41 }
42 
43 
GetNumberOfProcessors()44 UInt32 GetNumberOfProcessors()
45 {
46   // We need to know how many threads we can use.
47   // By default the process is assigned to one group.
48   // So we get the number of logical processors (threads)
49   // assigned to current process in the current group.
50   // Group size can be smaller than total number logical processors, for exammple, 2x36
51 
52   CProcessAffinity pa;
53 
54   if (pa.Get() && pa.processAffinityMask != 0)
55     return pa.GetNumProcessThreads();
56 
57   SYSTEM_INFO systemInfo;
58   GetSystemInfo(&systemInfo);
59   // the number of logical processors in the current group
60   return (UInt32)systemInfo.dwNumberOfProcessors;
61 }
62 
63 #else
64 
65 
66 BOOL CProcessAffinity::Get()
67 {
68   numSysThreads = GetNumberOfProcessors();
69 
70   /*
71   numSysThreads = 8;
72   for (unsigned i = 0; i < numSysThreads; i++)
73     CpuSet_Set(&cpu_set, i);
74   return TRUE;
75   */
76 
77   #ifdef _7ZIP_AFFINITY_SUPPORTED
78 
79   // numSysThreads = sysconf(_SC_NPROCESSORS_ONLN); // The number of processors currently online
80   if (sched_getaffinity(0, sizeof(cpu_set), &cpu_set) != 0)
81     return FALSE;
82   return TRUE;
83 
84   #else
85 
86   // cpu_set = ((CCpuSet)1 << (numSysThreads)) - 1;
87   return TRUE;
88   // errno = ENOSYS;
89   // return FALSE;
90 
91   #endif
92 }
93 
94 UInt32 GetNumberOfProcessors()
95 {
96   #ifndef _7ZIP_ST
97   long n = sysconf(_SC_NPROCESSORS_CONF);  // The number of processors configured
98   if (n < 1)
99     n = 1;
100   return (UInt32)n;
101   #else
102   return 1;
103   #endif
104 }
105 
106 #endif
107 
108 
109 #ifdef _WIN32
110 
111 #ifndef UNDER_CE
112 
113 #if !defined(_WIN64) && defined(__GNUC__)
114 
115 typedef struct _MY_MEMORYSTATUSEX {
116   DWORD dwLength;
117   DWORD dwMemoryLoad;
118   DWORDLONG ullTotalPhys;
119   DWORDLONG ullAvailPhys;
120   DWORDLONG ullTotalPageFile;
121   DWORDLONG ullAvailPageFile;
122   DWORDLONG ullTotalVirtual;
123   DWORDLONG ullAvailVirtual;
124   DWORDLONG ullAvailExtendedVirtual;
125 } MY_MEMORYSTATUSEX, *MY_LPMEMORYSTATUSEX;
126 
127 #else
128 
129 #define MY_MEMORYSTATUSEX MEMORYSTATUSEX
130 #define MY_LPMEMORYSTATUSEX LPMEMORYSTATUSEX
131 
132 #endif
133 
134 typedef BOOL (WINAPI *GlobalMemoryStatusExP)(MY_LPMEMORYSTATUSEX lpBuffer);
135 
136 #endif // !UNDER_CE
137 
138 
GetRamSize(UInt64 & size)139 bool GetRamSize(UInt64 &size)
140 {
141   size = (UInt64)(sizeof(size_t)) << 29;
142 
143   #ifndef UNDER_CE
144     MY_MEMORYSTATUSEX stat;
145     stat.dwLength = sizeof(stat);
146   #endif
147 
148   #ifdef _WIN64
149 
150     if (!::GlobalMemoryStatusEx(&stat))
151       return false;
152     size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);
153     return true;
154 
155   #else
156 
157     #ifndef UNDER_CE
158       GlobalMemoryStatusExP globalMemoryStatusEx = (GlobalMemoryStatusExP)
159           (void *)::GetProcAddress(::GetModuleHandleA("kernel32.dll"), "GlobalMemoryStatusEx");
160       if (globalMemoryStatusEx && globalMemoryStatusEx(&stat))
161       {
162         size = MyMin(stat.ullTotalVirtual, stat.ullTotalPhys);
163         return true;
164       }
165     #endif
166 
167     {
168       MEMORYSTATUS stat2;
169       stat2.dwLength = sizeof(stat2);
170       ::GlobalMemoryStatus(&stat2);
171       size = MyMin(stat2.dwTotalVirtual, stat2.dwTotalPhys);
172       return true;
173     }
174   #endif
175 }
176 
177 #else
178 
179 // POSIX
180 // #include <stdio.h>
181 
GetRamSize(UInt64 & size)182 bool GetRamSize(UInt64 &size)
183 {
184   size = (UInt64)(sizeof(size_t)) << 29;
185 
186   #ifdef __APPLE__
187 
188     #ifdef HW_MEMSIZE
189       uint64_t val = 0; // support 2Gb+ RAM
190       int mib[2] = { CTL_HW, HW_MEMSIZE };
191     #elif defined(HW_PHYSMEM64)
192       uint64_t val = 0; // support 2Gb+ RAM
193       int mib[2] = { CTL_HW, HW_PHYSMEM64 };
194     #else
195       unsigned int val = 0; // For old system
196       int mib[2] = { CTL_HW, HW_PHYSMEM };
197     #endif // HW_MEMSIZE
198       size_t size_sys = sizeof(val);
199 
200       sysctl(mib, 2, &val, &size_sys, NULL, 0);
201       if (val)
202         size = val;
203 
204   #elif defined(_AIX)
205   // fixme
206   #elif defined(__gnu_hurd__)
207   // fixme
208   #elif defined(__FreeBSD_kernel__) && defined(__GLIBC__)
209   // GNU/kFreeBSD Debian
210   // fixme
211   #else
212 
213   struct sysinfo info;
214   if (::sysinfo(&info) != 0)
215     return false;
216   size = (UInt64)info.mem_unit * info.totalram;
217   const UInt64 kLimit = (UInt64)1 << (sizeof(size_t) * 8 - 1);
218   if (size > kLimit)
219     size = kLimit;
220 
221   /*
222   printf("\n mem_unit  = %lld", (UInt64)info.mem_unit);
223   printf("\n totalram  = %lld", (UInt64)info.totalram);
224   printf("\n freeram   = %lld", (UInt64)info.freeram);
225   */
226 
227   #endif
228 
229   return true;
230 }
231 
232 #endif
233 
234 }}
235