aboutsummaryrefslogtreecommitdiffstats
path: root/mps/code
diff options
context:
space:
mode:
authorDavid Lovemore2012-05-22 16:08:49 +0100
committerDavid Lovemore2012-05-22 16:08:49 +0100
commit4c8144b692d2846b7826928b0fa5997d1de9a1f1 (patch)
treebe9ac769e7e3b607fbae810036a3414fbace426e /mps/code
parentb9dbf430ef23dec78732f9e050b5430b0707069d (diff)
downloademacs-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.c273
-rw-r--r--mps/code/thw3.h70
-rw-r--r--mps/code/thw3i3.c216
-rw-r--r--mps/code/w3i3mv.nmk4
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
55SRCID(thw3, "$Id$");
56
57
58Bool 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
68Bool ThreadCheckSimple(Thread thread)
69{
70 CHECKS(Thread, thread);
71 return TRUE;
72}
73
74
75Res 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
121void 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 */
144static 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
164static 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
177void ThreadRingSuspend(Ring ring)
178{
179 mapThreadRing(ring, suspend);
180}
181
182static 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
192void ThreadRingResume(Ring ring)
193{
194 mapThreadRing(ring, resume);
195}
196
197
198Thread 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>. */
208Arena 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
215Res 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
21typedef 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
83SRCID(thw3i3, "$Id$"); 67SRCID(thw3i3, "$Id$");
84 68
85 69
86typedef 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
97Bool 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
107Bool ThreadCheckSimple(Thread thread)
108{
109 CHECKS(Thread, thread);
110 return TRUE;
111}
112
113
114Res 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
160void 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 */
183static 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
203static 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
216void ThreadRingSuspend(Ring ring)
217{
218 mapThreadRing(ring, suspend);
219}
220
221static 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
231void ThreadRingResume(Ring ring)
232{
233 mapThreadRing(ring, resume);
234}
235
236
237Thread 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
247Res ThreadScan(ScanState ss, Thread thread, void *stackBot) 70Res 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>. */
307Arena 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
314Res 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>
26SW = <ring> <mpm> <bt> <protocol> <boot> \ 26SW = <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>