X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FRtsUtils.c;h=3e7e225dda3314468ed3deccab22b7d6545e2437;hb=28a464a75e14cece5db40f2765a29348273ff2d2;hp=f4d61b1992dda014b9b080402d8738375f9ca85b;hpb=20d697a1c300663df2c1472e222e57c84c4385fc;p=ghc-hetmet.git diff --git a/ghc/rts/RtsUtils.c b/ghc/rts/RtsUtils.c index f4d61b1..3e7e225 100644 --- a/ghc/rts/RtsUtils.c +++ b/ghc/rts/RtsUtils.c @@ -32,13 +32,30 @@ #include #include -#if defined(openbsd_TARGET_OS) -# ifdef HAVE_SIGNAL_H -# include -# endif -# ifdef HAVE_PTHREAD_H -# include -# endif +#ifdef HAVE_SIGNAL_H +#include +#endif + +#if defined(THREADED_RTS) && defined(openbsd_HOST_OS) && defined(HAVE_PTHREAD_H) +#include +#endif + +#if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(darwin_HOST_OS) +#include +#include +#include + +/* no C99 header stdint.h on OpenBSD? */ +#if defined(openbsd_HOST_OS) +typedef unsigned long my_uintptr_t; +#else +#include +typedef uintptr_t my_uintptr_t; +#endif +#endif + +#if defined(_WIN32) +#include #endif /* ----------------------------------------------------------------------------- @@ -74,11 +91,14 @@ stgReallocBytes (void *p, int n, char *msg) void * stgCallocBytes (int n, int m, char *msg) { - int i; - int sz = n * m; - char* p = stgMallocBytes(sz, msg); - for (i = 0; i < sz; i++) p[i] = 0; - return p; + char *space; + + if ((space = (char *) calloc((size_t) n, (size_t) m)) == NULL) { + /* don't fflush(stdout); WORKAROUND bug in Linux glibc */ + MallocFailHook((W_) n*m, msg); /*msg*/ + stg_exit(EXIT_INTERNAL_ERROR); + } + return space; } /* To simplify changing the underlying allocator used @@ -90,15 +110,6 @@ stgFree(void* p) free(p); } -void -_stgAssert (char *filename, unsigned int linenum) -{ - fflush(stdout); - fprintf(stderr, "ASSERTION FAILED: file %s, line %u\n", filename, linenum); - fflush(stderr); - abort(); -} - /* ----------------------------------------------------------------------------- Stack overflow @@ -178,9 +189,13 @@ time_str(void) if (now == 0) { time(&now); +#if HAVE_CTIME_R + ctime_r(&now, nowstr); +#else strcpy(nowstr, ctime(&now)); - strcpy(nowstr+16,nowstr+19); - nowstr[21] = '\0'; +#endif + memmove(nowstr+16,nowstr+19,7); + nowstr[21] = '\0'; // removes the \n } return nowstr; } @@ -192,7 +207,7 @@ time_str(void) * clean up for us. * -------------------------------------------------------------------------- */ -#if !defined(mingw32_TARGET_OS) +#if !defined(mingw32_HOST_OS) void resetNonBlockingFd(int fd) { @@ -231,7 +246,7 @@ static ullong startTime = 0; ullong msTime(void) { -# if defined(HAVE_GETCLOCK) && !defined(alpha_TARGET_ARCH) && !defined(hppa1_1_TARGET_ARCH) +# if defined(HAVE_GETCLOCK) && !defined(alpha_HOST_ARCH) && !defined(hppa1_1_HOST_ARCH) struct timespec tv; if (getclock(TIMEOFDAY, &tv) != 0) { @@ -240,7 +255,7 @@ msTime(void) stg_exit(EXIT_FAILURE); } return tv.tv_sec * LL(1000) + tv.tv_nsec / LL(1000000) - startTime; -# elif HAVE_GETTIMEOFDAY && !defined(alpha_TARGET_ARCH) +# elif HAVE_GETTIMEOFDAY && !defined(alpha_HOST_ARCH) struct timeval tv; if (gettimeofday(&tv, NULL) != 0) { @@ -298,18 +313,55 @@ heapCheckFail( void ) #endif /* - * It seems that pthreads and signals interact oddly in OpenBSD - * pthreads (and possibly FreeBSD). When linking with -lpthreads, we + * It seems that pthreads and signals interact oddly in OpenBSD & FreeBSD + * pthreads (and possibly others). When linking with -lpthreads, we * have to use pthread_kill to send blockable signals. So use that * when we have a threaded rts. So System.Posix.Signals will call * genericRaise(), rather than raise(3). */ -#if defined(openbsd_TARGET_OS) int genericRaise(int sig) { -# if defined(THREADED_RTS) +#if defined(THREADED_RTS) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS)) return pthread_kill(pthread_self(), sig); -# else +#else return raise(sig); -# endif +#endif } + +/* ----------------------------------------------------------------------------- + Allocating executable memory + -------------------------------------------------------------------------- */ + +/* Heavily arch-specific, I'm afraid.. */ + +/* + * Allocate len bytes which are readable, writable, and executable. + * + * ToDo: If this turns out to be a performance bottleneck, one could + * e.g. cache the last VirtualProtect/mprotect-ed region and do + * nothing in case of a cache hit. + */ +void* +stgMallocBytesRWX(int len) +{ + void *addr = stgMallocBytes(len, "mallocBytesRWX"); +#if defined(i386_HOST_ARCH) && defined(_WIN32) + /* This could be necessary for processors which distinguish between READ and + EXECUTE memory accesses, e.g. Itaniums. */ + DWORD dwOldProtect = 0; + if (VirtualProtect (addr, len, PAGE_EXECUTE_READWRITE, &dwOldProtect) == 0) { + barf("mallocBytesRWX: failed to protect 0x%p; error=%lu; old protection: %lu\n", + addr, (unsigned long)GetLastError(), (unsigned long)dwOldProtect); + } +#elif defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(darwin_HOST_OS) + /* malloced memory isn't executable by default on OpenBSD */ + my_uintptr_t pageSize = sysconf(_SC_PAGESIZE); + my_uintptr_t mask = ~(pageSize - 1); + my_uintptr_t startOfFirstPage = ((my_uintptr_t)addr ) & mask; + my_uintptr_t startOfLastPage = ((my_uintptr_t)addr + len - 1) & mask; + my_uintptr_t size = startOfLastPage - startOfFirstPage + pageSize; + if (mprotect((void*)startOfFirstPage, (size_t)size, PROT_EXEC | PROT_READ | PROT_WRITE) != 0) { + barf("mallocBytesRWX: failed to protect 0x%p\n", addr); + } #endif + return addr; +}