4 * Cooperative multi-threading stack switch function.
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.23 2003/01/06 18:41:08 rogerh
31 * Add NetBSD patches, taken from the NetBSD pkg patches.
32 * Submitted by Andreas Wrede
34 * Revision 1.22 2002/10/10 04:43:44 robertj
35 * VxWorks port, thanks Martijn Roest
37 * Revision 1.21 2001/08/11 15:38:43 rogerh
38 * Add Mac OS Carbon changes from John Woods <jfw@jfwhome.funhouse.com>
40 * Revision 1.20 2000/03/08 12:17:09 rogerh
43 * Revision 1.19 1999/05/12 02:12:02 robertj
44 * Fixed stack size on alpha
46 * Revision 1.18 1999/05/01 11:29:20 robertj
47 * Alpha linux port changes.
49 * Revision 1.17 1999/03/05 07:03:27 robertj
50 * Some more BeOS port changes.
52 * Revision 1.16 1999/02/22 13:26:54 robertj
55 * Revision 1.15 1998/12/21 06:50:36 robertj
58 * Revision 1.14 1998/12/04 12:21:14 robertj
61 * Revision 1.13 1998/11/05 09:04:16 craigs
62 * Changed free to runtime_free
64 * Revision 1.12 1998/09/24 04:12:21 robertj
65 * Added open software license.
71 #if !defined(P_PTHREADS) && !defined(BE_THREADS) && !defined(P_MAC_MPTHREADS) && !defined(VX_TASKS)
75 #define SET_STACK context[0].__jmpbuf[0].__misc[0] = (long int)stackTop-16;
79 #define SET_STACK context[0].__jmpbuf[JB_SP] = (INT)stackTop-16;
81 #define SET_STACK context[0].__sp = (__ptr_t)stackTop-16;
87 #define USE_MMAP MAP_ANON | MAP_PRIVATE
92 #if defined(P_FREEBSD) || defined(P_OPENBSD) || defined(P_NETBSD)
93 #define SET_STACK context[0]._jb[2] = (int)stackTop-16;
96 #define USE_MMAP MAP_ANON | MAP_PRIVATE
101 #define SET_STACK context[0].__jmpbuf[JB_SP] = (int)stackTop-16;
105 #define SETJMP_PROLOG __asm__ ("ta 3");
106 #define SET_STACK context[2] = ((int)stackTop-1024) & ~7;
110 #define SETJMP_PROLOG __asm__ ("ta 3");
111 #define SET_STACK context[1] = ((int)stackTop-1024) & ~7;
113 //#define USE_MMAP MAP_PRIVATE | MAP_NORESERVE
114 #include <sys/mman.h>
118 #define SET_STACK context[1] = (int)(stackBase+64*2);
122 #define SET_STACK context[JB_SP] = (int)(stackTop-16);
125 #ifndef SETJMP_PROLOG
126 #define SETJMP_PROLOG
130 #define STACK_MIN 10240
137 static PThread
* localThis
;
139 void PThread::SwitchContext(PThread
* from
)
142 // no need to switch to ourselves
149 // save context for old thread
151 if (setjmp(from
->context
) != 0) // Are being reactivated from previous yield
154 // if starting the current thread, create a context, give it a new stack
155 // and then switch to it.
156 // if we have just switched into a new thread, execute the BeginThread
158 if (status
== Starting
) {
161 if (setjmp(context
) != 0) { // Are being reactivated from previous yield
162 localThis
->BeginThread();
163 PAssertAlways("Return from BeginThread not allowed");
168 // switch to the new thread
169 longjmp(context
, TRUE
);
170 PAssertAlways("Return from longjmp not allowed");
174 #warning No lightweight thread context switch mechanism defined
175 PAssertAlways("SwitchContext() not implemented");
181 void PThread::AllocateStack(PINDEX stackProtoSize
)
183 int stackSize
= STACK_MULT
*PMAX(STACK_MIN
, stackProtoSize
);
185 #if defined(USE_MMAP)
186 stackBase
= (char *)mmap(0,
188 PROT_READ
| PROT_WRITE
,
191 PAssert(stackBase
!= (char *)-1, "Cannot allocate virtual stack for thread");
193 stackBase
= (char *)malloc(stackSize
);
194 PAssert(stackBase
!= NULL
, "Cannot allocate stack for thread");
196 stackTop
= stackBase
+ stackSize
-1;
199 void PThread::FreeStack()
201 if (stackBase
!= NULL
)
202 #if defined(USE_MMAP)
203 munmap(stackBase
, stackTop
-stackBase
+1);
209 #endif // !P_PTHREADS && !BE_THREADS