1 /* Pseudothread stacks.
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Library General Public
5 * License as published by the Free Software Foundation; either
6 * version 2 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Library General Public License for more details.
13 * You should have received a copy of the GNU Library General Public
14 * License along with this library; if not, write to the Free
15 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 * $Id: pthr_stack.c,v 1.4 2003/02/05 22:13:33 rich Exp $
20 /* The _PTH_GET_STACK and _PTH_RETURN_STACK functions are responsible
21 * for allocating new stacks and returning them when they are finished.
23 * We are careful to avoid freeing up a stack while we are actually
24 * using it. This means in particular that the _PTH_RETURN_STACK
25 * function doesn't directly free up the current stack. It will
26 * be freed up instead next time this function is called.
28 * Linux has the ability to allocate stacks from anonymous memory.
29 * We use this ability if available. However, Linux also has the
30 * ability to allocate "grows down" stack segments using the
31 * non-portable MAP_GROWSDOWN flag. We *don't* use this feature
32 * because (a) LinuxThreads itself doesn't use it any more and
33 * (b) it can cause intermittent failures if something else
34 * happens to allocate memory in the middle of our (as yet
37 * On Linux we also allocate a guard page to protect against
49 #ifdef HAVE_SYS_MMAN_H
53 #include "pthr_stack.h"
55 #define GUARD_PAGE_SIZE 8192
58 #define MAP_ANONYMOUS MAP_ANON
62 alloc_stack (int size)
66 /* Allocate the actual stack memory. */
67 base = mmap (0, size, PROT_READ|PROT_WRITE|PROT_EXEC,
68 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
69 if (base == MAP_FAILED) return 0;
71 /* Allocate a guard page right at the bottom of the stack. */
72 if (mprotect (base, GUARD_PAGE_SIZE, 0) == -1) abort ();
78 free_stack (void *base, int size)
83 /* Stack pending deallocation (see notes above). */
84 static void *pending_stack_base = 0;
85 static int pending_stack_size = 0;
88 _pth_get_stack (int size)
92 /* Is there a stack waiting to be freed up? If so, free it now. */
93 if (pending_stack_base)
95 free_stack (pending_stack_base, pending_stack_size);
96 pending_stack_base = 0;
99 /* Allocate a stack of the appropriate size, if available. */
100 base = alloc_stack (size);
107 _pth_return_stack (void *base, int size)
109 /* Is there a stack waiting to be freed up? If so, free it now. */
110 if (pending_stack_base)
112 free_stack (pending_stack_base, pending_stack_size);
113 pending_stack_base = 0;
116 /* Don't actually free the stack right now. We're still using it. */
117 pending_stack_base = base;
118 pending_stack_size = size;