|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24: /*
25: * Test of NXLock, NXConditionLock, and NXSpinLock (kernel version).
26: */
27:
28: /*
29: * Operations (performed sequentially per msg_id passed to server)
30: */
31: #define NXL_LIB_INIT 1 // call IOInitGeneralFuncs()
32: #define NXL_OBJ_ALLOC 2 // alloc an Object
33: #define NXL_OBJ_INIT 3 // init an Object
34: #define NXL_LOCK_INIT 5 // alloc and init all 3 locks
35: #define NXL_THREAD 6 // start up ioThread
36: #define NXL_PART1 7 // part 1 - NXSpinLock test
37: #define NXL_PART2 8 // part 2 - NXLock test
38: #define NXL_PART3 9 // part 2 - NXConditionLock test
39:
40: /*
41: * Kernel can't do spin lock tests on a single CPU.
42: */
43: #define DO_SPINLOCK 0
44:
45: #define KERNEL 1
46: #define KERNEL_PRIVATE 1 // pick up kernel private files
47:
48: #import <machkit/NXLock.h>
49: #import <driverkit/generalFuncs.h>
50: #import <kernserv/kern_server_types.h>
51: #import <mach/message.h>
52:
53: static int do_NXLockTest(int opcode);
54: static int ioThread(void *param);
55:
56: kern_server_t NXLock_ks_var;
57: id nxLock;
58: id nxCondLock;
59: id nxSpinLock;
60: int libInitFlag = 1;
61:
62: /*
63: * flags mean "I'm waiting for you" when true.
64: */
65: boolean_t threadFlag;
66: boolean_t mainFlag;
67:
68: /*
69: * kernserv callout functions.
70: */
71: void locktest_announce(int unit);
72: void locktest_port_gone(port_name_t port);
73: void locktest_terminate(int unit);
74: void locktest_server(msg_header_t *in_p, int unit);
75:
76: /*
77: * we're just placed into memory here.
78: */
79: void locktest_announce(int unit)
80: {
81: IOLog("NXLockTest Loaded\n", unit);
82: }
83:
84: void locktest_port_gone(port_name_t port)
85: {
86: IOLog("NXLockTest port death\n");
87:
88: }
89:
90: void locktest_terminate(int unit)
91: {
92: IOLog("NXLockTest Unloaded\n");
93: }
94:
95: /*
96: * This is invoked upon receipt of any message. (Use the smsg utility to
97: * send an empty message here.)
98: */
99: void locktest_server(msg_header_t *in_p, int unit)
100: {
101: int opcode = in_p->msg_id;
102: id foo;
103:
104: IOLog("NXLockTest: Starting\n");
105:
106: #ifdef TEST_IN_KERNEL
107: doNXLockTest(opcode);
108: goto done;
109: #endif TEST_IN_KERNEL
110:
111: /*
112: * First initialize the libraries we'll use. There's no shutdown
113: * needed later (or is there...?).
114: */
115: if(opcode < NXL_LIB_INIT)
116: goto done;
117: if(!libInitFlag) {
118: IOInitGeneralFuncs();
119: libInitFlag = 1;
120: }
121: IOLog("IOInitGeneralFunc called\n");
122:
123: /*
124: * Just to try out objc run time, alloc and init an Object.
125: */
126: if(opcode < NXL_OBJ_ALLOC)
127: goto done;
128: foo = [Object alloc];
129: if(opcode < NXL_OBJ_INIT)
130: goto done;
131: IOLog("Object alloc'd\n");
132: [foo init];
133: IOLog("Object init'd\n");
134:
135: do_NXLockTest(opcode);
136:
137: /*
138: * return message to loader.
139: */
140: done:
141: msg_send(in_p,
142: MSG_OPTION_NONE,
143: 0);
144: } /* locktest_server() */
145:
146: /*
147: * Call to avoid spinning.
148: */
149: static void yield()
150: {
151: IOSleep(10);
152: }
153:
154: /*
155: * Actual NXLock test. do_NXLockTest runs from our msg_receive thread in
156: * kernserv. This thread forks off ioThread() and the two perform the
157: * following:
158: *
159: * part main ioThread
160: * 1 mainFlag FALSE threadFlag FALSE
161: * grab spin lock wait for mainFlag
162: * mainFlag TRUE
163: * wait for threadFlag
164: * threadFlag TRUE
165: * try to acquire spinLock (held by main)
166: * mainFlag FALSE
167: * sleep
168: * unlock spin lock
169: * wait for threadFlag FALSE
170: * unlock spinLock
171: * threadFlag FALSE
172: *
173: * 2 grab nxLock wait for mainFlag
174: * mainFlag TRUE
175: * wait for threadFlag
176: * threadFlag TRUE
177: * try to acquire nxLock (held by main)
178: * mainFlag FALSE
179: * sleep
180: * unlock nxLock
181: * wait for threadFlag FALSE
182: * unlock spinLock
183: * threadFlag FALSE
184: *
185: * 3 grab nxCondLock wait for mainFlag
186: * mainFlag TRUE
187: * wait for threadFlag
188: * threadFlag TRUE
189: * [condLock lockWhen 1]
190: * mainFlag FALSE
191: * sleep
192: * [condLock unlockWith 1]
193: * [condLock lockWhen 2]
194: * sleep
195: * [condLock unlockWith 2]
196: * done done
197: */
198:
199: static int do_NXLockTest(int opcode)
200: {
201: if(opcode < NXL_LOCK_INIT)
202: return 0;
203:
204: /*
205: * Init the three locks.
206: */
207: nxLock = [NXLock new];
208: IOLog("NXLock new'd\n");
209: nxCondLock = [NXConditionLock alloc];
210: [nxCondLock initWith:0];
211: IOLog("NXCondLock initWith:'d\n");
212: nxSpinLock = [NXSpinLock new];
213: IOLog("NXSpinLock new'd\n");
214:
215: if(opcode < NXL_THREAD)
216: return 0;
217:
218: /*
219: * Start up the I/O thread.
220: */
221: IOForkThread((IOThreadFunc)ioThread, (void *)opcode);
222: IOLog("ioThread forked\n");
223: if(opcode < NXL_PART1)
224: return 0;
225:
226: /*
227: * Part 1.
228: */
229: #if DO_SPINLOCK
230: [nxSpinLock lock];
231: mainFlag = TRUE;
232: while(!threadFlag) {
233: yield();
234: }
235:
236: mainFlag = FALSE;
237: IOLog("1 (main) - threadFlag true, main() holds spin lock\n");
238: IOSleep(1);
239: [nxSpinLock unlock];
240:
241: /*
242: * Wait for I/O Thread to finish part 1.
243: */
244: while(threadFlag) {
245: yield();
246: }
247: #endif DO_SPINLOCK
248:
249: if(opcode < NXL_PART2)
250: return 0;
251:
252: /*
253: * Part 2.
254: */
255: [nxLock lock];
256: mainFlag = TRUE;
257: while(!threadFlag) {
258: yield();
259: }
260: mainFlag = FALSE;
261: IOLog("2 (main) - threadFlag true, main() holds nxLock\n");
262: IOSleep(1);
263: [nxLock unlock];
264:
265: /*
266: * Wait for I/O Thread to finish part 2.
267: */
268: while(threadFlag) {
269: yield();
270: }
271:
272: if(opcode < NXL_PART3)
273: return 0;
274:
275: /*
276: * Part 3.
277: */
278: [nxCondLock lock];
279: mainFlag = TRUE;
280: while(!threadFlag) {
281: yield();
282: }
283: IOLog("3 (main) - threadFlag true, main() holds condLock\n");
284: IOSleep(1);
285: [nxCondLock unlockWith:1];
286: [nxCondLock lockWhen:2];
287: IOLog("3 (main) - got condLock:2; done\n");
288:
289: /*
290: * Free the locks.
291: */
292: [nxLock free];
293: [nxCondLock free];
294: [nxSpinLock free];
295: return(0);
296: }
297:
298: static int ioThread(void *param)
299: {
300: int opcode = (int)param;
301:
302: if(opcode < NXL_PART1)
303: goto done;
304:
305: /*
306: * part 1.
307: */
308: #if DO_SPINLOCK
309: while(!mainFlag)
310: ;
311: threadFlag = TRUE;
312: [nxSpinLock lock];
313: IOLog("1 (thread) - thread got spinLock\n");
314: [nxSpinLock unlock];
315: threadFlag = FALSE;
316: #endif DO_SPINLOCK
317:
318: if(opcode < NXL_PART2)
319: goto done;
320:
321: /*
322: * part 2.
323: */
324: while(!mainFlag) {
325: yield();
326: }
327: threadFlag = TRUE;
328: [nxLock lock];
329: IOLog("2 (thread) - thread got nxLock\n");
330: [nxLock unlock];
331: threadFlag = FALSE;
332:
333: if(opcode < NXL_PART3)
334: goto done;
335:
336: /*
337: * Part 3.
338: */
339: while(!mainFlag) {
340: yield();
341: }
342: threadFlag = TRUE;
343: [nxCondLock lockWhen:1];
344: IOLog("3 (thread) - got condLock:1\n");
345: IOSleep(1);
346: [nxCondLock unlockWith:2];
347:
348: /*
349: * Done, kill this thread.
350: */
351: done:
352: IOExitThread();
353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.