gc: runtime option to handle different GC
[nit.git] / clib / nit_main.c
1 /* This file is part of NIT ( http://www.nitlanguage.org ).
2 *
3 * Copyright 2006-2009 Jean Privat <jean@pryen.org>
4 *
5 * This file is free software, which comes along with NIT. This software is
6 * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
7 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
8 * PARTICULAR PURPOSE. You can modify it is you want, provided this header
9 * is kept unaltered, and a notification of the changes is added.
10 * You are allowed to redistribute it and sell it, alone or is a part of
11 * another product.
12 */
13
14 #include "nit_common.h"
15 #include <signal.h>
16 #include <stdarg.h>
17
18 bigint object_id_counter = 1000000;
19 enum gc_option { large, boehm } gc_option;
20
21 #ifdef WITH_LIBGC
22 #define GC_DEBUG
23 #include <gc/gc.h>
24 #endif
25
26 void *large_alloc(size_t s0)
27 {
28 static char * alloc_pos = NULL;
29 static size_t alloc_size = 0;
30 void * res;
31 size_t s = ((s0+3)/4)*4;
32 if(alloc_size < s) {
33 alloc_size = s + 1024*1024;
34 alloc_pos = (char *)calloc(alloc_size, 1);
35 }
36 res = alloc_pos;
37 alloc_size -= s;
38 alloc_pos += s;
39 return res;
40 }
41
42 void * alloc(size_t s0)
43 {
44 switch (gc_option) {
45 #ifdef WITH_LIBGC
46 case boehm: return GC_MALLOC(s0);
47 #endif
48 case large:
49 default: return large_alloc(s0);
50 }
51 }
52
53 int glob_argc;
54 char **glob_argv;
55 val_t G_sys;
56
57 void exithandler(int s) {
58 fprintf(stderr, "Recieved signal %d\n", s);
59 nit_exit(1);
60 }
61 void initialize_gc_option(void) {
62 /* GC default */
63 #ifdef WITH_LIBGC
64 gc_option = boehm;
65 #else
66 gc_option = large;
67 #endif
68
69 /* Process GC runtime selection */
70 if (getenv("NIT_GC_OPTION") != NULL) {
71 char *opt=getenv("NIT_GC_OPTION");
72 if (strcmp(opt, "boehm")==0) {
73 #ifdef WITH_LIBGC
74 gc_option = boehm;
75 #else
76 fprintf(stderr, "Compiled without Boehm GC support. Using default.\n");
77 #endif
78 } else if (strcmp(opt, "large")==0) {
79 gc_option = large;
80 } else {
81 fprintf(stderr, "Invalid GC option in NIT_GC_OPTION environment variable. Using default.\n");
82 }
83 }
84
85 /* Initialize GC (if needed) */
86 switch(gc_option) {
87 #ifdef WITH_LIBGC
88 case boehm: GC_INIT(); break;
89 #endif
90 default: break; /* Nothing */
91 }
92 }
93 void prepare_signals(void) {
94 initialize_gc_option();
95
96 signal(SIGINT,exithandler);
97 signal(SIGABRT,exithandler);
98 signal(SIGSEGV,exithandler);
99 signal(SIGILL, exithandler);
100 signal(SIGFPE, exithandler);
101 signal(SIGTERM,exithandler);
102 signal(SIGBUS, exithandler);
103 }
104 struct trace_t *tracehead = NULL;
105 void nit_exit(int i) {
106 fprintf(stderr, ",---- Stack trace -- - - -\n");
107 while(tracehead != NULL) {
108 fprintf(stderr, "| %s (%s:%d)\n", tracehead->meth, tracehead->file, tracehead->line);
109 if (tracehead == tracehead->prev) break;
110 tracehead = tracehead->prev;
111 }
112 fprintf(stderr, "`------------------- - - -\n");
113 exit(i);
114 }