| version 1.4, 2002/07/24 07:46:22 |
version 1.5, 2002/07/24 08:00:12 |
|
|
| */ |
*/ |
| /* Boehm, September 14, 1994 4:44 pm PDT */ |
/* Boehm, September 14, 1994 4:44 pm PDT */ |
| |
|
| # if defined(GC_SOLARIS_THREADS) || defined(SOLARIS_THREADS) |
# if defined(GC_SOLARIS_THREADS) || defined(GC_SOLARIS_PTHREADS) |
| |
|
| # include "private/gc_priv.h" |
# include "private/gc_priv.h" |
| # include "private/solaris_threads.h" |
# include "private/solaris_threads.h" |
|
|
| # include <unistd.h> |
# include <unistd.h> |
| # include <errno.h> |
# include <errno.h> |
| |
|
| |
#ifdef HANDLE_FORK |
| |
--> Not yet supported. Try porting the code from linux_threads.c. |
| |
#endif |
| |
|
| /* |
/* |
| * This is the default size of the LWP arrays. If there are more LWPs |
* This is the default size of the LWP arrays. If there are more LWPs |
| * than this when a stop-the-world GC happens, set_max_lwps will be |
* than this when a stop-the-world GC happens, set_max_lwps will be |
| Line 361 static void restart_all_lwps() |
|
| Line 365 static void restart_all_lwps() |
|
| sizeof (prgregset_t)) != 0) { |
sizeof (prgregset_t)) != 0) { |
| int j; |
int j; |
| |
|
| for(j = 0; j < NGREG; j++) |
for(j = 0; j < NPRGREG; j++) |
| { |
{ |
| GC_printf3("%i: %x -> %x\n", j, |
GC_printf3("%i: %x -> %x\n", j, |
| GC_lwp_registers[i][j], |
GC_lwp_registers[i][j], |
| Line 414 GC_bool GC_thr_initialized = FALSE; |
|
| Line 418 GC_bool GC_thr_initialized = FALSE; |
|
| |
|
| size_t GC_min_stack_sz; |
size_t GC_min_stack_sz; |
| |
|
| size_t GC_page_sz; |
|
| |
|
| /* |
/* |
| * stack_head is stored at the top of free stacks |
* stack_head is stored at the top of free stacks |
| Line 456 ptr_t GC_stack_alloc(size_t * stack_size) |
|
| Line 459 ptr_t GC_stack_alloc(size_t * stack_size) |
|
| GC_stack_free_lists[index] = GC_stack_free_lists[index]->next; |
GC_stack_free_lists[index] = GC_stack_free_lists[index]->next; |
| } else { |
} else { |
| #ifdef MMAP_STACKS |
#ifdef MMAP_STACKS |
| base = (ptr_t)mmap(0, search_sz + GC_page_sz, |
base = (ptr_t)mmap(0, search_sz + GC_page_size, |
| PROT_READ|PROT_WRITE, MAP_PRIVATE |MAP_NORESERVE, |
PROT_READ|PROT_WRITE, MAP_PRIVATE |MAP_NORESERVE, |
| GC_zfd, 0); |
GC_zfd, 0); |
| if (base == (ptr_t)-1) |
if (base == (ptr_t)-1) |
| Line 465 ptr_t GC_stack_alloc(size_t * stack_size) |
|
| Line 468 ptr_t GC_stack_alloc(size_t * stack_size) |
|
| return NULL; |
return NULL; |
| } |
} |
| |
|
| mprotect(base, GC_page_sz, PROT_NONE); |
mprotect(base, GC_page_size, PROT_NONE); |
| /* Should this use divHBLKSZ(search_sz + GC_page_sz) ? -- cf */ |
/* Should this use divHBLKSZ(search_sz + GC_page_size) ? -- cf */ |
| GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz)); |
GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz)); |
| base += GC_page_sz; |
base += GC_page_size; |
| |
|
| #else |
#else |
| base = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_sz); |
base = (ptr_t) GC_scratch_alloc(search_sz + 2*GC_page_size); |
| if (base == NULL) |
if (base == NULL) |
| { |
{ |
| *stack_size = 0; |
*stack_size = 0; |
| return NULL; |
return NULL; |
| } |
} |
| |
|
| base = (ptr_t)(((word)base + GC_page_sz) & ~(GC_page_sz - 1)); |
base = (ptr_t)(((word)base + GC_page_size) & ~(GC_page_size - 1)); |
| /* Protect hottest page to detect overflow. */ |
/* Protect hottest page to detect overflow. */ |
| # ifdef SOLARIS23_MPROTECT_BUG_FIXED |
# ifdef SOLARIS23_MPROTECT_BUG_FIXED |
| mprotect(base, GC_page_sz, PROT_NONE); |
mprotect(base, GC_page_size, PROT_NONE); |
| # endif |
# endif |
| GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz)); |
GC_is_fresh((struct hblk *)base, divHBLKSZ(search_sz)); |
| |
|
| base += GC_page_sz; |
base += GC_page_size; |
| #endif |
#endif |
| } |
} |
| *stack_size = search_sz; |
*stack_size = search_sz; |
| Line 621 GC_thread GC_lookup_thread(thread_t id) |
|
| Line 624 GC_thread GC_lookup_thread(thread_t id) |
|
| return(p); |
return(p); |
| } |
} |
| |
|
| |
/* Solaris 2/Intel uses an initial stack size limit slightly bigger than the |
| |
SPARC default of 8 MB. Account for this to warn only if the user has |
| |
raised the limit beyond the default. |
| |
|
| |
This is identical to DFLSSIZ defined in <sys/vm_machparam.h>. This file |
| |
is installed in /usr/platform/`uname -m`/include, which is not in the |
| |
default include directory list, so copy the definition here. */ |
| |
#ifdef I386 |
| |
# define MAX_ORIG_STACK_SIZE (8 * 1024 * 1024 + ((USRSTACK) & 0x3FFFFF)) |
| |
#else |
| # define MAX_ORIG_STACK_SIZE (8 * 1024 * 1024) |
# define MAX_ORIG_STACK_SIZE (8 * 1024 * 1024) |
| |
#endif |
| |
|
| word GC_get_orig_stack_size() { |
word GC_get_orig_stack_size() { |
| struct rlimit rl; |
struct rlimit rl; |
| Line 654 void GC_my_stack_limits() |
|
| Line 668 void GC_my_stack_limits() |
|
| /* original thread */ |
/* original thread */ |
| /* Empirically, what should be the stack page with lowest */ |
/* Empirically, what should be the stack page with lowest */ |
| /* address is actually inaccessible. */ |
/* address is actually inaccessible. */ |
| stack_size = GC_get_orig_stack_size() - GC_page_sz; |
stack_size = GC_get_orig_stack_size() - GC_page_size; |
| stack = GC_stackbottom - stack_size + GC_page_sz; |
stack = GC_stackbottom - stack_size + GC_page_size; |
| } else { |
} else { |
| stack = me -> stack; |
stack = me -> stack; |
| } |
} |
| Line 693 void GC_push_all_stacks() |
|
| Line 707 void GC_push_all_stacks() |
|
| top = p -> stack + p -> stack_size; |
top = p -> stack + p -> stack_size; |
| } else { |
} else { |
| /* The original stack. */ |
/* The original stack. */ |
| bottom = GC_stackbottom - GC_get_orig_stack_size() + GC_page_sz; |
bottom = GC_stackbottom - GC_get_orig_stack_size() + GC_page_size; |
| top = GC_stackbottom; |
top = GC_stackbottom; |
| } |
} |
| if ((word)sp > (word)bottom && (word)sp < (word)top) bottom = sp; |
if ((word)sp > (word)bottom && (word)sp < (word)top) bottom = sp; |
| Line 778 void GC_thr_init(void) |
|
| Line 792 void GC_thr_init(void) |
|
| GC_thr_initialized = TRUE; |
GC_thr_initialized = TRUE; |
| GC_min_stack_sz = ((thr_min_stack() + 32*1024 + HBLKSIZE-1) |
GC_min_stack_sz = ((thr_min_stack() + 32*1024 + HBLKSIZE-1) |
| & ~(HBLKSIZE - 1)); |
& ~(HBLKSIZE - 1)); |
| GC_page_sz = sysconf(_SC_PAGESIZE); |
|
| #ifdef MMAP_STACKS |
#ifdef MMAP_STACKS |
| GC_zfd = open("/dev/zero", O_RDONLY); |
GC_zfd = open("/dev/zero", O_RDONLY); |
| if (GC_zfd == -1) |
if (GC_zfd == -1) |
| Line 812 int GC_thr_suspend(thread_t target_thread) |
|
| Line 825 int GC_thr_suspend(thread_t target_thread) |
|
| if (result == 0) { |
if (result == 0) { |
| t = GC_lookup_thread(target_thread); |
t = GC_lookup_thread(target_thread); |
| if (t == 0) ABORT("thread unknown to GC"); |
if (t == 0) ABORT("thread unknown to GC"); |
| t -> flags |= SUSPENDED; |
t -> flags |= SUSPNDED; |
| } |
} |
| UNLOCK(); |
UNLOCK(); |
| return(result); |
return(result); |
| Line 828 int GC_thr_continue(thread_t target_thread) |
|
| Line 841 int GC_thr_continue(thread_t target_thread) |
|
| if (result == 0) { |
if (result == 0) { |
| t = GC_lookup_thread(target_thread); |
t = GC_lookup_thread(target_thread); |
| if (t == 0) ABORT("thread unknown to GC"); |
if (t == 0) ABORT("thread unknown to GC"); |
| t -> flags &= ~SUSPENDED; |
t -> flags &= ~SUSPNDED; |
| } |
} |
| UNLOCK(); |
UNLOCK(); |
| return(result); |
return(result); |
| Line 900 GC_thr_create(void *stack_base, size_t stack_size, |
|
| Line 913 GC_thr_create(void *stack_base, size_t stack_size, |
|
| void * stack = stack_base; |
void * stack = stack_base; |
| |
|
| LOCK(); |
LOCK(); |
| if (!GC_thr_initialized) |
if (!GC_is_initialized) GC_init_inner(); |
| { |
|
| GC_thr_init(); |
|
| } |
|
| GC_multithreaded++; |
GC_multithreaded++; |
| if (stack == 0) { |
if (stack == 0) { |
| if (stack_size == 0) stack_size = 1024*1024; |
if (stack_size == 0) stack_size = 1024*1024; |
| Line 917 GC_thr_create(void *stack_base, size_t stack_size, |
|
| Line 927 GC_thr_create(void *stack_base, size_t stack_size, |
|
| my_flags |= CLIENT_OWNS_STACK; |
my_flags |= CLIENT_OWNS_STACK; |
| } |
} |
| if (flags & THR_DETACHED) my_flags |= DETACHED; |
if (flags & THR_DETACHED) my_flags |= DETACHED; |
| if (flags & THR_SUSPENDED) my_flags |= SUSPENDED; |
if (flags & THR_SUSPENDED) my_flags |= SUSPNDED; |
| result = thr_create(stack, stack_size, start_routine, |
result = thr_create(stack, stack_size, start_routine, |
| arg, flags & ~THR_DETACHED, &my_new_thread); |
arg, flags & ~THR_DETACHED, &my_new_thread); |
| if (result == 0) { |
if (result == 0) { |
| Line 938 GC_thr_create(void *stack_base, size_t stack_size, |
|
| Line 948 GC_thr_create(void *stack_base, size_t stack_size, |
|
| return(result); |
return(result); |
| } |
} |
| |
|
| # else /* SOLARIS_THREADS */ |
# else /* !GC_SOLARIS_THREADS */ |
| |
|
| #ifndef LINT |
#ifndef LINT |
| int GC_no_sunOS_threads; |
int GC_no_sunOS_threads; |