suricata
util-cpu.c
Go to the documentation of this file.
1 /* Copyright (C) 2007-2013 Open Information Security Foundation
2  *
3  * You can copy, redistribute or modify this Program under the terms of
4  * the GNU General Public License version 2 as published by the Free
5  * Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * version 2 along with this program; if not, write to the Free Software
14  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
15  * 02110-1301, USA.
16  */
17 
18 /**
19  * \file
20  *
21  * \author Pablo Rincon Crespo <pablo.rincon.crespo@gmail.com>
22  *
23  * Retrieve CPU information (configured CPUs, online CPUs)
24  */
25 
26 #include "suricata-common.h"
27 #include "util-error.h"
28 #include "util-debug.h"
29 #include "util-cpu.h"
30 
31 /**
32  * Ok, if they should use sysconf, check that they have the macro's
33  * (syscalls) defined;
34  *
35  * Note: For windows it's different; Check the following:
36  * SYSTEM_INFO info;
37  * GetSystemInfo(&info);
38  * -> info.dwNumberOfProcessors;
39  */
40 #ifdef _SC_NPROCESSORS_CONF
41 #define SYSCONF_NPROCESSORS_CONF_COMPAT
42 #endif
43 
44 #ifdef _SC_NPROCESSORS_ONLN
45 #define SYSCONF_NPROCESSORS_ONLN_COMPAT
46 #endif
47 
48 /* This one is available on Solaris 10 */
49 #ifdef _SC_NPROCESSORS_MAX
50 #define SYSCONF_NPROCESSORS_MAX_COMPAT
51 #endif
52 
53 /**
54  * \brief Get the number of cpus configured in the system
55  * \retval 0 if the syscall is not available or we have an error;
56  * otherwise it will return the number of cpus configured
57  */
59 {
60 #ifdef SYSCONF_NPROCESSORS_CONF_COMPAT
61  long nprocs = -1;
62  nprocs = sysconf(_SC_NPROCESSORS_CONF);
63  if (nprocs < 1) {
64  SCLogError(SC_ERR_SYSCALL, "Couldn't retrieve the number of cpus "
65  "configured (%s)", strerror(errno));
66  return 0;
67  }
68 
69  if (nprocs > UINT16_MAX) {
70  SCLogDebug("It seems that there are more than %"PRIu16" CPUs "
71  "configured on this system. You can modify util-cpu.{c,h} "
72  "to use uint32_t to support it", UINT16_MAX);
73  return UINT16_MAX;
74  }
75 
76  return (uint16_t)nprocs;
77 #elif OS_WIN32
78  long nprocs = -1;
79  const char* envvar = getenv("NUMBER_OF_PROCESSORS");
80  nprocs = (NULL != envvar) ? atoi(envvar) : 0;
81  if (nprocs < 1) {
82  SCLogError(SC_ERR_SYSCALL, "Couldn't retrieve the number of cpus "
83  "configured from the NUMBER_OF_PROCESSORS environment variable");
84  return 0;
85  }
86  return (uint16_t)nprocs;
87 #else
88  SCLogError(SC_ERR_SYSCONF, "Couldn't retrieve the number of cpus "
89  "configured, sysconf macro unavailable");
90  return 0;
91 #endif
92 }
93 
94 /**
95  * \brief Get the number of cpus online in the system
96  * \retval 0 if the syscall is not available or we have an error;
97  * otherwise it will return the number of cpus online
98  */
100 {
101 #ifdef SYSCONF_NPROCESSORS_ONLN_COMPAT
102  long nprocs = -1;
103  nprocs = sysconf(_SC_NPROCESSORS_ONLN);
104  if (nprocs < 1) {
105  SCLogError(SC_ERR_SYSCALL, "Couldn't retrieve the number of cpus "
106  "online (%s)", strerror(errno));
107  return 0;
108  }
109 
110  if (nprocs > UINT16_MAX) {
111  SCLogDebug("It seems that there are more than %"PRIu16" CPUs online. "
112  "You can modify util-cpu.{c,h} to use uint32_t to "
113  "support it", UINT16_MAX);
114  return UINT16_MAX;
115  }
116 
117  return nprocs;
118 #elif OS_WIN32
120 #else
121  SCLogError(SC_ERR_SYSCONF, "Couldn't retrieve the number of cpus online, "
122  "synconf macro unavailable");
123  return 0;
124 #endif
125 }
126 
127 /**
128  * \brief Get the maximum number of cpus allowed in the system
129  * This syscall is present on Solaris, but it's not on linux
130  * or macosx. Maybe you should look at UtilCpuGetNumProcessorsConfigured()
131  * \retval 0 if the syscall is not available or we have an error;
132  * otherwise it will return the number of cpus allowed
133  */
135 {
136 #ifdef SYSCONF_NPROCESSORS_MAX_COMPAT
137  long nprocs = -1;
138  nprocs = sysconf(_SC_NPROCESSORS_MAX);
139  if (nprocs < 1) {
140  SCLogError(SC_ERR_SYSCALL, "Couldn't retrieve the maximum number of cpus "
141  "allowed by the system (%s)", strerror(errno));
142  return 0;
143  }
144 
145  if (nprocs > UINT16_MAX) {
146  SCLogDebug("It seems that the system support more that %"PRIu16" CPUs. You "
147  "can modify util-cpu.{c,h} to use uint32_t to support it", UINT16_MAX);
148  return UINT16_MAX;
149  }
150 
151  return (uint16_t)nprocs;
152 #else
153  SCLogError(SC_ERR_SYSCONF, "Couldn't retrieve the maximum number of cpus allowed by "
154  "the system, synconf macro unavailable");
155  return 0;
156 #endif
157 }
158 
159 /**
160  * \brief Print a summary of CPUs detected (configured and online)
161  */
163 {
164  uint16_t cpus_conf = UtilCpuGetNumProcessorsConfigured();
165  uint16_t cpus_online = UtilCpuGetNumProcessorsOnline();
166 
167  SCLogDebug("CPUs Summary: ");
168  if (cpus_conf > 0)
169  SCLogDebug("CPUs configured: %"PRIu16, cpus_conf);
170  if (cpus_online > 0)
171  SCLogInfo("CPUs/cores online: %"PRIu16, cpus_online);
172  if (cpus_online == 0 && cpus_conf == 0)
173  SCLogInfo("Couldn't retireve any information of CPU's, please, send your operating "
174  "system info and check util-cpu.{c,h}");
175 }
176 
177 /**
178  * Get the current number of ticks from the CPU.
179  *
180  * \todo We'll have to deal with removig ticks from the extra cpuids inbetween
181  * 2 calls.
182  */
183 uint64_t UtilCpuGetTicks(void)
184 {
185  uint64_t val;
186 #if defined(__GNUC__) && (defined(__x86_64) || defined(_X86_64_) || defined(ia_64) || defined(__i386__))
187 #if defined(__x86_64) || defined(_X86_64_) || defined(ia_64)
188  __asm__ __volatile__ (
189  "xorl %%eax,%%eax\n\t"
190  "cpuid\n\t"
191  ::: "%rax", "%rbx", "%rcx", "%rdx");
192 #else
193  __asm__ __volatile__ (
194  "xorl %%eax,%%eax\n\t"
195  "pushl %%ebx\n\t"
196  "cpuid\n\t"
197  "popl %%ebx\n\t"
198  ::: "%eax", "%ecx", "%edx");
199 #endif
200  uint32_t a, d;
201  __asm__ __volatile__ ("rdtsc" : "=a" (a), "=d" (d));
202  val = ((uint64_t)a) | (((uint64_t)d) << 32);
203 #if defined(__x86_64) || defined(_X86_64_) || defined(ia_64)
204  __asm__ __volatile__ (
205  "xorl %%eax,%%eax\n\t"
206  "cpuid\n\t"
207  ::: "%rax", "%rbx", "%rcx", "%rdx");
208 #else
209  __asm__ __volatile__ (
210  "xorl %%eax,%%eax\n\t"
211  "pushl %%ebx\n\t"
212  "cpuid\n\t"
213  "popl %%ebx\n\t"
214  ::: "%eax", "%ecx", "%edx");
215 #endif
216 
217 #else /* #if defined(__GNU__) */
218 //#warning Using inferior version of UtilCpuGetTicks
219  struct timeval now;
220  gettimeofday(&now, NULL);
221  val = (now.tv_sec * 1000000) + now.tv_usec;
222 #endif
223  return val;
224 }
#define SCLogDebug(...)
Definition: util-debug.h:335
uint16_t UtilCpuGetNumProcessorsConfigured(void)
Get the number of cpus configured in the system.
Definition: util-cpu.c:58
uint64_t UtilCpuGetTicks(void)
Definition: util-cpu.c:183
#define SCLogError(err_code,...)
Macro used to log ERROR messages.
Definition: util-debug.h:294
void UtilCpuPrintSummary(void)
Print a summary of CPUs detected (configured and online)
Definition: util-cpu.c:162
#define SCLogInfo(...)
Macro used to log INFORMATIONAL messages.
Definition: util-debug.h:254
uint16_t UtilCpuGetNumProcessorsOnline(void)
Get the number of cpus online in the system.
Definition: util-cpu.c:99
uint16_t UtilCpuGetNumProcessorsMax(void)
Get the maximum number of cpus allowed in the system This syscall is present on Solaris, but it&#39;s not on linux or macosx. Maybe you should look at UtilCpuGetNumProcessorsConfigured()
Definition: util-cpu.c:134