diff options
| author | David Lovemore | 2012-05-22 16:08:49 +0100 |
|---|---|---|
| committer | David Lovemore | 2012-05-22 16:08:49 +0100 |
| commit | 4c8144b692d2846b7826928b0fa5997d1de9a1f1 (patch) | |
| tree | be9ac769e7e3b607fbae810036a3414fbace426e /mps/code | |
| parent | b9dbf430ef23dec78732f9e050b5430b0707069d (diff) | |
| download | emacs-4c8144b692d2846b7826928b0fa5997d1de9a1f1.tar.gz emacs-4c8144b692d2846b7826928b0fa5997d1de9a1f1.zip | |
Split windows thread implementation into two files so that the non-architecture specific part can be shared.
Copied from Perforce
Change: 178281
ServerID: perforce.ravenbrook.com
Diffstat (limited to 'mps/code')
| -rw-r--r-- | mps/code/thw3.c | 273 | ||||
| -rw-r--r-- | mps/code/thw3.h | 70 | ||||
| -rw-r--r-- | mps/code/thw3i3.c | 216 | ||||
| -rw-r--r-- | mps/code/w3i3mv.nmk | 4 |
4 files changed, 351 insertions, 212 deletions
diff --git a/mps/code/thw3.c b/mps/code/thw3.c new file mode 100644 index 00000000000..250951018da --- /dev/null +++ b/mps/code/thw3.c | |||
| @@ -0,0 +1,273 @@ | |||
| 1 | /* thw3i3.c: WIN32 THREAD MANAGER | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | ||
| 5 | * | ||
| 6 | * Implements thread registration, suspension, and stack | ||
| 7 | * scanning. See <design/thread-manager/>. | ||
| 8 | * | ||
| 9 | * This supports the <code/th.h> along with <code/thw3i3.c> or <code/thw3i6.c> | ||
| 10 | * | ||
| 11 | * .thread.id: The thread id is used to identify the current thread. | ||
| 12 | * .thread.handle: The thread handle needs the enough access to | ||
| 13 | * be able to suspend threads and to get their context. i.e. | ||
| 14 | * .thread.handle.susp-res: THREAD_SUSPEND_RESUME access | ||
| 15 | * .thread.handle.get-context: THREAD_GET_CONTEXT access | ||
| 16 | * An appropriate handle is created on registration. | ||
| 17 | * | ||
| 18 | * | ||
| 19 | * ASSUMPTIONS | ||
| 20 | * | ||
| 21 | * .error: some major errors are assumed not to happen. | ||
| 22 | * .error.close-handle: CloseHandle is assumed to succeed. | ||
| 23 | * | ||
| 24 | * Other errors are assumed to only happen in certain circumstances. | ||
| 25 | * .error.resume: ResumeThread is assumed to succeed unless the thread | ||
| 26 | * has been destroyed (in fact, perversely, it appears to succeeed even | ||
| 27 | * when the thread has been destroyed). | ||
| 28 | * .error.suspend: SuspendThread is assumed to succeed unless the thread | ||
| 29 | * has been destroyed. | ||
| 30 | * | ||
| 31 | * | ||
| 32 | * .nt: uses Win32 specific stuff | ||
| 33 | * HANDLE | ||
| 34 | * DWORD | ||
| 35 | * GetCurrentProcess | ||
| 36 | * DuplicateHandle | ||
| 37 | * THREAD_SUSPEND_RESUME | ||
| 38 | * GetCurrentThreadId | ||
| 39 | * CloseHandle | ||
| 40 | * SuspendThread | ||
| 41 | * ResumeThread | ||
| 42 | * | ||
| 43 | */ | ||
| 44 | |||
| 45 | #include "mpm.h" | ||
| 46 | |||
| 47 | #if !defined(MPS_OS_W3) /* .nt */ | ||
| 48 | #error "Compiling thw3 when MPS_OS_W3 not defined." | ||
| 49 | #endif | ||
| 50 | |||
| 51 | #include "thw3.h" | ||
| 52 | |||
| 53 | #include "mpswin.h" | ||
| 54 | |||
| 55 | SRCID(thw3, "$Id$"); | ||
| 56 | |||
| 57 | |||
| 58 | Bool ThreadCheck(Thread thread) | ||
| 59 | { | ||
| 60 | CHECKS(Thread, thread); | ||
| 61 | CHECKU(Arena, thread->arena); | ||
| 62 | CHECKL(thread->serial < thread->arena->threadSerial); | ||
| 63 | CHECKL(RingCheck(&thread->arenaRing)); | ||
| 64 | return TRUE; | ||
| 65 | } | ||
| 66 | |||
| 67 | |||
| 68 | Bool ThreadCheckSimple(Thread thread) | ||
| 69 | { | ||
| 70 | CHECKS(Thread, thread); | ||
| 71 | return TRUE; | ||
| 72 | } | ||
| 73 | |||
| 74 | |||
| 75 | Res ThreadRegister(Thread *threadReturn, Arena arena) | ||
| 76 | { | ||
| 77 | Res res; | ||
| 78 | Thread thread; | ||
| 79 | HANDLE procHandle; | ||
| 80 | BOOL b; | ||
| 81 | void *p; | ||
| 82 | |||
| 83 | AVER(threadReturn != NULL); | ||
| 84 | AVERT(Arena, arena); | ||
| 85 | |||
| 86 | res = ControlAlloc(&p, arena, sizeof(ThreadStruct), | ||
| 87 | /* withReservoirPermit */ FALSE); | ||
| 88 | if(res != ResOK) | ||
| 89 | return res; | ||
| 90 | thread = (Thread)p; /* avoid pun */ | ||
| 91 | |||
| 92 | /* Duplicate handle gives us a new handle with updated privileges. | ||
| 93 | * .thread.handle describes the ones needed. | ||
| 94 | */ | ||
| 95 | procHandle = GetCurrentProcess(); | ||
| 96 | |||
| 97 | b = DuplicateHandle(procHandle, GetCurrentThread(), procHandle, | ||
| 98 | &thread->handle, | ||
| 99 | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT, | ||
| 100 | FALSE, 0); | ||
| 101 | if(!b) | ||
| 102 | return ResRESOURCE; | ||
| 103 | |||
| 104 | thread->id = GetCurrentThreadId(); | ||
| 105 | |||
| 106 | RingInit(&thread->arenaRing); | ||
| 107 | |||
| 108 | thread->sig = ThreadSig; | ||
| 109 | thread->serial = arena->threadSerial; | ||
| 110 | ++arena->threadSerial; | ||
| 111 | thread->arena = arena; | ||
| 112 | |||
| 113 | AVERT(Thread, thread); | ||
| 114 | |||
| 115 | RingAppend(ArenaThreadRing(arena), &thread->arenaRing); | ||
| 116 | |||
| 117 | *threadReturn = thread; | ||
| 118 | return ResOK; | ||
| 119 | } | ||
| 120 | |||
| 121 | void ThreadDeregister(Thread thread, Arena arena) | ||
| 122 | { | ||
| 123 | Bool b; | ||
| 124 | |||
| 125 | AVERT(Thread, thread); | ||
| 126 | AVERT(Arena, arena); | ||
| 127 | |||
| 128 | RingRemove(&thread->arenaRing); | ||
| 129 | |||
| 130 | thread->sig = SigInvalid; | ||
| 131 | |||
| 132 | RingFinish(&thread->arenaRing); | ||
| 133 | |||
| 134 | b = CloseHandle(thread->handle); | ||
| 135 | AVER(b); /* .error.close-handle */ | ||
| 136 | |||
| 137 | ControlFree(arena, thread, sizeof(ThreadStruct)); | ||
| 138 | } | ||
| 139 | |||
| 140 | |||
| 141 | /* Map over threads on ring calling f on each one except the | ||
| 142 | * current thread. | ||
| 143 | */ | ||
| 144 | static void mapThreadRing(Ring ring, void (*f)(Thread thread)) | ||
| 145 | { | ||
| 146 | Ring node; | ||
| 147 | DWORD id; | ||
| 148 | |||
| 149 | id = GetCurrentThreadId(); | ||
| 150 | node = RingNext(ring); | ||
| 151 | while(node != ring) { | ||
| 152 | Ring next = RingNext(node); | ||
| 153 | Thread thread; | ||
| 154 | |||
| 155 | thread = RING_ELT(Thread, arenaRing, node); | ||
| 156 | AVERT(Thread, thread); | ||
| 157 | if(id != thread->id) /* .thread.id */ | ||
| 158 | (*f)(thread); | ||
| 159 | |||
| 160 | node = next; | ||
| 161 | } | ||
| 162 | } | ||
| 163 | |||
| 164 | static void suspend(Thread thread) | ||
| 165 | { | ||
| 166 | /* .thread.handle.susp-res */ | ||
| 167 | /* .error.suspend */ | ||
| 168 | /* In the error case (SuspendThread returning 0xFFFFFFFF), we */ | ||
| 169 | /* assume the thread has been destroyed (as part of process shutdown). */ | ||
| 170 | /* In which case we simply continue. */ | ||
| 171 | /* [GetLastError appears to return 5 when SuspendThread is called */ | ||
| 172 | /* on a destroyed thread, but I'm not sufficiently confident of this */ | ||
| 173 | /* to check -- drj 1998-04-09] */ | ||
| 174 | (void)SuspendThread(thread->handle); | ||
| 175 | } | ||
| 176 | |||
| 177 | void ThreadRingSuspend(Ring ring) | ||
| 178 | { | ||
| 179 | mapThreadRing(ring, suspend); | ||
| 180 | } | ||
| 181 | |||
| 182 | static void resume(Thread thread) | ||
| 183 | { | ||
| 184 | /* .thread.handle.susp-res */ | ||
| 185 | /* .error.resume */ | ||
| 186 | /* In the error case (ResumeThread returning 0xFFFFFFFF), we */ | ||
| 187 | /* assume the thread has been destroyed (as part of process shutdown). */ | ||
| 188 | /* In which case we simply continue. */ | ||
| 189 | (void)ResumeThread(thread->handle); | ||
| 190 | } | ||
| 191 | |||
| 192 | void ThreadRingResume(Ring ring) | ||
| 193 | { | ||
| 194 | mapThreadRing(ring, resume); | ||
| 195 | } | ||
| 196 | |||
| 197 | |||
| 198 | Thread ThreadRingThread(Ring threadRing) | ||
| 199 | { | ||
| 200 | Thread thread; | ||
| 201 | AVERT(Ring, threadRing); | ||
| 202 | thread = RING_ELT(Thread, arenaRing, threadRing); | ||
| 203 | AVERT(Thread, thread); | ||
| 204 | return thread; | ||
| 205 | } | ||
| 206 | |||
| 207 | /* Must be thread-safe. See <design/interface-c/#thread-safety>. */ | ||
| 208 | Arena ThreadArena(Thread thread) | ||
| 209 | { | ||
| 210 | /* Can't AVER thread as that would not be thread-safe */ | ||
| 211 | /* AVERT(Thread, thread); */ | ||
| 212 | return thread->arena; | ||
| 213 | } | ||
| 214 | |||
| 215 | Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) | ||
| 216 | { | ||
| 217 | Res res; | ||
| 218 | |||
| 219 | res = WriteF(stream, | ||
| 220 | "Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial, | ||
| 221 | " arena $P ($U)\n", | ||
| 222 | (WriteFP)thread->arena, (WriteFU)thread->arena->serial, | ||
| 223 | " handle $W\n", (WriteFW)thread->handle, | ||
| 224 | " id $U\n", (WriteFU)thread->id, | ||
| 225 | "} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial, | ||
| 226 | NULL); | ||
| 227 | if(res != ResOK) | ||
| 228 | return res; | ||
| 229 | |||
| 230 | return ResOK; | ||
| 231 | } | ||
| 232 | |||
| 233 | |||
| 234 | /* C. COPYRIGHT AND LICENSE | ||
| 235 | * | ||
| 236 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | ||
| 237 | * All rights reserved. This is an open source license. Contact | ||
| 238 | * Ravenbrook for commercial licensing options. | ||
| 239 | * | ||
| 240 | * Redistribution and use in source and binary forms, with or without | ||
| 241 | * modification, are permitted provided that the following conditions are | ||
| 242 | * met: | ||
| 243 | * | ||
| 244 | * 1. Redistributions of source code must retain the above copyright | ||
| 245 | * notice, this list of conditions and the following disclaimer. | ||
| 246 | * | ||
| 247 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 248 | * notice, this list of conditions and the following disclaimer in the | ||
| 249 | * documentation and/or other materials provided with the distribution. | ||
| 250 | * | ||
| 251 | * 3. Redistributions in any form must be accompanied by information on how | ||
| 252 | * to obtain complete source code for this software and any accompanying | ||
| 253 | * software that uses this software. The source code must either be | ||
| 254 | * included in the distribution or be available for no more than the cost | ||
| 255 | * of distribution plus a nominal fee, and must be freely redistributable | ||
| 256 | * under reasonable conditions. For an executable file, complete source | ||
| 257 | * code means the source code for all modules it contains. It does not | ||
| 258 | * include source code for modules or files that typically accompany the | ||
| 259 | * major components of the operating system on which the executable file | ||
| 260 | * runs. | ||
| 261 | * | ||
| 262 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 263 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
| 264 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
| 265 | * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 266 | * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 267 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 268 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 269 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 270 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 271 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 272 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 273 | */ | ||
diff --git a/mps/code/thw3.h b/mps/code/thw3.h new file mode 100644 index 00000000000..78e57192236 --- /dev/null +++ b/mps/code/thw3.h | |||
| @@ -0,0 +1,70 @@ | |||
| 1 | /* thw3.h: WIN32 THREAD MANAGER HEADER | ||
| 2 | * | ||
| 3 | * $Id$ | ||
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | ||
| 5 | * | ||
| 6 | * This is used in <code/thw3.c> and <code/thw3i3.c> and <code/thw3i6.c> | ||
| 7 | * | ||
| 8 | * .nt: uses Win32 specific stuff | ||
| 9 | * HANDLE | ||
| 10 | * DWORD | ||
| 11 | */ | ||
| 12 | |||
| 13 | #include "mpm.h" | ||
| 14 | |||
| 15 | #if !defined(MPS_OS_W3) /* .nt */ | ||
| 16 | #error "Compiling thw3 when MPS_OS_W3 not defined." | ||
| 17 | #endif | ||
| 18 | |||
| 19 | #include "mpswin.h" | ||
| 20 | |||
| 21 | typedef struct ThreadStruct { /* Win32 thread structure */ | ||
| 22 | Sig sig; /* <design/sig/> */ | ||
| 23 | Serial serial; /* from arena->threadSerial */ | ||
| 24 | Arena arena; /* owning arena */ | ||
| 25 | RingStruct arenaRing; /* threads attached to arena */ | ||
| 26 | HANDLE handle; /* Handle of thread, see | ||
| 27 | * <code/thw3.c#thread.handle> */ | ||
| 28 | DWORD id; /* Thread id of thread */ | ||
| 29 | } ThreadStruct; | ||
| 30 | |||
| 31 | /* C. COPYRIGHT AND LICENSE | ||
| 32 | * | ||
| 33 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | ||
| 34 | * All rights reserved. This is an open source license. Contact | ||
| 35 | * Ravenbrook for commercial licensing options. | ||
| 36 | * | ||
| 37 | * Redistribution and use in source and binary forms, with or without | ||
| 38 | * modification, are permitted provided that the following conditions are | ||
| 39 | * met: | ||
| 40 | * | ||
| 41 | * 1. Redistributions of source code must retain the above copyright | ||
| 42 | * notice, this list of conditions and the following disclaimer. | ||
| 43 | * | ||
| 44 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 45 | * notice, this list of conditions and the following disclaimer in the | ||
| 46 | * documentation and/or other materials provided with the distribution. | ||
| 47 | * | ||
| 48 | * 3. Redistributions in any form must be accompanied by information on how | ||
| 49 | * to obtain complete source code for this software and any accompanying | ||
| 50 | * software that uses this software. The source code must either be | ||
| 51 | * included in the distribution or be available for no more than the cost | ||
| 52 | * of distribution plus a nominal fee, and must be freely redistributable | ||
| 53 | * under reasonable conditions. For an executable file, complete source | ||
| 54 | * code means the source code for all modules it contains. It does not | ||
| 55 | * include source code for modules or files that typically accompany the | ||
| 56 | * major components of the operating system on which the executable file | ||
| 57 | * runs. | ||
| 58 | * | ||
| 59 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS | ||
| 60 | * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | ||
| 61 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR | ||
| 62 | * PURPOSE, OR NON-INFRINGEMENT, ARE DISCLAIMED. IN NO EVENT SHALL THE | ||
| 63 | * COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
| 64 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
| 65 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF | ||
| 66 | * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON | ||
| 67 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
| 68 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
| 69 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
| 70 | */ | ||
diff --git a/mps/code/thw3i3.c b/mps/code/thw3i3.c index 873f2b4643e..3e2e6ee1a5c 100644 --- a/mps/code/thw3i3.c +++ b/mps/code/thw3i3.c | |||
| @@ -1,32 +1,20 @@ | |||
| 1 | /* thw3i3.c: WIN32 THREAD MANAGER | 1 | /* thw3i3.c: WIN32 THREAD MANAGER x86 |
| 2 | * | 2 | * |
| 3 | * $Id$ | 3 | * $Id$ |
| 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. | 4 | * Copyright (c) 2001 Ravenbrook Limited. See end of file for license. |
| 5 | * | 5 | * |
| 6 | * Implements thread registration, suspension, and stack | 6 | * Implements thread stack scanning. See <design/thread-manager/>. |
| 7 | * scanning. See <design/thread-manager/>. | ||
| 8 | * | 7 | * |
| 9 | * This supports the <code/th.h> | 8 | * This supports the <code/th.h> together with <code/thw3.c> |
| 10 | * | 9 | * |
| 11 | * .thread.id: The thread id is used to identify the current thread. | 10 | * .thread.id: The thread id is used to identify the current thread. |
| 12 | * .thread.handle: The thread handle needs the enough access to | ||
| 13 | * be able to suspend threads and to get their context. i.e. | ||
| 14 | * .thread.handle.susp-res: THREAD_SUSPEND_RESUME access | ||
| 15 | * .thread.handle.get-context: THREAD_GET_CONTEXT access | ||
| 16 | * An appropriate handle is created on registration. | ||
| 17 | * | 11 | * |
| 18 | * | 12 | * |
| 19 | * ASSUMPTIONS | 13 | * ASSUMPTIONS |
| 20 | * | 14 | * |
| 21 | * .error: some major errors are assumed not to happen. | 15 | * .error: some major errors are assumed not to happen. |
| 22 | * .error.close-handle: CloseHandle is assumed to succeed. | ||
| 23 | * | 16 | * |
| 24 | * Other errors are assumed to only happen in certain circumstances. | 17 | * Other errors are assumed to only happen in certain circumstances. |
| 25 | * .error.resume: ResumeThread is assumed to succeed unless the thread | ||
| 26 | * has been destroyed (in fact, perversely, it appears to succeeed even | ||
| 27 | * when the thread has been destroyed). | ||
| 28 | * .error.suspend: SuspendThread is assumed to succeed unless the thread | ||
| 29 | * has been destroyed. | ||
| 30 | * .error.get-context: GetThreadContext is assumed to succeed unless the | 18 | * .error.get-context: GetThreadContext is assumed to succeed unless the |
| 31 | * thread has been destroyed. | 19 | * thread has been destroyed. |
| 32 | * | 20 | * |
| @@ -53,13 +41,7 @@ | |||
| 53 | * .nt: uses Win32 specific stuff | 41 | * .nt: uses Win32 specific stuff |
| 54 | * HANDLE | 42 | * HANDLE |
| 55 | * DWORD | 43 | * DWORD |
| 56 | * GetCurrentProcess | ||
| 57 | * DuplicateHandle | ||
| 58 | * THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT | ||
| 59 | * GetCurrentThreadId | 44 | * GetCurrentThreadId |
| 60 | * CloseHandle | ||
| 61 | * SuspendThread | ||
| 62 | * ResumeThread | ||
| 63 | * CONTEXT | 45 | * CONTEXT |
| 64 | * CONTEXT_CONTROL | CONTEXT_INTEGER | 46 | * CONTEXT_CONTROL | CONTEXT_INTEGER |
| 65 | * GetThreadContext | 47 | * GetThreadContext |
| @@ -75,175 +57,16 @@ | |||
| 75 | #include "mpm.h" | 57 | #include "mpm.h" |
| 76 | 58 | ||
| 77 | #if !defined(MPS_OS_W3) || !defined(MPS_ARCH_I3) /* .i3 .nt */ | 59 | #if !defined(MPS_OS_W3) || !defined(MPS_ARCH_I3) /* .i3 .nt */ |
| 78 | #error "Compiling thnti3 when MPS_OS_W3 or MPS_ARCH_I3 not defined." | 60 | #error "Compiling thw3i3 when MPS_OS_W3 or MPS_ARCH_I3 not defined." |
| 79 | #endif | 61 | #endif |
| 80 | 62 | ||
| 63 | #include "thw3.h" | ||
| 64 | |||
| 81 | #include "mpswin.h" | 65 | #include "mpswin.h" |
| 82 | 66 | ||
| 83 | SRCID(thw3i3, "$Id$"); | 67 | SRCID(thw3i3, "$Id$"); |
| 84 | 68 | ||
| 85 | 69 | ||
| 86 | typedef struct ThreadStruct { /* Win32 thread structure */ | ||
| 87 | Sig sig; /* <design/sig/> */ | ||
| 88 | Serial serial; /* from arena->threadSerial */ | ||
| 89 | Arena arena; /* owning arena */ | ||
| 90 | RingStruct arenaRing; /* threads attached to arena */ | ||
| 91 | HANDLE handle; /* Handle of thread, see | ||
| 92 | * <code/thnti3.c#thread.handle> */ | ||
| 93 | DWORD id; /* Thread id of thread */ | ||
| 94 | } ThreadStruct; | ||
| 95 | |||
| 96 | |||
| 97 | Bool ThreadCheck(Thread thread) | ||
| 98 | { | ||
| 99 | CHECKS(Thread, thread); | ||
| 100 | CHECKU(Arena, thread->arena); | ||
| 101 | CHECKL(thread->serial < thread->arena->threadSerial); | ||
| 102 | CHECKL(RingCheck(&thread->arenaRing)); | ||
| 103 | return TRUE; | ||
| 104 | } | ||
| 105 | |||
| 106 | |||
| 107 | Bool ThreadCheckSimple(Thread thread) | ||
| 108 | { | ||
| 109 | CHECKS(Thread, thread); | ||
| 110 | return TRUE; | ||
| 111 | } | ||
| 112 | |||
| 113 | |||
| 114 | Res ThreadRegister(Thread *threadReturn, Arena arena) | ||
| 115 | { | ||
| 116 | Res res; | ||
| 117 | Thread thread; | ||
| 118 | HANDLE procHandle; | ||
| 119 | BOOL b; | ||
| 120 | void *p; | ||
| 121 | |||
| 122 | AVER(threadReturn != NULL); | ||
| 123 | AVERT(Arena, arena); | ||
| 124 | |||
| 125 | res = ControlAlloc(&p, arena, sizeof(ThreadStruct), | ||
| 126 | /* withReservoirPermit */ FALSE); | ||
| 127 | if(res != ResOK) | ||
| 128 | return res; | ||
| 129 | thread = (Thread)p; /* avoid pun */ | ||
| 130 | |||
| 131 | /* Duplicate handle gives us a new handle with updated privileges. | ||
| 132 | * .thread.handle describes the ones needed. | ||
| 133 | */ | ||
| 134 | procHandle = GetCurrentProcess(); | ||
| 135 | |||
| 136 | b = DuplicateHandle(procHandle, GetCurrentThread(), procHandle, | ||
| 137 | &thread->handle, | ||
| 138 | THREAD_SUSPEND_RESUME | THREAD_GET_CONTEXT, | ||
| 139 | FALSE, 0); | ||
| 140 | if(!b) | ||
| 141 | return ResRESOURCE; | ||
| 142 | |||
| 143 | thread->id = GetCurrentThreadId(); | ||
| 144 | |||
| 145 | RingInit(&thread->arenaRing); | ||
| 146 | |||
| 147 | thread->sig = ThreadSig; | ||
| 148 | thread->serial = arena->threadSerial; | ||
| 149 | ++arena->threadSerial; | ||
| 150 | thread->arena = arena; | ||
| 151 | |||
| 152 | AVERT(Thread, thread); | ||
| 153 | |||
| 154 | RingAppend(ArenaThreadRing(arena), &thread->arenaRing); | ||
| 155 | |||
| 156 | *threadReturn = thread; | ||
| 157 | return ResOK; | ||
| 158 | } | ||
| 159 | |||
| 160 | void ThreadDeregister(Thread thread, Arena arena) | ||
| 161 | { | ||
| 162 | Bool b; | ||
| 163 | |||
| 164 | AVERT(Thread, thread); | ||
| 165 | AVERT(Arena, arena); | ||
| 166 | |||
| 167 | RingRemove(&thread->arenaRing); | ||
| 168 | |||
| 169 | thread->sig = SigInvalid; | ||
| 170 | |||
| 171 | RingFinish(&thread->arenaRing); | ||
| 172 | |||
| 173 | b = CloseHandle(thread->handle); | ||
| 174 | AVER(b); /* .error.close-handle */ | ||
| 175 | |||
| 176 | ControlFree(arena, thread, sizeof(ThreadStruct)); | ||
| 177 | } | ||
| 178 | |||
| 179 | |||
| 180 | /* Map over threads on ring calling f on each one except the | ||
| 181 | * current thread. | ||
| 182 | */ | ||
| 183 | static void mapThreadRing(Ring ring, void (*f)(Thread thread)) | ||
| 184 | { | ||
| 185 | Ring node; | ||
| 186 | DWORD id; | ||
| 187 | |||
| 188 | id = GetCurrentThreadId(); | ||
| 189 | node = RingNext(ring); | ||
| 190 | while(node != ring) { | ||
| 191 | Ring next = RingNext(node); | ||
| 192 | Thread thread; | ||
| 193 | |||
| 194 | thread = RING_ELT(Thread, arenaRing, node); | ||
| 195 | AVERT(Thread, thread); | ||
| 196 | if(id != thread->id) /* .thread.id */ | ||
| 197 | (*f)(thread); | ||
| 198 | |||
| 199 | node = next; | ||
| 200 | } | ||
| 201 | } | ||
| 202 | |||
| 203 | static void suspend(Thread thread) | ||
| 204 | { | ||
| 205 | /* .thread.handle.susp-res */ | ||
| 206 | /* .error.suspend */ | ||
| 207 | /* In the error case (SuspendThread returning 0xFFFFFFFF), we */ | ||
| 208 | /* assume the thread has been destroyed (as part of process shutdown). */ | ||
| 209 | /* In which case we simply continue. */ | ||
| 210 | /* [GetLastError appears to return 5 when SuspendThread is called */ | ||
| 211 | /* on a destroyed thread, but I'm not sufficiently confident of this */ | ||
| 212 | /* to check -- drj 1998-04-09] */ | ||
| 213 | (void)SuspendThread(thread->handle); | ||
| 214 | } | ||
| 215 | |||
| 216 | void ThreadRingSuspend(Ring ring) | ||
| 217 | { | ||
| 218 | mapThreadRing(ring, suspend); | ||
| 219 | } | ||
| 220 | |||
| 221 | static void resume(Thread thread) | ||
| 222 | { | ||
| 223 | /* .thread.handle.susp-res */ | ||
| 224 | /* .error.resume */ | ||
| 225 | /* In the error case (ResumeThread returning 0xFFFFFFFF), we */ | ||
| 226 | /* assume the thread has been destroyed (as part of process shutdown). */ | ||
| 227 | /* In which case we simply continue. */ | ||
| 228 | (void)ResumeThread(thread->handle); | ||
| 229 | } | ||
| 230 | |||
| 231 | void ThreadRingResume(Ring ring) | ||
| 232 | { | ||
| 233 | mapThreadRing(ring, resume); | ||
| 234 | } | ||
| 235 | |||
| 236 | |||
| 237 | Thread ThreadRingThread(Ring threadRing) | ||
| 238 | { | ||
| 239 | Thread thread; | ||
| 240 | AVERT(Ring, threadRing); | ||
| 241 | thread = RING_ELT(Thread, arenaRing, threadRing); | ||
| 242 | AVERT(Thread, thread); | ||
| 243 | return thread; | ||
| 244 | } | ||
| 245 | |||
| 246 | |||
| 247 | Res ThreadScan(ScanState ss, Thread thread, void *stackBot) | 70 | Res ThreadScan(ScanState ss, Thread thread, void *stackBot) |
| 248 | { | 71 | { |
| 249 | DWORD id; | 72 | DWORD id; |
| @@ -303,33 +126,6 @@ Res ThreadScan(ScanState ss, Thread thread, void *stackBot) | |||
| 303 | return ResOK; | 126 | return ResOK; |
| 304 | } | 127 | } |
| 305 | 128 | ||
| 306 | /* Must be thread-safe. See <design/interface-c/#thread-safety>. */ | ||
| 307 | Arena ThreadArena(Thread thread) | ||
| 308 | { | ||
| 309 | /* Can't AVER thread as that would not be thread-safe */ | ||
| 310 | /* AVERT(Thread, thread); */ | ||
| 311 | return thread->arena; | ||
| 312 | } | ||
| 313 | |||
| 314 | Res ThreadDescribe(Thread thread, mps_lib_FILE *stream) | ||
| 315 | { | ||
| 316 | Res res; | ||
| 317 | |||
| 318 | res = WriteF(stream, | ||
| 319 | "Thread $P ($U) {\n", (WriteFP)thread, (WriteFU)thread->serial, | ||
| 320 | " arena $P ($U)\n", | ||
| 321 | (WriteFP)thread->arena, (WriteFU)thread->arena->serial, | ||
| 322 | " handle $W\n", (WriteFW)thread->handle, | ||
| 323 | " id $U\n", (WriteFU)thread->id, | ||
| 324 | "} Thread $P ($U)\n", (WriteFP)thread, (WriteFU)thread->serial, | ||
| 325 | NULL); | ||
| 326 | if(res != ResOK) | ||
| 327 | return res; | ||
| 328 | |||
| 329 | return ResOK; | ||
| 330 | } | ||
| 331 | |||
| 332 | |||
| 333 | /* C. COPYRIGHT AND LICENSE | 129 | /* C. COPYRIGHT AND LICENSE |
| 334 | * | 130 | * |
| 335 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. | 131 | * Copyright (C) 2001-2002 Ravenbrook Limited <http://www.ravenbrook.com/>. |
diff --git a/mps/code/w3i3mv.nmk b/mps/code/w3i3mv.nmk index 6a670938165..93ef97984f9 100644 --- a/mps/code/w3i3mv.nmk +++ b/mps/code/w3i3mv.nmk | |||
| @@ -20,7 +20,7 @@ MPM = <ring> <mpm> <bt> <protocol> <boot> \ | |||
| 20 | <root> <format> <buffer> <walk> <lockw3> \ | 20 | <root> <format> <buffer> <walk> <lockw3> \ |
| 21 | <ref> <trace> <traceanc> <protw3> <proti3> <prmci3w3> \ | 21 | <ref> <trace> <traceanc> <protw3> <proti3> <prmci3w3> \ |
| 22 | <shield> <vmw3> \ | 22 | <shield> <vmw3> \ |
| 23 | <thw3i3> <ssw3i3> <mpsi> <mpsiw3> <ld> <spi3> \ | 23 | <thw3> <thw3i3> <ssw3i3> <mpsi> <mpsiw3> <ld> <spi3> \ |
| 24 | <event> <seg> <sac> <poolmrg> <message> <dbgpool> <dbgpooli> \ | 24 | <event> <seg> <sac> <poolmrg> <message> <dbgpool> <dbgpooli> \ |
| 25 | <abq> <meter> <cbs> <poolmv2> <splay> <diag> <version> | 25 | <abq> <meter> <cbs> <poolmv2> <splay> <diag> <version> |
| 26 | SW = <ring> <mpm> <bt> <protocol> <boot> \ | 26 | SW = <ring> <mpm> <bt> <protocol> <boot> \ |
| @@ -29,7 +29,7 @@ SW = <ring> <mpm> <bt> <protocol> <boot> \ | |||
| 29 | <root> <format> <buffer> <walk> \ | 29 | <root> <format> <buffer> <walk> \ |
| 30 | <ref> <trace> <traceanc> <protsw> <prmcan> \ | 30 | <ref> <trace> <traceanc> <protsw> <prmcan> \ |
| 31 | <shield> <vmw3> \ | 31 | <shield> <vmw3> \ |
| 32 | <thw3i3> <ssan> <mpsi> <ld> \ | 32 | <thw3> <thw3i3> <ssan> <mpsi> <ld> \ |
| 33 | <event> <seg> <sac> <poolmrg> <message> <mpsioan> \ | 33 | <event> <seg> <sac> <poolmrg> <message> <mpsioan> \ |
| 34 | <poolams> <poolamsi> <dbgpool> <dbgpooli> \ | 34 | <poolams> <poolamsi> <dbgpool> <dbgpooli> \ |
| 35 | <abq> <meter> <cbs> <poolmv2> <splay> <diag> <version> <poolmvff> | 35 | <abq> <meter> <cbs> <poolmv2> <splay> <diag> <version> <poolmvff> |