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)
90 closeMutex(&allocator_mutex);
94 static void addAllocation(void *addr, size_t len) {
98 alloc_size = sizeof(Allocated);
99 if ((a = (Allocated *) malloc(alloc_size)) == NULL) {
100 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
101 MallocFailHook((W_) alloc_size, "creating info for debugging allocator");
102 stg_exit(EXIT_INTERNAL_ERROR);
106 ACQUIRE_LOCK(&allocator_mutex);
107 a->next = allocs->next;
109 RELEASE_LOCK(&allocator_mutex);
112 static void removeAllocation(void *addr) {
116 barf("Freeing NULL!");
119 ACQUIRE_LOCK(&allocator_mutex);
123 if (a->addr == addr) {
124 prev->next = a->next;
125 memset(addr, 0xaa, a->len);
127 RELEASE_LOCK(&allocator_mutex);
133 barf("Freeing non-allocated memory at %p", addr);
137 /* -----------------------------------------------------------------------------
138 Result-checking malloc wrappers.
139 -------------------------------------------------------------------------- */
142 stgMallocBytes (int n, char *msg)
148 if ((space = (char *) malloc(n2)) == NULL) {
149 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
150 MallocFailHook((W_) n, msg); /*msg*/
151 stg_exit(EXIT_INTERNAL_ERROR);
154 addAllocation(space, n2);
160 stgReallocBytes (void *p, int n, char *msg)
166 if ((space = (char *) realloc(p, (size_t) n2)) == NULL) {
167 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
168 MallocFailHook((W_) n, msg); /*msg*/
169 stg_exit(EXIT_INTERNAL_ERROR);
173 addAllocation(space, n2);
179 stgCallocBytes (int n, int m, char *msg)
183 if ((space = (char *) calloc((size_t) n, (size_t) m)) == NULL) {
184 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
185 MallocFailHook((W_) n*m, msg); /*msg*/
186 stg_exit(EXIT_INTERNAL_ERROR);
189 addAllocation(space, (size_t) n * (size_t) m);
194 /* To simplify changing the underlying allocator used
195 * by stgMallocBytes(), provide stgFree() as well.
206 /* -----------------------------------------------------------------------------
209 Not sure if this belongs here.
210 -------------------------------------------------------------------------- */
215 StackOverflowHook(RtsFlags.GcFlags.maxStkSize * sizeof(W_));
217 #if defined(TICKY_TICKY)
218 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
225 /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
226 OutOfHeapHook(0/*unknown request size*/,
227 RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);
229 #if defined(TICKY_TICKY)
230 if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
233 stg_exit(EXIT_HEAPOVERFLOW);
236 /* -----------------------------------------------------------------------------
239 Used in addr2Integer because the C compiler on x86 chokes on
240 strlen, trying to inline it with not enough registers available.
241 -------------------------------------------------------------------------- */
243 nat stg_strlen(char *s)
252 /* -----------------------------------------------------------------------------
253 genSym stuff, used by GHC itself for its splitting unique supply.
255 ToDo: put this somewhere sensible.
256 ------------------------------------------------------------------------- */
258 static I_ __GenSymCounter = 0;
263 return(__GenSymCounter++);
266 resetGenSymZh(void) /* it's your funeral */
269 return(__GenSymCounter);
272 /* -----------------------------------------------------------------------------
273 Get the current time as a string. Used in profiling reports.
274 -------------------------------------------------------------------------- */
276 #if defined(PROFILING) || defined(DEBUG) || defined(PAR) || defined(GRAN)
280 static time_t now = 0;
281 static char nowstr[26];
286 ctime_r(&now, nowstr);
288 strcpy(nowstr, ctime(&now));
290 memmove(nowstr+16,nowstr+19,7);
291 nowstr[21] = '\0'; // removes the \n
297 /* -----------------------------------------------------------------------------
298 * Reset a file handle to blocking mode. We do this for the standard
299 * file descriptors before exiting, because the shell doesn't always
301 * -------------------------------------------------------------------------- */
303 #if !defined(mingw32_HOST_OS)
305 resetNonBlockingFd(int fd)
309 /* clear the non-blocking flag on this file descriptor */
310 fd_flags = fcntl(fd, F_GETFL);
311 if (fd_flags & O_NONBLOCK) {
312 fcntl(fd, F_SETFL, fd_flags & ~O_NONBLOCK);
317 setNonBlockingFd(int fd)
321 /* clear the non-blocking flag on this file descriptor */
322 fd_flags = fcntl(fd, F_GETFL);
323 if (!(fd_flags & O_NONBLOCK)) {
324 fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);
328 /* Stub defns -- async / non-blocking IO is not done
329 * via O_NONBLOCK and select() under Win32.
331 void resetNonBlockingFd(int fd STG_UNUSED) {}
332 void setNonBlockingFd(int fd STG_UNUSED) {}
336 static ullong startTime = 0;
338 /* used in a parallel setup */
342 # if defined(HAVE_GETCLOCK) && !defined(alpha_HOST_ARCH) && !defined(hppa1_1_HOST_ARCH)
345 if (getclock(TIMEOFDAY, &tv) != 0) {
347 fprintf(stderr, "Clock failed\n");
348 stg_exit(EXIT_FAILURE);
350 return tv.tv_sec * LL(1000) + tv.tv_nsec / LL(1000000) - startTime;
351 # elif HAVE_GETTIMEOFDAY && !defined(alpha_HOST_ARCH)
354 if (gettimeofday(&tv, NULL) != 0) {
356 fprintf(stderr, "Clock failed\n");
357 stg_exit(EXIT_FAILURE);
359 return tv.tv_sec * LL(1000) + tv.tv_usec / LL(1000) - startTime;
362 if ((t = time(NULL)) == (time_t) -1) {
364 fprintf(stderr, "Clock failed\n");
365 stg_exit(EXIT_FAILURE);
367 return t * LL(1000) - startTime;
372 /* -----------------------------------------------------------------------------
373 Print large numbers, with punctuation.
374 -------------------------------------------------------------------------- */
377 ullong_format_string(ullong x, char *s, rtsBool with_commas)
379 if (x < (ullong)1000)
380 sprintf(s, "%lu", (lnat)x);
381 else if (x < (ullong)1000000)
382 sprintf(s, (with_commas) ? "%lu,%3.3lu" : "%lu%3.3lu",
383 (lnat)((x)/(ullong)1000),
384 (lnat)((x)%(ullong)1000));
385 else if (x < (ullong)1000000000)
386 sprintf(s, (with_commas) ? "%lu,%3.3lu,%3.3lu" : "%lu%3.3lu%3.3lu",
387 (lnat)((x)/(ullong)1000000),
388 (lnat)((x)/(ullong)1000%(ullong)1000),
389 (lnat)((x)%(ullong)1000));
391 sprintf(s, (with_commas) ? "%lu,%3.3lu,%3.3lu,%3.3lu" : "%lu%3.3lu%3.3lu%3.3lu",
392 (lnat)((x)/(ullong)1000000000),
393 (lnat)((x)/(ullong)1000000%(ullong)1000),
394 (lnat)((x)/(ullong)1000%(ullong)1000),
395 (lnat)((x)%(ullong)1000));
400 // Can be used as a breakpoint to set on every heap check failure.
403 heapCheckFail( void )
409 * It seems that pthreads and signals interact oddly in OpenBSD & FreeBSD
410 * pthreads (and possibly others). When linking with -lpthreads, we
411 * have to use pthread_kill to send blockable signals. So use that
412 * when we have a threaded rts. So System.Posix.Signals will call
413 * genericRaise(), rather than raise(3).
415 int genericRaise(int sig) {
416 #if defined(THREADED_RTS) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS))
417 return pthread_kill(pthread_self(), sig);