1 |
/* |
/* |
2 |
* Mach Operating System |
* Mach Operating System |
3 |
* Copyright (c) 1991,1990 Carnegie Mellon University |
* Copyright (c) 1992,1991,1990 Carnegie Mellon University |
4 |
* All Rights Reserved. |
* All Rights Reserved. |
5 |
* |
* |
6 |
* Permission to use, copy, modify and distribute this software and its |
* Permission to use, copy, modify and distribute this software and its |
26 |
/* |
/* |
27 |
* HISTORY |
* HISTORY |
28 |
* $Log$ |
* $Log$ |
29 |
* Revision 1.7 2001/03/31 23:01:01 roland |
* Revision 1.8 2002/05/27 02:50:41 roland |
30 |
* 2001-03-31 Roland McGrath <roland@frob.com> |
* 2002-05-26 Roland McGrath <roland@frob.com> |
31 |
* |
* |
32 |
* * cthreads.h: Fix obsolescent #endif syntax. |
* Changes merged from CMU MK83a version: |
33 |
* * cthread_internals.h: Likewise. |
* * cthreads.h, options.h: Various cleanups. |
34 |
* * cancel-cond.c: Likewise. |
* * call.c, cthread_data.c, sync.c, mig_support.c, stack.c: Likewise. |
35 |
* * stack.c: Likewise. |
* * i386/cthreads.h, i386/thread.c, i386/lock.s: Likewise. |
36 |
|
* * cthread_internals.h: Add decls for internal functions. |
37 |
|
* (struct cproc): Use vm_offset_t for stack_base and stack_size members. |
38 |
|
* Use natural_t for context member. |
39 |
|
* * cprocs.c: Use prototypes for all defns. |
40 |
* * cthreads.c: Likewise. |
* * cthreads.c: Likewise. |
41 |
* * cprocs.c: Likewise. |
* (cthread_exit): Cast any_t to integer_t before int. |
|
* * call.c: Likewise. |
|
42 |
* |
* |
43 |
* Revision 1.6 1997/02/20 04:30:35 miles |
* Revision 2.14 93/01/14 18:05:58 danner |
44 |
* (__hurd_threadvar_stack_mask, __hurd_threadvar_stack_offset, |
* Converted file to ANSI C. |
45 |
* __hurd_threadvar_max): |
* [92/12/18 pds] |
46 |
* Make extern. |
* 64bit cleanup. |
47 |
* |
* [92/12/02 af] |
|
* Revision 1.5 1995/12/10 13:41:30 roland |
|
|
* (addr_range_check, probe_stack): Functions #if 0'd out. |
|
|
* (stack_init): Don't call probe_stack or frob old stack at all. |
|
|
* Default cthread_stack_size to 16 pages if it is zero. |
|
|
* |
|
|
* Revision 1.4 1994/05/05 16:00:09 roland |
|
|
* entered into RCS |
|
48 |
* |
* |
49 |
* Revision 2.13 92/01/14 16:48:54 rpd |
* Revision 2.13 92/01/14 16:48:54 rpd |
50 |
* Fixed addr_range_check to deallocate the object port from vm_region. |
* Fixed addr_range_check to deallocate the object port from vm_region. |
143 |
|
|
144 |
#define BYTES_TO_PAGES(b) (((b) + vm_page_size - 1) / vm_page_size) |
#define BYTES_TO_PAGES(b) (((b) + vm_page_size - 1) / vm_page_size) |
145 |
|
|
146 |
int cthread_stack_mask; |
vm_offset_t cthread_stack_mask; |
147 |
vm_size_t cthread_stack_size; |
vm_size_t cthread_stack_size; |
148 |
private vm_address_t next_stack_base; |
private vm_address_t next_stack_base; |
149 |
|
|
|
vm_offset_t cproc_stack_base(); /* forward */ |
|
|
|
|
150 |
/* |
/* |
151 |
* Set up a stack segment for a thread. |
* Set up a stack segment for a thread. |
152 |
* Segment has a red zone (invalid page) |
* Segment has a red zone (invalid page) |
176 |
register cproc_t p; |
register cproc_t p; |
177 |
register vm_address_t base; |
register vm_address_t base; |
178 |
{ |
{ |
179 |
|
#if defined(RED_ZONE) |
180 |
register kern_return_t r; |
register kern_return_t r; |
181 |
|
#endif /* defined(RED_ZONE) */ |
182 |
|
|
183 |
p->stack_base = base; |
p->stack_base = base; |
184 |
/* |
/* |
188 |
/* |
/* |
189 |
* Protect red zone. |
* Protect red zone. |
190 |
*/ |
*/ |
191 |
#ifdef RED_ZONE |
#if defined(RED_ZONE) |
192 |
MACH_CALL(vm_protect(mach_task_self(), base + vm_page_size, vm_page_size, FALSE, VM_PROT_NONE), r); |
MACH_CALL(vm_protect(mach_task_self(), base + vm_page_size, vm_page_size, FALSE, VM_PROT_NONE), r); |
193 |
#endif /* RED_ZONE */ |
#endif /* defined(RED_ZONE) */ |
194 |
/* |
/* |
195 |
* Store self pointer. |
* Store self pointer. |
196 |
*/ |
*/ |
197 |
*(cproc_t *)&ur_cthread_ptr(base) = p; |
*(cproc_t *)&ur_cthread_ptr(base) = p; |
198 |
} |
} |
199 |
|
|
200 |
#if 0 /* roland@gnu */ |
#if 0 /* GNU */ |
201 |
vm_offset_t |
private vm_offset_t |
202 |
addr_range_check(start_addr, end_addr, desired_protection) |
addr_range_check(vm_offset_t start_addr, vm_offset_t end_addr, |
203 |
vm_offset_t start_addr, end_addr; |
vm_prot_t desired_protection) |
|
vm_prot_t desired_protection; |
|
204 |
{ |
{ |
205 |
register vm_offset_t addr; |
register vm_offset_t addr; |
206 |
|
|
238 |
* 1. stack grows DOWN |
* 1. stack grows DOWN |
239 |
* 2. There is an unallocated region below the stack. |
* 2. There is an unallocated region below the stack. |
240 |
*/ |
*/ |
241 |
void |
private void |
242 |
probe_stack(stack_bottom, stack_top) |
probe_stack(vm_offset_t *stack_bottom, vm_offset_t *stack_top) |
|
vm_offset_t *stack_bottom; |
|
|
vm_offset_t *stack_top; |
|
243 |
{ |
{ |
244 |
/* |
/* |
245 |
* Since vm_region returns the region starting at |
* Since vm_region returns the region starting at |
284 |
/* |
/* |
285 |
* Check that the entire range exists and is writable |
* Check that the entire range exists and is writable |
286 |
*/ |
*/ |
287 |
} while (end_addr = (addr_range_check(start_addr, |
} while ((end_addr = addr_range_check(start_addr, end_addr, |
288 |
end_addr, |
VM_PROT_READ|VM_PROT_WRITE))); |
|
VM_PROT_READ|VM_PROT_WRITE))); |
|
289 |
/* |
/* |
290 |
* Back off to previous power of 2. |
* Back off to previous power of 2. |
291 |
*/ |
*/ |
300 |
extern unsigned int __hurd_threadvar_max; |
extern unsigned int __hurd_threadvar_max; |
301 |
|
|
302 |
vm_offset_t |
vm_offset_t |
303 |
stack_init(p) |
stack_init(cproc_t p) |
|
cproc_t p; |
|
304 |
{ |
{ |
305 |
#if 0 |
#if 0 |
306 |
vm_offset_t stack_bottom, |
vm_offset_t stack_bottom, |
308 |
start; |
start; |
309 |
vm_size_t size; |
vm_size_t size; |
310 |
kern_return_t r; |
kern_return_t r; |
|
#endif |
|
311 |
|
|
|
void alloc_stack(); |
|
|
|
|
|
#if 0 |
|
312 |
/* |
/* |
313 |
* Probe for bottom and top of stack, as a power-of-2 size. |
* Probe for bottom and top of stack, as a power-of-2 size. |
314 |
*/ |
*/ |
320 |
*/ |
*/ |
321 |
if (cthread_stack_size == 0) |
if (cthread_stack_size == 0) |
322 |
cthread_stack_size = stack_top - stack_bottom; |
cthread_stack_size = stack_top - stack_bottom; |
323 |
#else /* roland@gnu */ |
#else /* GNU */ |
324 |
if (cthread_stack_size == 0) |
if (cthread_stack_size == 0) |
325 |
cthread_stack_size = vm_page_size * 16; /* Reasonable default. */ |
cthread_stack_size = vm_page_size * 16; /* Reasonable default. */ |
326 |
#endif |
#endif /* GNU */ |
327 |
|
|
328 |
#ifdef STACK_GROWTH_UP |
#if defined(STACK_GROWTH_UP) |
329 |
cthread_stack_mask = ~(cthread_stack_size - 1); |
cthread_stack_mask = ~(cthread_stack_size - 1); |
330 |
#else /* STACK_GROWTH_UP */ |
#else /* not defined(STACK_GROWTH_UP) */ |
331 |
cthread_stack_mask = cthread_stack_size - 1; |
cthread_stack_mask = cthread_stack_size - 1; |
332 |
#endif /* STACK_GROWTH_UP */ |
#endif /* defined(STACK_GROWTH_UP) */ |
|
|
|
|
/* Set up the variables so GNU can find its per-thread variables. */ |
|
|
__hurd_threadvar_stack_mask = ~(cthread_stack_size - 1); |
|
|
/* The GNU per-thread variables will be stored just after the |
|
|
cthread-self pointer at the base of the stack. */ |
|
|
#ifdef STACK_GROWTH_UP |
|
|
__hurd_threadvar_stack_offset = sizeof (ur_cthread_t *); |
|
|
#else |
|
|
__hurd_threadvar_stack_offset = (cthread_stack_size - |
|
|
sizeof (ur_cthread_t *) - |
|
|
__hurd_threadvar_max * sizeof (long)); |
|
|
#endif |
|
333 |
|
|
334 |
/* |
/* |
335 |
* Guess at first available region for stack. |
* Guess at first available region for stack. |
341 |
*/ |
*/ |
342 |
alloc_stack(p); |
alloc_stack(p); |
343 |
|
|
344 |
#if 0 |
#if 0 /* GNU */ |
345 |
/* |
/* |
346 |
* Delete rest of old stack. |
* Delete rest of old stack. |
347 |
*/ |
*/ |
348 |
|
|
349 |
#ifdef STACK_GROWTH_UP |
#if defined(STACK_GROWTH_UP) |
350 |
start = (cthread_sp() | (vm_page_size - 1)) + 1 + vm_page_size; |
start = (cthread_sp() | (vm_page_size - 1)) + 1 + vm_page_size; |
351 |
size = stack_top - start; |
size = stack_top - start; |
352 |
#else /* STACK_GROWTH_UP */ |
#else /* not defined(STACK_GROWTH_UP) */ |
353 |
start = stack_bottom; |
start = stack_bottom; |
354 |
size = (cthread_sp() & ~(vm_page_size - 1)) - stack_bottom - |
size = (cthread_sp() & ~(vm_page_size - 1)) - stack_bottom - |
355 |
vm_page_size; |
vm_page_size; |
356 |
#endif /* STACK_GROWTH_UP */ |
#endif /* defined(STACK_GROWTH_UP) */ |
357 |
MACH_CALL(vm_deallocate(mach_task_self(),start,size),r); |
MACH_CALL(vm_deallocate(mach_task_self(),start,size),r); |
358 |
#endif |
#endif /* GNU */ |
359 |
|
|
360 |
/* |
/* |
361 |
* Return new stack; it gets passed back to the caller |
* Return new stack; it gets passed back to the caller |
362 |
* of cthread_init who must switch to it. |
* of cthread_init who must switch to it. |
363 |
*/ |
*/ |
364 |
return cproc_stack_base(p, |
return cproc_stack_base(p, sizeof(ur_cthread_t *) + |
|
sizeof(ur_cthread_t *) + |
|
365 |
/* Account for GNU per-thread variables. */ |
/* Account for GNU per-thread variables. */ |
366 |
__hurd_threadvar_max * sizeof (long int)); |
__hurd_threadvar_max * sizeof (long int)); |
367 |
} |
} |
377 |
*/ |
*/ |
378 |
|
|
379 |
void |
void |
380 |
alloc_stack(p) |
alloc_stack(cproc_t p) |
|
cproc_t p; |
|
381 |
{ |
{ |
382 |
vm_address_t base = next_stack_base; |
vm_address_t base = next_stack_base; |
383 |
|
|
394 |
register cproc_t cproc; |
register cproc_t cproc; |
395 |
register int offset; |
register int offset; |
396 |
{ |
{ |
397 |
#ifdef STACK_GROWTH_UP |
#if defined(STACK_GROWTH_UP) |
398 |
return (cproc->stack_base + offset); |
return (cproc->stack_base + offset); |
399 |
#else /* STACK_GROWTH_UP */ |
#else /* not defined(STACK_GROWTH_UP) */ |
400 |
return (cproc->stack_base + cproc->stack_size - offset); |
return (cproc->stack_base + cproc->stack_size - offset); |
401 |
#endif /* STACK_GROWTH_UP */ |
#endif /* defined(STACK_GROWTH_UP) */ |
402 |
|
|
403 |
} |
} |
404 |
|
|