1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team, 1998-2004
5 * General utility functions used in the RTS.
7 * ---------------------------------------------------------------------------*/
9 #include "PosixSource.h"
25 #ifdef HAVE_GETTIMEOFDAY
38 #if defined(THREADED_RTS) && defined(openbsd_HOST_OS) && defined(HAVE_PTHREAD_H)
47 /* -----------------------------------------------------------------------------
49 -------------------------------------------------------------------------- */
53 typedef struct Allocated_ {
56 struct Allocated_ *next;
59 static Allocated *allocs = NULL;
62 static Mutex allocator_mutex;
72 initMutex(&allocator_mutex);
74 alloc_size = sizeof(Allocated);
75 if ((a = (Allocated *) malloc(alloc_size)) == NULL) {
76 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
77 MallocFailHook((W_) alloc_size, "initialising debugging allocator");
78 stg_exit(EXIT_INTERNAL_ERROR);
87 shutdownAllocator(void)
92 barf("Allocator shutdown requested, but not initialised!");
96 closeMutex(&allocator_mutex);
103 if (a == NULL) return;
105 debugBelch("Warning: %p still allocated at shutdown\n",
111 static void addAllocation(void *addr, size_t len) {
115 if (allocs != NULL) {
116 alloc_size = sizeof(Allocated);
117 if ((a = (Allocated *) malloc(alloc_size)) == NULL) {
118 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
119 MallocFailHook((W_) alloc_size,
120 "creating info for debugging allocator");
121 stg_exit(EXIT_INTERNAL_ERROR);
125 ACQUIRE_LOCK(&allocator_mutex);
126 a->next = allocs->next;
128 RELEASE_LOCK(&allocator_mutex);
131 /* This doesn't actually help as we haven't looked at the flags
132 * at the time that it matters (while running constructors) */
134 debugBelch("Ignoring allocation %p %zd as allocs is NULL\n",
139 static void removeAllocation(void *addr, int overwrite_with_aa) {
143 barf("Freeing NULL!");
146 if (allocs != NULL) {
147 ACQUIRE_LOCK(&allocator_mutex);
151 if (a->addr == addr) {
152 prev->next = a->next;
153 if (overwrite_with_aa) {
154 memset(addr, 0xaa, a->len);
157 RELEASE_LOCK(&allocator_mutex);
163 /* We would like to barf here, but we can't as conc021
164 * allocates some stuff in a constructor which then gets freed
166 /* barf("Freeing non-allocated memory at %p", addr); */
168 debugBelch("Warning: Freeing non-allocated memory at %p\n",
170 RELEASE_LOCK(&allocator_mutex);
174 debugBelch("Ignoring free of %p as allocs is NULL\n",
180 /* -----------------------------------------------------------------------------
181 Result-checking malloc wrappers.
182 -------------------------------------------------------------------------- */
185 stgMallocBytes (int n, char *msg)
191 if ((space = (char *) malloc(n2)) == NULL) {
192 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
193 MallocFailHook((W_) n, msg); /*msg*/
194 stg_exit(EXIT_INTERNAL_ERROR);
197 addAllocation(space, n2);
203 stgReallocBytes (void *p, int n, char *msg)
209 if ((space = (char *) realloc(p, (size_t) n2)) == NULL) {
210 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
211 MallocFailHook((W_) n, msg); /*msg*/
212 stg_exit(EXIT_INTERNAL_ERROR);
215 removeAllocation(p, 0);
216 addAllocation(space, n2);
222 stgCallocBytes (int n, int m, char *msg)
226 if ((space = (char *) calloc((size_t) n, (size_t) m)) == NULL) {
227 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
228 MallocFailHook((W_) n*m, msg); /*msg*/
229 stg_exit(EXIT_INTERNAL_ERROR);
232 addAllocation(space, (size_t) n * (size_t) m);
237 /* To simplify changing the underlying allocator used
238 * by stgMallocBytes(), provide stgFree() as well.
244 removeAllocation(p, 1);
249 /* -----------------------------------------------------------------------------
252 Not sure if this belongs here.
253 -------------------------------------------------------------------------- */
258 StackOverflowHook(RtsFlags.GcFlags.maxStkSize * sizeof(W_));
260 #if defined(TICKY_TICKY)
261 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
268 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
269 OutOfHeapHook(0/*unknown request size*/,
270 RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);
272 #if defined(TICKY_TICKY)
273 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
276 stg_exit(EXIT_HEAPOVERFLOW);
279 /* -----------------------------------------------------------------------------
282 Used in addr2Integer because the C compiler on x86 chokes on
283 strlen, trying to inline it with not enough registers available.
284 -------------------------------------------------------------------------- */
286 nat stg_strlen(char *s)
295 /* -----------------------------------------------------------------------------
296 genSym stuff, used by GHC itself for its splitting unique supply.
298 ToDo: put this somewhere sensible.
299 ------------------------------------------------------------------------- */
301 static HsInt __GenSymCounter = 0;
306 return(__GenSymCounter++);
309 resetGenSymZh(void) /* it's your funeral */
312 return(__GenSymCounter);
315 /* -----------------------------------------------------------------------------
316 Get the current time as a string. Used in profiling reports.
317 -------------------------------------------------------------------------- */
319 #if defined(PROFILING) || defined(DEBUG) || defined(PAR) || defined(GRAN)
323 static time_t now = 0;
324 static char nowstr[26];
329 ctime_r(&now, nowstr);
331 strcpy(nowstr, ctime(&now));
333 memmove(nowstr+16,nowstr+19,7);
334 nowstr[21] = '\0'; // removes the \n
340 /* -----------------------------------------------------------------------------
341 * Reset a file handle to blocking mode. We do this for the standard
342 * file descriptors before exiting, because the shell doesn't always
344 * -------------------------------------------------------------------------- */
346 #if !defined(mingw32_HOST_OS)
348 resetNonBlockingFd(int fd)
352 /* clear the non-blocking flag on this file descriptor */
353 fd_flags = fcntl(fd, F_GETFL);
354 if (fd_flags & O_NONBLOCK) {
355 fcntl(fd, F_SETFL, fd_flags & ~O_NONBLOCK);
360 setNonBlockingFd(int fd)
364 /* clear the non-blocking flag on this file descriptor */
365 fd_flags = fcntl(fd, F_GETFL);
366 if (!(fd_flags & O_NONBLOCK)) {
367 fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);
371 /* Stub defns -- async / non-blocking IO is not done
372 * via O_NONBLOCK and select() under Win32.
374 void resetNonBlockingFd(int fd STG_UNUSED) {}
375 void setNonBlockingFd(int fd STG_UNUSED) {}
379 static ullong startTime = 0;
381 /* used in a parallel setup */
385 # if defined(HAVE_GETCLOCK) && !defined(alpha_HOST_ARCH) && !defined(hppa1_1_HOST_ARCH)
388 if (getclock(TIMEOFDAY, &tv) != 0) {
390 fprintf(stderr, "Clock failed\n");
391 stg_exit(EXIT_FAILURE);
393 return tv.tv_sec * LL(1000) + tv.tv_nsec / LL(1000000) - startTime;
394 # elif HAVE_GETTIMEOFDAY && !defined(alpha_HOST_ARCH)
397 if (gettimeofday(&tv, NULL) != 0) {
399 fprintf(stderr, "Clock failed\n");
400 stg_exit(EXIT_FAILURE);
402 return tv.tv_sec * LL(1000) + tv.tv_usec / LL(1000) - startTime;
405 if ((t = time(NULL)) == (time_t) -1) {
407 fprintf(stderr, "Clock failed\n");
408 stg_exit(EXIT_FAILURE);
410 return t * LL(1000) - startTime;
415 /* -----------------------------------------------------------------------------
416 Print large numbers, with punctuation.
417 -------------------------------------------------------------------------- */
420 ullong_format_string(ullong x, char *s, rtsBool with_commas)
422 if (x < (ullong)1000)
423 sprintf(s, "%lu", (lnat)x);
424 else if (x < (ullong)1000000)
425 sprintf(s, (with_commas) ? "%lu,%3.3lu" : "%lu%3.3lu",
426 (lnat)((x)/(ullong)1000),
427 (lnat)((x)%(ullong)1000));
428 else if (x < (ullong)1000000000)
429 sprintf(s, (with_commas) ? "%lu,%3.3lu,%3.3lu" : "%lu%3.3lu%3.3lu",
430 (lnat)((x)/(ullong)1000000),
431 (lnat)((x)/(ullong)1000%(ullong)1000),
432 (lnat)((x)%(ullong)1000));
434 sprintf(s, (with_commas) ? "%lu,%3.3lu,%3.3lu,%3.3lu" : "%lu%3.3lu%3.3lu%3.3lu",
435 (lnat)((x)/(ullong)1000000000),
436 (lnat)((x)/(ullong)1000000%(ullong)1000),
437 (lnat)((x)/(ullong)1000%(ullong)1000),
438 (lnat)((x)%(ullong)1000));
443 // Can be used as a breakpoint to set on every heap check failure.
446 heapCheckFail( void )
452 * It seems that pthreads and signals interact oddly in OpenBSD & FreeBSD
453 * pthreads (and possibly others). When linking with -lpthreads, we
454 * have to use pthread_kill to send blockable signals. So use that
455 * when we have a threaded rts. So System.Posix.Signals will call
456 * genericRaise(), rather than raise(3).
458 int genericRaise(int sig) {
459 #if defined(THREADED_RTS) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS))
460 return pthread_kill(pthread_self(), sig);