Coverage Report

Created: 2025-07-27 06:09

/src/nspr/pr/src/misc/prsystem.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
/* This Source Code Form is subject to the terms of the Mozilla Public
3
 * License, v. 2.0. If a copy of the MPL was not distributed with this
4
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5
6
#include "primpl.h"
7
#include "prsystem.h"
8
#include "prprf.h"
9
#include "prlong.h"
10
11
/* BSD-derived systems use sysctl() to get the number of processors */
12
#if defined(FREEBSD) || defined(NETBSD) || defined(OPENBSD) || \
13
    defined(DRAGONFLY) || defined(DARWIN)
14
#  define _PR_HAVE_SYSCTL
15
#  include <sys/param.h>
16
#  include <sys/sysctl.h>
17
#endif
18
19
#if defined(DARWIN)
20
#  include <mach/mach_init.h>
21
#  include <mach/mach_host.h>
22
#  include <mach/mach_port.h>
23
#endif
24
25
#if defined(HPUX)
26
#  include <sys/mpctl.h>
27
#  include <sys/pstat.h>
28
#endif
29
30
#if defined(XP_UNIX)
31
#  include <unistd.h>
32
#  include <sys/utsname.h>
33
#endif
34
35
#if defined(LINUX)
36
#  include <string.h>
37
#  include <ctype.h>
38
0
#  define MAX_LINE 512
39
#endif
40
41
#if defined(AIX)
42
#  include <cf.h>
43
#  include <sys/cfgodm.h>
44
#endif
45
46
0
PR_IMPLEMENT(char) PR_GetDirectorySeparator(void) {
47
0
  return PR_DIRECTORY_SEPARATOR;
48
0
} /* PR_GetDirectorySeparator */
49
50
/*
51
** OBSOLETE -- the function name is misspelled.
52
*/
53
0
PR_IMPLEMENT(char) PR_GetDirectorySepartor(void) {
54
0
#if defined(DEBUG)
55
0
  static PRBool warn = PR_TRUE;
56
0
  if (warn) {
57
0
    warn =
58
0
        _PR_Obsolete("PR_GetDirectorySepartor()", "PR_GetDirectorySeparator()");
59
0
  }
60
0
#endif
61
0
  return PR_GetDirectorySeparator();
62
0
} /* PR_GetDirectorySepartor */
63
64
0
PR_IMPLEMENT(char) PR_GetPathSeparator(void) {
65
0
  return PR_PATH_SEPARATOR;
66
0
} /* PR_GetPathSeparator */
67
68
PR_IMPLEMENT(PRStatus)
69
0
PR_GetSystemInfo(PRSysInfo cmd, char* buf, PRUint32 buflen) {
70
0
  PRUintn len = 0;
71
72
0
  if (!_pr_initialized) {
73
0
    _PR_ImplicitInitialization();
74
0
  }
75
76
0
  switch (cmd) {
77
0
    case PR_SI_HOSTNAME:
78
0
    case PR_SI_HOSTNAME_UNTRUNCATED:
79
0
      if (PR_FAILURE == _PR_MD_GETHOSTNAME(buf, (PRUintn)buflen)) {
80
0
        return PR_FAILURE;
81
0
      }
82
83
0
      if (cmd == PR_SI_HOSTNAME_UNTRUNCATED) {
84
0
        break;
85
0
      }
86
      /*
87
       * On some platforms a system does not have a hostname and
88
       * its IP address is returned instead.   The following code
89
       * should be skipped on those platforms.
90
       */
91
0
#ifndef _PR_GET_HOST_ADDR_AS_NAME
92
      /* Return the unqualified hostname */
93
0
      while (buf[len] && (len < buflen)) {
94
0
        if (buf[len] == '.') {
95
0
          buf[len] = '\0';
96
0
          break;
97
0
        }
98
0
        len += 1;
99
0
      }
100
0
#endif
101
0
      break;
102
103
0
    case PR_SI_SYSNAME:
104
      /* Return the operating system name */
105
0
#if defined(XP_UNIX) || defined(WIN32)
106
0
      if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) {
107
0
        return PR_FAILURE;
108
0
      }
109
#else
110
      (void)PR_snprintf(buf, buflen, _PR_SI_SYSNAME);
111
#endif
112
0
      break;
113
114
0
    case PR_SI_RELEASE:
115
      /* Return the version of the operating system */
116
0
#if defined(XP_UNIX) || defined(WIN32)
117
0
      if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) {
118
0
        return PR_FAILURE;
119
0
      }
120
0
#endif
121
0
      break;
122
123
0
    case PR_SI_RELEASE_BUILD:
124
      /* Return the version of the operating system */
125
0
#if defined(XP_UNIX) || defined(WIN32)
126
0
      if (PR_FAILURE == _PR_MD_GETSYSINFO(cmd, buf, (PRUintn)buflen)) {
127
0
        return PR_FAILURE;
128
0
      }
129
#else
130
      if (buflen) {
131
        *buf = 0;
132
      }
133
#endif /* XP_UNIX || WIN32 */
134
0
      break;
135
136
0
    case PR_SI_ARCHITECTURE:
137
      /* Return the architecture of the machine (ie. x86, mips, alpha, ...)*/
138
0
      (void)PR_snprintf(buf, buflen, _PR_SI_ARCHITECTURE);
139
0
      break;
140
0
    default:
141
0
      PR_SetError(PR_INVALID_ARGUMENT_ERROR, 0);
142
0
      return PR_FAILURE;
143
0
  }
144
0
  return PR_SUCCESS;
145
0
}
146
147
/*
148
** PR_GetNumberOfProcessors()
149
**
150
** Implementation notes:
151
**   Every platform does it a bit different.
152
**     numCpus is the returned value.
153
**   for each platform's "if defined" section
154
**     declare your local variable
155
**     do your thing, assign to numCpus
156
**   order of the if defined()s may be important,
157
**     especially for unix variants. Do platform
158
**     specific implementations before XP_UNIX.
159
**
160
*/
161
0
PR_IMPLEMENT(PRInt32) PR_GetNumberOfProcessors(void) {
162
0
  PRInt32 numCpus;
163
#if defined(WIN32)
164
  SYSTEM_INFO info;
165
166
  GetSystemInfo(&info);
167
  numCpus = info.dwNumberOfProcessors;
168
#elif defined(_PR_HAVE_SYSCTL)
169
  int mib[2];
170
  int rc;
171
  size_t len = sizeof(numCpus);
172
173
  mib[0] = CTL_HW;
174
#  ifdef HW_NCPUONLINE
175
  mib[1] = HW_NCPUONLINE;
176
#  else
177
  mib[1] = HW_NCPU;
178
#  endif
179
  rc = sysctl(mib, 2, &numCpus, &len, NULL, 0);
180
  if (-1 == rc) {
181
    numCpus = -1; /* set to -1 for return value on error */
182
    _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
183
  }
184
#elif defined(HPUX)
185
  numCpus = mpctl(MPC_GETNUMSPUS, 0, 0);
186
  if (numCpus < 1) {
187
    numCpus = -1; /* set to -1 for return value on error */
188
    _PR_MD_MAP_DEFAULT_ERROR(_MD_ERRNO());
189
  }
190
#elif defined(RISCOS)
191
  numCpus = 1;
192
#elif defined(LINUX)
193
  /* for the benefit of devices with advanced power-saving, that
194
     actually hotplug their cpus in heavy load, try to figure out
195
     the real number of CPUs */
196
0
  char buf[MAX_LINE];
197
0
  FILE* fin;
198
0
  const char* cpu_present = "/sys/devices/system/cpu/present";
199
0
  size_t strsize;
200
0
  numCpus = 0;
201
0
  fin = fopen(cpu_present, "r");
202
0
  if (fin != NULL) {
203
0
    if (fgets(buf, MAX_LINE, fin) != NULL) {
204
      /* check that the format is what we expect */
205
0
      if (buf[0] == '0') {
206
0
        strsize = strlen(buf);
207
0
        if (strsize == 1) {
208
          /* single core */
209
0
          numCpus = 1;
210
0
        } else if (strsize >= 3 && strsize <= 5) {
211
          /* should be of the form 0-999 */
212
          /* parse the part after the 0-, note count is 0-based */
213
0
          if (buf[1] == '-' && isdigit(buf[2])) {
214
0
            numCpus = 1 + atoi(buf + 2);
215
0
          }
216
0
        }
217
0
      }
218
0
    }
219
0
    fclose(fin);
220
0
  }
221
  /* if that fails, fall back to more standard methods */
222
0
  if (!numCpus) {
223
0
    numCpus = sysconf(_SC_NPROCESSORS_CONF);
224
0
  }
225
#elif defined(XP_UNIX)
226
  numCpus = sysconf(_SC_NPROCESSORS_CONF);
227
#else
228
#  error "An implementation is required"
229
#endif
230
0
  return (numCpus);
231
0
} /* end PR_GetNumberOfProcessors() */
232
233
/*
234
** PR_GetPhysicalMemorySize()
235
**
236
** Implementation notes:
237
**   Every platform does it a bit different.
238
**     bytes is the returned value.
239
**   for each platform's "if defined" section
240
**     declare your local variable
241
**     do your thing, assign to bytes.
242
**
243
*/
244
0
PR_IMPLEMENT(PRUint64) PR_GetPhysicalMemorySize(void) {
245
0
  PRUint64 bytes = 0;
246
247
0
#if defined(LINUX) || defined(SOLARIS)
248
249
0
  long pageSize = sysconf(_SC_PAGESIZE);
250
0
  long pageCount = sysconf(_SC_PHYS_PAGES);
251
0
  if (pageSize >= 0 && pageCount >= 0) {
252
0
    bytes = (PRUint64)pageSize * pageCount;
253
0
  }
254
255
#elif defined(NETBSD) || defined(OPENBSD) || defined(FREEBSD) || \
256
    defined(DRAGONFLY)
257
258
  int mib[2];
259
  int rc;
260
#  ifdef HW_PHYSMEM64
261
  uint64_t memSize;
262
#  else
263
  unsigned long memSize;
264
#  endif
265
  size_t len = sizeof(memSize);
266
267
  mib[0] = CTL_HW;
268
#  ifdef HW_PHYSMEM64
269
  mib[1] = HW_PHYSMEM64;
270
#  else
271
  mib[1] = HW_PHYSMEM;
272
#  endif
273
  rc = sysctl(mib, 2, &memSize, &len, NULL, 0);
274
  if (-1 != rc) {
275
    bytes = memSize;
276
  }
277
278
#elif defined(HPUX)
279
280
  struct pst_static info;
281
  int result = pstat_getstatic(&info, sizeof(info), 1, 0);
282
  if (result == 1) {
283
    bytes = (PRUint64)info.physical_memory * info.page_size;
284
  }
285
286
#elif defined(DARWIN)
287
288
  mach_port_t mach_host = mach_host_self();
289
  struct host_basic_info hInfo;
290
  mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
291
292
  int result =
293
      host_info(mach_host, HOST_BASIC_INFO, (host_info_t)&hInfo, &count);
294
  mach_port_deallocate(mach_task_self(), mach_host);
295
  if (result == KERN_SUCCESS) {
296
    bytes = hInfo.max_mem;
297
  }
298
299
#elif defined(WIN32)
300
301
  MEMORYSTATUSEX memStat;
302
  memStat.dwLength = sizeof(memStat);
303
  if (GlobalMemoryStatusEx(&memStat)) {
304
    bytes = memStat.ullTotalPhys;
305
  }
306
307
#elif defined(AIX)
308
309
  if (odm_initialize() == 0) {
310
    int how_many;
311
    struct CuAt* obj = getattr("sys0", "realmem", 0, &how_many);
312
    if (obj != NULL) {
313
      bytes = (PRUint64)atoi(obj->value) * 1024;
314
      free(obj);
315
    }
316
    odm_terminate();
317
  }
318
319
#else
320
321
  PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
322
323
#endif
324
325
0
  return bytes;
326
0
} /* end PR_GetPhysicalMemorySize() */