Declare this file to be POSIX
[ghc-hetmet.git] / rts / RtsUtils.c
1 /* -----------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 1998-2004
4  *
5  * General utility functions used in the RTS.
6  *
7  * ---------------------------------------------------------------------------*/
8
9 #include "PosixSource.h"
10
11 #include "Rts.h"
12 #include "RtsAPI.h"
13 #include "RtsFlags.h"
14 #include "RtsUtils.h"
15 #include "Ticky.h"
16
17 #ifdef HAVE_TIME_H
18 #include <time.h>
19 #endif
20
21 #ifdef HAVE_FCNTL_H
22 #include <fcntl.h>
23 #endif
24
25 #ifdef HAVE_GETTIMEOFDAY
26 #include <sys/time.h>
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <stdio.h>
33
34 #ifdef HAVE_SIGNAL_H
35 #include <signal.h>
36 #endif
37
38 #if defined(THREADED_RTS) && defined(openbsd_HOST_OS) && defined(HAVE_PTHREAD_H)
39 #include <pthread.h>
40 #endif
41
42 #if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(darwin_HOST_OS)
43 #include <unistd.h>
44 #include <sys/types.h>
45 #include <sys/mman.h>
46
47 /* no C99 header stdint.h on OpenBSD? */
48 #if defined(openbsd_HOST_OS)
49 typedef unsigned long my_uintptr_t;
50 #else
51 #include <stdint.h>
52 typedef uintptr_t my_uintptr_t;
53 #endif
54 #endif
55
56 #if defined(_WIN32)
57 #include <windows.h>
58 #endif
59
60 /* -----------------------------------------------------------------------------
61    Result-checking malloc wrappers.
62    -------------------------------------------------------------------------- */
63
64 void *
65 stgMallocBytes (int n, char *msg)
66 {
67     char *space;
68
69     if ((space = (char *) malloc((size_t) n)) == NULL) {
70       /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
71       MallocFailHook((W_) n, msg); /*msg*/
72       stg_exit(EXIT_INTERNAL_ERROR);
73     }
74     return space;
75 }
76
77 void *
78 stgReallocBytes (void *p, int n, char *msg)
79 {
80     char *space;
81
82     if ((space = (char *) realloc(p, (size_t) n)) == NULL) {
83       /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
84       MallocFailHook((W_) n, msg); /*msg*/
85       stg_exit(EXIT_INTERNAL_ERROR);
86     }
87     return space;
88 }
89
90 void *
91 stgCallocBytes (int n, int m, char *msg)
92 {
93     char *space;
94
95     if ((space = (char *) calloc((size_t) n, (size_t) m)) == NULL) {
96       /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
97       MallocFailHook((W_) n*m, msg); /*msg*/
98       stg_exit(EXIT_INTERNAL_ERROR);
99     }
100     return space;
101 }
102
103 /* To simplify changing the underlying allocator used
104  * by stgMallocBytes(), provide stgFree() as well.
105  */
106 void
107 stgFree(void* p)
108 {
109   free(p);
110 }
111
112 /* -----------------------------------------------------------------------------
113    Stack overflow
114    
115    Not sure if this belongs here.
116    -------------------------------------------------------------------------- */
117
118 void
119 stackOverflow(void)
120 {
121   StackOverflowHook(RtsFlags.GcFlags.maxStkSize * sizeof(W_));
122
123 #if defined(TICKY_TICKY)
124   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
125 #endif
126 }
127
128 void
129 heapOverflow(void)
130 {
131   /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
132   OutOfHeapHook(0/*unknown request size*/, 
133                 RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);
134   
135 #if defined(TICKY_TICKY)
136   if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
137 #endif
138
139   stg_exit(EXIT_HEAPOVERFLOW);
140 }
141
142 /* -----------------------------------------------------------------------------
143    Out-of-line strlen.
144
145    Used in addr2Integer because the C compiler on x86 chokes on
146    strlen, trying to inline it with not enough registers available.
147    -------------------------------------------------------------------------- */
148
149 nat stg_strlen(char *s)
150 {
151    char *p = s;
152
153    while (*p) p++;
154    return p-s;
155 }
156
157
158 /* -----------------------------------------------------------------------------
159    genSym stuff, used by GHC itself for its splitting unique supply.
160
161    ToDo: put this somewhere sensible.
162    -------------------------------------------------------------------------  */
163
164 static I_ __GenSymCounter = 0;
165
166 I_
167 genSymZh(void)
168 {
169     return(__GenSymCounter++);
170 }
171 I_
172 resetGenSymZh(void) /* it's your funeral */
173 {
174     __GenSymCounter=0;
175     return(__GenSymCounter);
176 }
177
178 /* -----------------------------------------------------------------------------
179    Get the current time as a string.  Used in profiling reports.
180    -------------------------------------------------------------------------- */
181
182 #if defined(PROFILING) || defined(DEBUG) || defined(PAR) || defined(GRAN)
183 char *
184 time_str(void)
185 {
186     static time_t now = 0;
187     static char nowstr[26];
188
189     if (now == 0) {
190         time(&now);
191 #if HAVE_CTIME_R
192         ctime_r(&now, nowstr);
193 #else
194         strcpy(nowstr, ctime(&now));
195 #endif
196         memmove(nowstr+16,nowstr+19,7);
197         nowstr[21] = '\0';  // removes the \n
198     }
199     return nowstr;
200 }
201 #endif
202
203 /* -----------------------------------------------------------------------------
204  * Reset a file handle to blocking mode.  We do this for the standard
205  * file descriptors before exiting, because the shell doesn't always
206  * clean up for us.
207  * -------------------------------------------------------------------------- */
208
209 #if !defined(mingw32_HOST_OS)
210 void
211 resetNonBlockingFd(int fd)
212 {
213   long fd_flags;
214
215   /* clear the non-blocking flag on this file descriptor */
216   fd_flags = fcntl(fd, F_GETFL);
217   if (fd_flags & O_NONBLOCK) {
218     fcntl(fd, F_SETFL, fd_flags & ~O_NONBLOCK);
219   }
220 }
221
222 void
223 setNonBlockingFd(int fd)
224 {
225   long fd_flags;
226
227   /* clear the non-blocking flag on this file descriptor */
228   fd_flags = fcntl(fd, F_GETFL);
229   if (!(fd_flags & O_NONBLOCK)) {
230     fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);
231   }
232 }
233 #else
234 /* Stub defns -- async / non-blocking IO is not done 
235  * via O_NONBLOCK and select() under Win32. 
236  */
237 void resetNonBlockingFd(int fd STG_UNUSED) {}
238 void setNonBlockingFd(int fd STG_UNUSED) {}
239 #endif
240
241 #ifdef PAR
242 static ullong startTime = 0;
243
244 /* used in a parallel setup */
245 ullong
246 msTime(void)
247 {
248 # if defined(HAVE_GETCLOCK) && !defined(alpha_HOST_ARCH) && !defined(hppa1_1_HOST_ARCH)
249     struct timespec tv;
250
251     if (getclock(TIMEOFDAY, &tv) != 0) {
252         fflush(stdout);
253         fprintf(stderr, "Clock failed\n");
254         stg_exit(EXIT_FAILURE);
255     }
256     return tv.tv_sec * LL(1000) + tv.tv_nsec / LL(1000000) - startTime;
257 # elif HAVE_GETTIMEOFDAY && !defined(alpha_HOST_ARCH)
258     struct timeval tv;
259  
260     if (gettimeofday(&tv, NULL) != 0) {
261         fflush(stdout);
262         fprintf(stderr, "Clock failed\n");
263         stg_exit(EXIT_FAILURE);
264     }
265     return tv.tv_sec * LL(1000) + tv.tv_usec / LL(1000) - startTime;
266 # else
267     time_t t;
268     if ((t = time(NULL)) == (time_t) -1) {
269         fflush(stdout);
270         fprintf(stderr, "Clock failed\n");
271         stg_exit(EXIT_FAILURE);
272     }
273     return t * LL(1000) - startTime;
274 # endif
275 }
276 #endif /* PAR */
277
278 /* -----------------------------------------------------------------------------
279    Print large numbers, with punctuation.
280    -------------------------------------------------------------------------- */
281
282 char *
283 ullong_format_string(ullong x, char *s, rtsBool with_commas)
284 {
285     if (x < (ullong)1000) 
286         sprintf(s, "%lu", (lnat)x);
287     else if (x < (ullong)1000000)
288         sprintf(s, (with_commas) ? "%lu,%3.3lu" : "%lu%3.3lu",
289                 (lnat)((x)/(ullong)1000),
290                 (lnat)((x)%(ullong)1000));
291     else if (x < (ullong)1000000000)
292         sprintf(s, (with_commas) ? "%lu,%3.3lu,%3.3lu" :  "%lu%3.3lu%3.3lu",
293                 (lnat)((x)/(ullong)1000000),
294                 (lnat)((x)/(ullong)1000%(ullong)1000),
295                 (lnat)((x)%(ullong)1000));
296     else
297         sprintf(s, (with_commas) ? "%lu,%3.3lu,%3.3lu,%3.3lu" : "%lu%3.3lu%3.3lu%3.3lu",
298                 (lnat)((x)/(ullong)1000000000),
299                 (lnat)((x)/(ullong)1000000%(ullong)1000),
300                 (lnat)((x)/(ullong)1000%(ullong)1000), 
301                 (lnat)((x)%(ullong)1000));
302     return s;
303 }
304
305
306 // Can be used as a breakpoint to set on every heap check failure.
307 #ifdef DEBUG
308 void
309 heapCheckFail( void )
310 {
311 }
312 #endif
313
314 /* 
315  * It seems that pthreads and signals interact oddly in OpenBSD & FreeBSD
316  * pthreads (and possibly others). When linking with -lpthreads, we
317  * have to use pthread_kill to send blockable signals. So use that
318  * when we have a threaded rts. So System.Posix.Signals will call
319  * genericRaise(), rather than raise(3).
320  */
321 int genericRaise(int sig) {
322 #if defined(THREADED_RTS) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS))
323         return pthread_kill(pthread_self(), sig);
324 #else
325         return raise(sig);
326 #endif
327 }
328
329 /* -----------------------------------------------------------------------------
330    Allocating executable memory
331    -------------------------------------------------------------------------- */
332
333 /* Heavily arch-specific, I'm afraid.. */
334
335 /*
336  * Allocate len bytes which are readable, writable, and executable.
337  *
338  * ToDo: If this turns out to be a performance bottleneck, one could
339  * e.g. cache the last VirtualProtect/mprotect-ed region and do
340  * nothing in case of a cache hit.
341  */
342 void*
343 stgMallocBytesRWX(int len)
344 {
345   void *addr = stgMallocBytes(len, "mallocBytesRWX");
346 #if defined(i386_HOST_ARCH) && defined(_WIN32)
347   /* This could be necessary for processors which distinguish between READ and
348      EXECUTE memory accesses, e.g. Itaniums. */
349   DWORD dwOldProtect = 0;
350   if (VirtualProtect (addr, len, PAGE_EXECUTE_READWRITE, &dwOldProtect) == 0) {
351     barf("mallocBytesRWX: failed to protect 0x%p; error=%lu; old protection: %lu\n",
352          addr, (unsigned long)GetLastError(), (unsigned long)dwOldProtect);
353   }
354 #elif defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(darwin_HOST_OS)
355   /* malloced memory isn't executable by default on OpenBSD */
356   my_uintptr_t pageSize         = sysconf(_SC_PAGESIZE);
357   my_uintptr_t mask             = ~(pageSize - 1);
358   my_uintptr_t startOfFirstPage = ((my_uintptr_t)addr          ) & mask;
359   my_uintptr_t startOfLastPage  = ((my_uintptr_t)addr + len - 1) & mask;
360   my_uintptr_t size             = startOfLastPage - startOfFirstPage + pageSize;
361   if (mprotect((void*)startOfFirstPage, (size_t)size, PROT_EXEC | PROT_READ | PROT_WRITE) != 0) {
362     barf("mallocBytesRWX: failed to protect 0x%p\n", addr);
363   }
364 #endif
365   return addr;
366 }