RtsUtils.c 5.9 KB
Newer Older
1
/* -----------------------------------------------------------------------------
2
 * $Id: RtsUtils.c,v 1.11 2000/01/12 15:15:17 simonmar Exp $
3 4
 *
 * (c) The GHC Team, 1998-1999
5 6 7 8 9 10 11 12 13 14 15
 *
 * General utility functions used in the RTS.
 *
 * ---------------------------------------------------------------------------*/

#include "Rts.h"
#include "RtsAPI.h"
#include "RtsFlags.h"
#include "Hooks.h"
#include "Main.h"
#include "RtsUtils.h"
16
#include "Ticky.h"
17 18 19 20 21

#ifdef HAVE_TIME_H
#include <time.h>
#endif

22 23 24 25
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

26 27 28 29 30 31 32 33
#include <stdarg.h>

/* variable-argument error function. */

void barf(char *s, ...)
{
  va_list ap;
  va_start(ap,s);
34
  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
35 36 37 38 39 40 41
  if (prog_argv != NULL && prog_argv[0] != NULL) {
    fprintf(stderr, "%s: fatal error: ", prog_argv[0]);
  } else {
    fprintf(stderr, "fatal error: ");
  }
  vfprintf(stderr, s, ap);
  fprintf(stderr, "\n");
sof's avatar
sof committed
42
  fflush(stderr);
43 44 45
  stg_exit(EXIT_FAILURE);
}

46 47 48 49 50 51 52 53 54 55 56 57
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");
}

58 59 60 61
void belch(char *s, ...)
{
  va_list ap;
  va_start(ap,s);
62
  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
63 64 65 66 67 68 69 70 71 72 73 74
  vfprintf(stderr, s, ap);
  fprintf(stderr, "\n");
}

/* result-checking malloc wrappers. */

void *
stgMallocBytes (int n, char *msg)
{
    char *space;

    if ((space = (char *) malloc((size_t) n)) == NULL) {
75
      /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
76 77 78 79 80 81 82 83 84 85 86 87
	MallocFailHook((W_) n, msg); /*msg*/
	stg_exit(EXIT_FAILURE);
    }
    return space;
}

void *
stgReallocBytes (void *p, int n, char *msg)
{
    char *space;

    if ((space = (char *) realloc(p, (size_t) n)) == NULL) {
88
      /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
	MallocFailHook((W_) n, msg); /*msg*/
	exit(EXIT_FAILURE);
    }
    return space;
}

void *
stgMallocWords (int n, char *msg)
{
  return(stgMallocBytes(n * sizeof(W_), msg));
}

void *
stgReallocWords (void *p, int n, char *msg)
{
  return(stgReallocBytes(p, n * sizeof(W_), msg));
}

void 
_stgAssert (char *filename, nat linenum)
{
110
  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
111 112 113 114 115 116 117 118 119 120 121
  fprintf(stderr, "ASSERTION FAILED: file %s, line %u\n", filename, linenum);
  abort();
}

/* -----------------------------------------------------------------------------
   Stack overflow
   
   Not sure if this belongs here.
   -------------------------------------------------------------------------- */

void
122
stackOverflow(void)
123
{
124
  StackOverflowHook(RtsFlags.GcFlags.maxStkSize * sizeof(W_));
125 126

#if defined(TICKY_TICKY)
127
  if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
128 129 130 131 132 133
#endif
}

void
heapOverflow(void)
{
134 135 136 137
  /* don't fflush(stdout); WORKAROUND bug in Linux glibc */
  OutOfHeapHook(0/*unknown request size*/, 
		RtsFlags.GcFlags.maxHeapSize * BLOCK_SIZE);
  
138
#if defined(TICKY_TICKY)
139
  if (RtsFlags.TickyFlags.showTickyStats) PrintTickyInfo();
140 141
#endif

142
  stg_exit(EXIT_FAILURE);
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
}

/* -----------------------------------------------------------------------------
   Out-of-line strlen.

   Used in addr2Integer because the C compiler on x86 chokes on
   strlen, trying to inline it with not enough registers available.
   -------------------------------------------------------------------------- */

nat stg_strlen(char *s)
{
   char *p = s;

   while (*p) p++;
   return p-s;
}


/* -----------------------------------------------------------------------------
   genSym stuff, used by GHC itself for its splitting unique supply.

   ToDo: put this somewhere sensible.
   -------------------------------------------------------------------------  */

I_ __GenSymCounter = 0;

I_
170
genSymZh(void)
171 172 173 174
{
    return(__GenSymCounter++);
}
I_
175
resetGenSymZh(void) /* it's your funeral */
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201
{
    __GenSymCounter=0;
    return(__GenSymCounter);
}

/* -----------------------------------------------------------------------------
   Get the current time as a string.  Used in profiling reports.
   -------------------------------------------------------------------------- */

#if defined(PROFILING) || defined(DEBUG)
char *
time_str(void)
{
    static time_t now = 0;
    static char nowstr[26];

    if (now == 0) {
	time(&now);
	strcpy(nowstr, ctime(&now));
	strcpy(nowstr+16,nowstr+19);
	nowstr[21] = '\0';
    }
    return nowstr;
}
#endif

202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
/* -----------------------------------------------------------------------------
 * 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.
 * -------------------------------------------------------------------------- */

void
resetNonBlockingFd(int fd)
{
  long fd_flags;

#if !defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__)
  /* 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);
  }
#endif
}

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247
/* -----------------------------------------------------------------------------
   Print large numbers, with punctuation.
   -------------------------------------------------------------------------- */

char *
ullong_format_string(ullong x, char *s, rtsBool with_commas)
{
    if (x < (ullong)1000) 
	sprintf(s, "%d", (nat)x);
    else if (x < (ullong)1000000)
	sprintf(s, (with_commas) ? "%ld,%3.3ld" : "%ld%3.3ld",
		(nat)((x)/(ullong)1000),
		(nat)((x)%(ullong)1000));
    else if (x < (ullong)1000000000)
	sprintf(s, (with_commas) ? "%ld,%3.3ld,%3.3ld" :  "%ld%3.3ld%3.3ld",
		(nat)((x)/(ullong)1000000),
		(nat)((x)/(ullong)1000%(ullong)1000),
		(nat)((x)%(ullong)1000));
    else
	sprintf(s, (with_commas) ? "%ld,%3.3ld,%3.3ld,%3.3ld" : "%ld%3.3ld%3.3ld%3.3ld",
		(nat)((x)/(ullong)1000000000),
		(nat)((x)/(ullong)1000000%(ullong)1000),
		(nat)((x)/(ullong)1000%(ullong)1000), 
		(nat)((x)%(ullong)1000));
    return s;
}