[project @ 2002-02-14 16:55:07 by sof]
[ghc-hetmet.git] / ghc / rts / RtsUtils.c
index 2ed09d3..e077204 100644 (file)
@@ -1,11 +1,17 @@
 /* -----------------------------------------------------------------------------
- * $Id: RtsUtils.c,v 1.3 1999/01/21 10:31:49 simonm Exp $
+ * $Id: RtsUtils.c,v 1.24 2002/02/14 16:55:07 sof Exp $
+ *
+ * (c) The GHC Team, 1998-1999
  *
  * General utility functions used in the RTS.
  *
  * ---------------------------------------------------------------------------*/
 
+/* gettimeofday isn't POSIX */
+/* #include "PosixSource.h" */
+
 #include "Rts.h"
+#include "RtsTypes.h"
 #include "RtsAPI.h"
 #include "RtsFlags.h"
 #include "Hooks.h"
 #include <time.h>
 #endif
 
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+
+#ifdef HAVE_GETTIMEOFDAY
+#include <sys/time.h>
+#endif
+
 #include <stdarg.h>
 
 /* variable-argument error function. */
@@ -25,7 +39,7 @@ void barf(char *s, ...)
 {
   va_list ap;
   va_start(ap,s);
-  fflush(stdout);
+  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
   if (prog_argv != NULL && prog_argv[0] != NULL) {
     fprintf(stderr, "%s: fatal error: ", prog_argv[0]);
   } else {
@@ -33,14 +47,27 @@ void barf(char *s, ...)
   }
   vfprintf(stderr, s, ap);
   fprintf(stderr, "\n");
-  stg_exit(EXIT_FAILURE);
+  fflush(stderr);
+  stg_exit(EXIT_INTERNAL_ERROR);
+}
+
+void prog_belch(char *s, ...)
+{
+  va_list ap;
+  va_start(ap,s);
+  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+  if (prog_argv != NULL && prog_argv[0] != NULL) {
+    fprintf(stderr, "%s: ", prog_argv[0]);
+  } 
+  vfprintf(stderr, s, ap);
+  fprintf(stderr, "\n");
 }
 
 void belch(char *s, ...)
 {
   va_list ap;
   va_start(ap,s);
-  fflush(stdout);
+  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
   vfprintf(stderr, s, ap);
   fprintf(stderr, "\n");
 }
@@ -53,9 +80,9 @@ stgMallocBytes (int n, char *msg)
     char *space;
 
     if ((space = (char *) malloc((size_t) n)) == NULL) {
-       fflush(stdout);
-       MallocFailHook((W_) n, msg); /*msg*/
-       stg_exit(EXIT_FAILURE);
+      /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+      MallocFailHook((W_) n, msg); /*msg*/
+      stg_exit(EXIT_INTERNAL_ERROR);
     }
     return space;
 }
@@ -66,9 +93,9 @@ stgReallocBytes (void *p, int n, char *msg)
     char *space;
 
     if ((space = (char *) realloc(p, (size_t) n)) == NULL) {
-       fflush(stdout);
-       MallocFailHook((W_) n, msg); /*msg*/
-       exit(EXIT_FAILURE);
+      /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+      MallocFailHook((W_) n, msg); /*msg*/
+      stg_exit(EXIT_INTERNAL_ERROR);
     }
     return space;
 }
@@ -85,23 +112,25 @@ stgReallocWords (void *p, int n, char *msg)
   return(stgReallocBytes(p, n * sizeof(W_), 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;
+}
+
 void 
-_stgAssert (char *filename, nat linenum)
+_stgAssert (char *filename, unsigned int linenum)
 {
   fflush(stdout);
   fprintf(stderr, "ASSERTION FAILED: file %s, line %u\n", filename, linenum);
+  fflush(stderr);
   abort();
 }
 
-StgStablePtr errorHandler = -1; /* -1 indicates no handler installed */
-
-void
-raiseError( StgStablePtr handler STG_UNUSED )
-{
-  shutdownHaskell();
-  stg_exit(EXIT_FAILURE);
-}
-
 /* -----------------------------------------------------------------------------
    Stack overflow
    
@@ -109,30 +138,27 @@ raiseError( StgStablePtr handler STG_UNUSED )
    -------------------------------------------------------------------------- */
 
 void
-stackOverflow(nat max_stack_size)
+stackOverflow(void)
 {
-    fflush(stdout);
-    StackOverflowHook(max_stack_size * sizeof(W_)); /*msg*/
+  StackOverflowHook(RtsFlags.GcFlags.maxStkSize * sizeof(W_));
 
 #if defined(TICKY_TICKY)
-    if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
+  if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
 #endif
-
-    stg_exit(EXIT_FAILURE);
 }
 
 void
 heapOverflow(void)
 {
-    fflush(stdout);
-    OutOfHeapHook(0/*unknown request size*/, 
-                 RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);
-
+  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
+  OutOfHeapHook(0/*unknown request size*/, 
+               RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);
+  
 #if defined(TICKY_TICKY)
-    if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
+  if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
 #endif
 
-    stg_exit(EXIT_FAILURE);
+  stg_exit(EXIT_HEAPOVERFLOW);
 }
 
 /* -----------------------------------------------------------------------------
@@ -175,7 +201,7 @@ resetGenSymZh(void) /* it's your funeral */
    Get the current time as a string.  Used in profiling reports.
    -------------------------------------------------------------------------- */
 
-#if defined(PROFILING) || defined(DEBUG)
+#if defined(PROFILING) || defined(DEBUG) || defined(PAR) || defined(GRAN)
 char *
 time_str(void)
 {
@@ -193,6 +219,75 @@ time_str(void)
 #endif
 
 /* -----------------------------------------------------------------------------
+ * Reset a file handle to blocking mode.  We do this for the standard
+ * file descriptors before exiting, because the shell doesn't always
+ * clean up for us.
+ * -------------------------------------------------------------------------- */
+
+#if !defined(mingw32_TARGET_OS)
+void
+resetNonBlockingFd(int fd)
+{
+  long fd_flags;
+
+  /* clear the non-blocking flag on this file descriptor */
+  fd_flags = fcntl(fd, F_GETFL);
+  if (fd_flags & O_NONBLOCK) {
+    fcntl(fd, F_SETFL, fd_flags & ~O_NONBLOCK);
+  }
+}
+
+void
+setNonBlockingFd(int fd)
+{
+  long fd_flags;
+
+  /* clear the non-blocking flag on this file descriptor */
+  fd_flags = fcntl(fd, F_GETFL);
+  fcntl(fd, F_SETFL, fd_flags | O_NONBLOCK);
+}
+#else
+/* Don't support non-blocking FDs (yet) on mingw */
+void resetNonBlockingFd(int fd STG_UNUSED) {}
+void setNonBlockingFd(int fd STG_UNUSED) {}
+#endif
+
+static ullong startTime = 0;
+
+/* used in a parallel setup */
+ullong
+msTime(void)
+{
+# if defined(HAVE_GETCLOCK) && !defined(alpha_TARGET_ARCH) && !defined(hppa1_1_TARGET_ARCH)
+    struct timespec tv;
+
+    if (getclock(TIMEOFDAY, &tv) != 0) {
+       fflush(stdout);
+       fprintf(stderr, "Clock failed\n");
+       stg_exit(EXIT_FAILURE);
+    }
+    return tv.tv_sec * LL(1000) + tv.tv_nsec / LL(1000000) - startTime;
+# elif HAVE_GETTIMEOFDAY && !defined(alpha_TARGET_ARCH)
+    struct timeval tv;
+    if (gettimeofday(&tv, NULL) != 0) {
+       fflush(stdout);
+       fprintf(stderr, "Clock failed\n");
+       stg_exit(EXIT_FAILURE);
+    }
+    return tv.tv_sec * LL(1000) + tv.tv_usec / LL(1000) - startTime;
+# else
+    time_t t;
+    if ((t = time(NULL)) == (time_t) -1) {
+       fflush(stdout);
+       fprintf(stderr, "Clock failed\n");
+       stg_exit(EXIT_FAILURE);
+    }
+    return t * LL(1000) - startTime;
+# endif
+}
+
+/* -----------------------------------------------------------------------------
    Print large numbers, with punctuation.
    -------------------------------------------------------------------------- */