Newer
Older
{
if (WRITE(GC_stderr, s, strlen(s)) < 0) ABORT("write to stderr failed");
}
#if defined(LINUX) && !defined(SMALL_CONFIG)
void GC_err_write(buf, len)
GC_CONST char *buf;
size_t len;
{
if (WRITE(GC_stderr, buf, len) < 0) ABORT("write to stderr failed");
}
#endif
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
# if defined(__STDC__) || defined(__cplusplus)
void GC_default_warn_proc(char *msg, GC_word arg)
# else
void GC_default_warn_proc(msg, arg)
char *msg;
GC_word arg;
# endif
{
GC_err_printf1(msg, (unsigned long)arg);
}
GC_warn_proc GC_current_warn_proc = GC_default_warn_proc;
# if defined(__STDC__) || defined(__cplusplus)
GC_warn_proc GC_set_warn_proc(GC_warn_proc p)
# else
GC_warn_proc GC_set_warn_proc(p)
GC_warn_proc p;
# endif
{
GC_warn_proc result;
# ifdef GC_WIN32_THREADS
GC_ASSERT(GC_is_initialized);
# endif
LOCK();
result = GC_current_warn_proc;
GC_current_warn_proc = p;
UNLOCK();
return(result);
}
# if defined(__STDC__) || defined(__cplusplus)
GC_word GC_set_free_space_divisor (GC_word value)
# else
GC_word GC_set_free_space_divisor (value)
GC_word value;
# endif
{
GC_word old = GC_free_space_divisor;
GC_free_space_divisor = value;
return old;
}
# if defined(MSWIN32)
(void) MessageBoxA(NULL, msg, "Fatal error in gc", MB_ICONERROR|MB_OK);
# else
GC_err_printf1("%s\n", msg);
# endif
if (GETENV("GC_LOOP_ON_ABORT") != NULL) {
/* In many cases it's easier to debug a running process. */
/* It's arguably nicer to sleep, but that makes it harder */
/* to look at the thread if the debugger doesn't know much */
/* about threads. */
DebugBreak();
# else
(void) abort();
# endif
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
/* Helper procedures for new kind creation. */
void ** GC_new_free_list_inner()
{
void *result = GC_INTERNAL_MALLOC((MAXOBJSZ+1)*sizeof(ptr_t), PTRFREE);
if (result == 0) ABORT("Failed to allocate freelist for new kind");
BZERO(result, (MAXOBJSZ+1)*sizeof(ptr_t));
return result;
}
void ** GC_new_free_list()
{
void *result;
LOCK(); DISABLE_SIGNALS();
result = GC_new_free_list_inner();
UNLOCK(); ENABLE_SIGNALS();
return result;
}
int GC_new_kind_inner(fl, descr, adjust, clear)
void **fl;
GC_word descr;
int adjust;
int clear;
{
int result = GC_n_kinds++;
if (GC_n_kinds > MAXOBJKINDS) ABORT("Too many kinds");
GC_obj_kinds[result].ok_freelist = (ptr_t *)fl;
GC_obj_kinds[result].ok_reclaim_list = 0;
GC_obj_kinds[result].ok_descriptor = descr;
GC_obj_kinds[result].ok_relocate_descr = adjust;
GC_obj_kinds[result].ok_init = clear;
return result;
}
int GC_new_kind(fl, descr, adjust, clear)
void **fl;
GC_word descr;
int adjust;
int clear;
{
int result;
LOCK(); DISABLE_SIGNALS();
result = GC_new_kind_inner(fl, descr, adjust, clear);
UNLOCK(); ENABLE_SIGNALS();
return result;
}
int GC_new_proc_inner(proc)
GC_mark_proc proc;
{
int result = GC_n_mark_procs++;
if (GC_n_mark_procs > MAX_MARK_PROCS) ABORT("Too many mark procedures");
GC_mark_procs[result] = proc;
return result;
}
int GC_new_proc(proc)
GC_mark_proc proc;
{
int result;
LOCK(); DISABLE_SIGNALS();
result = GC_new_proc_inner(proc);
UNLOCK(); ENABLE_SIGNALS();
return result;
}
#if !defined(NO_DEBUGGING)
void GC_dump()
{
GC_printf0("***Static roots:\n");
GC_print_static_roots();
GC_printf0("\n***Heap sections:\n");
GC_print_heap_sects();
GC_printf0("\n***Free blocks:\n");
GC_print_hblkfreelist();
GC_printf0("\n***Blocks in use:\n");
GC_print_block_list();
GC_printf0("\n***Finalization statistics:\n");
GC_print_finalization_stats();