Line data Source code
1 : /* src/vm/os.cpp - system (OS) functions
2 :
3 : Copyright (C) 2007, 2008
4 : CACAOVM - Verein zur Foerderung der freien virtuellen Maschine CACAO
5 : Copyright (C) 2008 Theobroma Systems Ltd.
6 :
7 : This file is part of CACAO.
8 :
9 : This program is free software; you can redistribute it and/or
10 : modify it under the terms of the GNU General Public License as
11 : published by the Free Software Foundation; either version 2, or (at
12 : your option) any later version.
13 :
14 : This program is distributed in the hope that it will be useful, but
15 : WITHOUT ANY WARRANTY; without even the implied warranty of
16 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 : General Public License for more details.
18 :
19 : You should have received a copy of the GNU General Public License
20 : along with this program; if not, write to the Free Software
21 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22 : 02110-1301, USA.
23 :
24 : */
25 :
26 :
27 : #include "config.h"
28 :
29 : #if defined(__DARWIN__)
30 : # include <mach/mach.h>
31 : # include <mach/mach_host.h>
32 : # include <mach/host_info.h>
33 : #endif
34 :
35 : /* this should work on BSD */
36 : /* #include <sys/sysctl.h> */
37 :
38 : #include "mm/memory.hpp"
39 : #include "toolbox/logging.hpp"
40 : #include "vm/os.hpp"
41 : #include "vm/vm.hpp"
42 :
43 :
44 : /**
45 : * Prints an error message and aborts the VM.
46 : *
47 : * @param text Error message to print.
48 : */
49 0 : void os::abort(const char* text, ...)
50 : {
51 : va_list ap;
52 :
53 : // Print the log message.
54 0 : log_start();
55 :
56 0 : va_start(ap, text);
57 0 : log_vprint(text, ap);
58 0 : va_end(ap);
59 :
60 0 : log_finish();
61 :
62 : // Print a backtrace.
63 0 : os::print_backtrace();
64 :
65 : // Now abort the VM.
66 0 : os::abort();
67 0 : }
68 :
69 : /**
70 : * Prints a should not reach message and aborts the VM.
71 : *
72 : * @param text Error message to print.
73 : */
74 0 : void os::shouldnotreach(const char* text, ...)
75 : {
76 : va_list ap;
77 :
78 : // Print the log message.
79 0 : log_start();
80 :
81 0 : log_print("should not reach: ");
82 0 : va_start(ap, text);
83 0 : log_vprint(text, ap);
84 0 : va_end(ap);
85 :
86 0 : log_finish();
87 :
88 : // Print a backtrace.
89 0 : os::print_backtrace();
90 :
91 : // Now abort the VM.
92 0 : os::abort();
93 0 : }
94 :
95 : /**
96 : * Prints an unimplemented message and aborts the VM.
97 : *
98 : * @param text Error message to print.
99 : */
100 0 : void os::unimplemented(const char* text, ...)
101 : {
102 : va_list ap;
103 :
104 : // Print the log message.
105 0 : log_start();
106 :
107 0 : log_print("not implemented yet: ");
108 0 : va_start(ap, text);
109 0 : log_vprint(text, ap);
110 0 : va_end(ap);
111 :
112 0 : log_finish();
113 :
114 : // Print a backtrace.
115 0 : os::print_backtrace();
116 :
117 : // Now abort the VM.
118 0 : os::abort();
119 0 : }
120 :
121 : /**
122 : * Common code for both os::abort_errnum and os::abort_errno.
123 : */
124 0 : static void abort_verrnum(int errnum, const char* text, va_list ap)
125 : {
126 : // Print the log message.
127 0 : log_start();
128 :
129 0 : log_vprint(text, ap);
130 :
131 : // Print the strerror-message of errnum.
132 0 : log_print(": %s", os::strerror(errnum));
133 :
134 0 : log_finish();
135 :
136 : // Print a backtrace.
137 0 : os::print_backtrace();
138 :
139 : // Now abort the VM.
140 0 : os::abort();
141 0 : }
142 :
143 : /**
144 : * Prints an error message, appends ":" plus the strerror-message of
145 : * errnum and aborts the VM.
146 : *
147 : * @param errnum Error number.
148 : * @param text Error message to print.
149 : */
150 0 : void os::abort_errnum(int errnum, const char* text, ...)
151 : {
152 : va_list ap;
153 :
154 0 : va_start(ap, text);
155 0 : abort_verrnum(errnum, text, ap);
156 0 : va_end(ap);
157 0 : }
158 :
159 :
160 : /**
161 : * Equal to abort_errnum, but uses errno to get the error number.
162 : *
163 : * @param text Error message to print.
164 : */
165 0 : void os::abort_errno(const char* text, ...)
166 : {
167 : va_list ap;
168 :
169 0 : va_start(ap, text);
170 0 : abort_verrnum(errno, text, ap);
171 0 : va_end(ap);
172 0 : }
173 :
174 :
175 : /**
176 : * Return the current working directory.
177 : *
178 : * @return Pointer to a char array allocated by MNEW, or
179 : * NULL if memory could not be allocated.
180 : */
181 329 : char* os::getcwd(void)
182 : {
183 329 : int32_t size = 1024;
184 :
185 329 : char* buf = MNEW(char, size);
186 :
187 658 : while (buf != NULL) {
188 329 : if (getcwd(buf, size) != NULL)
189 329 : return buf;
190 :
191 0 : MFREE(buf, char, size);
192 :
193 : /* too small buffer or a more serious problem */
194 :
195 0 : if (errno != ERANGE)
196 0 : abort_errno("os::getcwd: getcwd failed");
197 :
198 : /* double the buffer size */
199 :
200 0 : size *= 2;
201 :
202 0 : buf = MNEW(char, size);
203 : }
204 :
205 0 : return NULL;
206 : }
207 :
208 :
209 : /**
210 : * Maps anonymous memory, even on systems not defining
211 : * MAP_ANON(YMOUS).
212 : *
213 : * @param ...
214 : */
215 491 : void* os::mmap_anonymous(void *addr, size_t len, int prot, int flags)
216 : {
217 : void* p;
218 :
219 : #if defined(MAP_ANON) || defined(MAP_ANONYMOUS)
220 : p = mmap(addr, len, prot,
221 : # if defined(MAP_ANON)
222 : MAP_ANON | flags,
223 : # else
224 : MAP_ANONYMOUS | flags,
225 : # endif
226 491 : -1, 0);
227 : #else
228 : int fd;
229 :
230 : fd = open("/dev/zero", O_RDONLY, 0);
231 :
232 : if (fd == -1)
233 : os::abort_errno("os::mmap_anonymous: open failed");
234 :
235 : p = mmap(addr, len, prot, flags, fd, 0);
236 : #endif
237 :
238 : #if defined(MAP_FAILED)
239 491 : if (p == MAP_FAILED)
240 : #else
241 : if (p == (void *) -1)
242 : #endif
243 0 : os::abort_errno("os::mmap_anonymous: mmap failed");
244 :
245 491 : return p;
246 : }
247 :
248 :
249 : /**
250 : * Print a C backtrace.
251 : */
252 0 : void os::print_backtrace()
253 : {
254 : #define BACKTRACE_SIZE 100
255 0 : void** array = new void*[SIZEOF_VOID_P * BACKTRACE_SIZE];
256 :
257 : // Get the backtrace.
258 0 : int size = backtrace(array, BACKTRACE_SIZE);
259 :
260 : // Resolve the symbols.
261 0 : char** strings = backtrace_symbols(array, size);
262 :
263 0 : log_println("Backtrace (%d stack frames):", size);
264 :
265 0 : for (int i = 0; i < size; i++)
266 0 : log_println("%s", strings[i]);
267 :
268 : // We have to free the strings.
269 0 : free(strings);
270 0 : }
271 :
272 :
273 : /**
274 : * Returns the number of online processors in the system.
275 : *
276 : * @return Number of online processors.
277 : */
278 0 : int os::processors_online(void)
279 : {
280 : #if defined(_SC_NPROC_ONLN)
281 :
282 : return (int) sysconf(_SC_NPROC_ONLN);
283 :
284 : #elif defined(_SC_NPROCESSORS_ONLN)
285 :
286 0 : return (int) sysconf(_SC_NPROCESSORS_ONLN);
287 :
288 : #elif defined(__DARWIN__)
289 :
290 : host_basic_info_data_t hinfo;
291 : mach_msg_type_number_t hinfo_count = HOST_BASIC_INFO_COUNT;
292 : kern_return_t rc;
293 :
294 : rc = host_info(mach_host_self(), HOST_BASIC_INFO,
295 : (host_info_t) &hinfo, &hinfo_count);
296 :
297 : if (rc != KERN_SUCCESS) {
298 : return -1;
299 : }
300 :
301 : /* XXX michi: according to my infos this should be
302 : hinfo.max_cpus, can someone please confirm or deny that? */
303 : return (int) hinfo.avail_cpus;
304 :
305 : #elif defined(__FREEBSD__)
306 : # error IMPLEMENT ME!
307 :
308 : /* this should work in BSD */
309 : /*
310 : int ncpu, mib[2], rc;
311 : size_t len;
312 :
313 : mib[0] = CTL_HW;
314 : mib[1] = HW_NCPU;
315 : len = sizeof(ncpu);
316 : rc = sysctl(mib, 2, &ncpu, &len, NULL, 0);
317 :
318 : return (int32_t) ncpu;
319 : */
320 :
321 : #else
322 :
323 : return 1;
324 :
325 : #endif
326 : }
327 :
328 :
329 : // Legacy C interface.
330 :
331 : extern "C" {
332 0 : void* os_mmap_anonymous(void *addr, size_t len, int prot, int flags) { return os::mmap_anonymous(addr, len, prot, flags); }
333 :
334 0 : int os_atoi(const char* nptr) { return os::atoi(nptr); }
335 0 : int os_getpagesize(void) { return os::getpagesize(); }
336 0 : void* os_memcpy(void* dest, const void* src, size_t n) { return os::memcpy(dest, src, n); }
337 0 : void* os_memset(void* s, int c, size_t n) { return os::memset(s, c, n); }
338 0 : char* os_strdup(const char* s) { return os::strdup(s); }
339 0 : int os_strlen(const char* s) { return os::strlen(s); }
340 :
341 : }
342 :
343 :
344 : /*
345 : * These are local overrides for various environment variables in Emacs.
346 : * Please do not remove this and leave it at the end of the file, where
347 : * Emacs will automagically detect them.
348 : * ---------------------------------------------------------------------
349 : * Local variables:
350 : * mode: c++
351 : * indent-tabs-mode: t
352 : * c-basic-offset: 4
353 : * tab-width: 4
354 : * End:
355 : * vim:noexpandtab:sw=4:ts=4:
356 : */
|