|
|
1.1 root 1: /*
2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * The contents of this file constitute Original Code as defined in and
7: * are subject to the Apple Public Source License Version 1.1 (the
8: * "License"). You may not use this file except in compliance with the
9: * License. Please obtain a copy of the License at
10: * http://www.apple.com/publicsource and read it before using this file.
11: *
12: * This Original Code and all software distributed under the License are
13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17: * License for the specific language governing rights and limitations
18: * under the License.
19: *
20: * @APPLE_LICENSE_HEADER_END@
21: */
22: /*
23: * @OSF_COPYRIGHT@
24: */
25: /*
26: * Mach Operating System
27: * Copyright (c) 1989 Carnegie-Mellon University
28: * All rights reserved. The CMU software License Agreement specifies
29: * the terms and conditions for use and redistribution.
30: */
31:
32: #include <cpus.h>
33: #include <mach_rt.h>
34: #include <platforms.h>
35: #include <mach_ldebug.h>
36: #include <i386/asm.h>
37: #include <assym.s>
38: #include <kern/etap_options.h>
39:
40:
41: /*
42: * When performance isn't the only concern, it's
43: * nice to build stack frames...
44: */
45: #define BUILD_STACK_FRAMES ((MACH_LDEBUG || ETAP_LOCK_TRACE) && MACH_KDB)
46:
47: #if BUILD_STACK_FRAMES
48:
49: #define L_PC 4(%ebp)
50: #define L_ARG0 8(%ebp)
51: #define L_ARG1 12(%ebp)
52:
53: #define SWT_HI -4(%ebp)
54: #define SWT_LO -8(%ebp)
55: #define MISSED -12(%ebp)
56:
57: #else /* BUILD_STACK_FRAMES */
58:
59: #undef FRAME
60: #undef EMARF
61: #define FRAME
62: #define EMARF
63: #define L_PC (%esp)
64: #define L_ARG0 4(%esp)
65: #define L_ARG1 8(%esp)
66:
67: #endif /* BUILD_STACK_FRAMES */
68:
69:
70: #define M_ILK (%edx)
71: #define M_LOCKED 1(%edx)
72: #define M_WAITERS 2(%edx)
73: #if MACH_LDEBUG
74: #define M_TYPE 4(%edx)
75: #define M_PC 8(%edx)
76: #define M_THREAD 12(%edx)
77: #endif /* MACH_LDEBUG */
78:
79: #include <i386/AT386/mp/mp.h>
80: #if (NCPUS > 1)
81: #define CX(addr,reg) addr(,reg,4)
82: #else
83: #define CPU_NUMBER(reg)
84: #define CX(addr,reg) addr
85: #endif /* (NCPUS > 1) */
86:
87: #if MACH_LDEBUG
88: /*
89: * Routines for general lock debugging.
90: */
91: #define S_TYPE 4(%edx)
92: #define S_PC 8(%edx)
93: #define S_THREAD 12(%edx)
94: #define S_DURATIONH 16(%edx)
95: #define S_DURATIONL 20(%edx)
96:
97: /*
98: * Checks for expected lock types and calls "panic" on
99: * mismatch. Detects calls to Mutex functions with
100: * type simplelock and vice versa.
101: */
102: #define CHECK_MUTEX_TYPE() \
103: cmpl $MUTEX_TAG, M_TYPE ; \
104: je 1f ; \
105: pushl $2f ; \
106: call EXT(panic) ; \
107: hlt ; \
108: .data ; \
109: 2: String "not a mutex!" ; \
110: .text ; \
111: 1:
112:
113: #define CHECK_SIMPLE_LOCK_TYPE() \
114: cmpl $SIMPLE_LOCK_TAG,S_TYPE ; \
115: je 1f ; \
116: pushl $2f ; \
117: call EXT(panic) ; \
118: hlt ; \
119: .data ; \
120: 2: String "not a simple lock!" ; \
121: .text ; \
122: 1:
123:
124: /*
125: * If one or more simplelocks are currently held by a thread,
126: * an attempt to acquire a mutex will cause this check to fail
127: * (since a mutex lock may context switch, holding a simplelock
128: * is not a good thing).
129: */
130: #if 0 /*MACH_RT - 11/12/99 - [email protected] disable check for now*/
131: #define CHECK_PREEMPTION_LEVEL() \
132: movl $CPD_PREEMPTION_LEVEL,%eax ; \
133: cmpl $0,%gs:(%eax) ; \
134: je 1f ; \
135: pushl $2f ; \
136: call EXT(panic) ; \
137: hlt ; \
138: .data ; \
139: 2: String "preemption_level != 0!" ; \
140: .text ; \
141: 1:
142: #else /* MACH_RT */
143: #define CHECK_PREEMPTION_LEVEL()
144: #endif /* MACH_RT */
145:
146: #define CHECK_NO_SIMPLELOCKS() \
147: movl $CPD_SIMPLE_LOCK_COUNT,%eax ; \
148: cmpl $0,%gs:(%eax) ; \
149: je 1f ; \
150: pushl $2f ; \
151: call EXT(panic) ; \
152: hlt ; \
153: .data ; \
154: 2: String "simple_locks_held!" ; \
155: .text ; \
156: 1:
157:
158: /*
159: * Verifies return to the correct thread in "unlock" situations.
160: */
161: #define CHECK_THREAD(thd) \
162: movl $CPD_ACTIVE_THREAD,%eax ; \
163: movl %gs:(%eax),%ecx ; \
164: testl %ecx,%ecx ; \
165: je 1f ; \
166: cmpl %ecx,thd ; \
167: je 1f ; \
168: pushl $2f ; \
169: call EXT(panic) ; \
170: hlt ; \
171: .data ; \
172: 2: String "wrong thread!" ; \
173: .text ; \
174: 1:
175:
176: #define CHECK_MYLOCK(thd) \
177: movl $CPD_ACTIVE_THREAD,%eax ; \
178: movl %gs:(%eax),%ecx ; \
179: testl %ecx,%ecx ; \
180: je 1f ; \
181: cmpl %ecx,thd ; \
182: jne 1f ; \
183: pushl $2f ; \
184: call EXT(panic) ; \
185: hlt ; \
186: .data ; \
187: 2: String "mylock attempt!" ; \
188: .text ; \
189: 1:
190:
191: #define METER_SIMPLE_LOCK_LOCK(reg) \
192: pushl reg ; \
193: call EXT(meter_simple_lock) ; \
194: popl reg
195:
196: #define METER_SIMPLE_LOCK_UNLOCK(reg) \
197: pushl reg ; \
198: call EXT(meter_simple_unlock) ; \
199: popl reg
200:
201: #else /* MACH_LDEBUG */
202: #define CHECK_MUTEX_TYPE()
203: #define CHECK_SIMPLE_LOCK_TYPE
204: #define CHECK_THREAD(thd)
205: #define CHECK_PREEMPTION_LEVEL()
206: #define CHECK_NO_SIMPLELOCKS()
207: #define CHECK_MYLOCK(thd)
208: #define METER_SIMPLE_LOCK_LOCK(reg)
209: #define METER_SIMPLE_LOCK_UNLOCK(reg)
210: #endif /* MACH_LDEBUG */
211:
212:
213: /*
214: * void hw_lock_init(hw_lock_t)
215: *
216: * Initialize a hardware lock.
217: */
218: ENTRY(hw_lock_init)
219: FRAME
220: movl L_ARG0,%edx /* fetch lock pointer */
221: xorl %eax,%eax
222: movb %al,0(%edx) /* clear the lock */
223: EMARF
224: ret
225:
226: /*
227: * void hw_lock_lock(hw_lock_t)
228: *
229: * Acquire lock, spinning until it becomes available.
230: * MACH_RT: also return with preemption disabled.
231: */
232: ENTRY(hw_lock_lock)
233: FRAME
234: movl L_ARG0,%edx /* fetch lock pointer */
235:
236: 1: DISABLE_PREEMPTION(%eax)
237: movb $1,%cl
238: xchgb 0(%edx),%cl /* try to acquire the HW lock */
239: testb %cl,%cl /* success? */
240: jne 3f
241:
242: EMARF /* if yes, then nothing left to do */
243: ret
244:
245: 3: ENABLE_PREEMPTION(%eax) /* no reason we can't be preemptable now */
246:
247: movb $1,%cl
248: 2: testb %cl,0(%edx) /* spin checking lock value in cache */
249: jne 2b /* non-zero means locked, keep spinning */
250: jmp 1b /* zero means unlocked, try to grab it */
251:
252: /*
253: * void hw_lock_unlock(hw_lock_t)
254: *
255: * Unconditionally release lock.
256: * MACH_RT: release preemption level.
257: */
258: ENTRY(hw_lock_unlock)
259: FRAME
260: movl L_ARG0,%edx /* fetch lock pointer */
261: xorl %eax,%eax
262: xchgb 0(%edx),%al /* clear the lock... a mov instruction */
263: /* ...might be cheaper and less paranoid */
264: ENABLE_PREEMPTION(%eax)
265: EMARF
266: ret
267:
268: /*
269: * unsigned int hw_lock_try(hw_lock_t)
270: * MACH_RT: returns with preemption disabled on success.
271: */
272: ENTRY(hw_lock_try)
273: FRAME
274: movl L_ARG0,%edx /* fetch lock pointer */
275:
276: DISABLE_PREEMPTION(%eax)
277: movb $1,%cl
278: xchgb 0(%edx),%cl /* try to acquire the HW lock */
279: testb %cl,%cl /* success? */
280: jne 1f /* if yes, let the caller know */
281:
282: movl $1,%eax /* success */
283: EMARF
284: ret
285:
286: 1: ENABLE_PREEMPTION(%eax) /* failure: release preemption... */
287: xorl %eax,%eax /* ...and return failure */
288: EMARF
289: ret
290:
291: /*
292: * unsigned int hw_lock_held(hw_lock_t)
293: * MACH_RT: doesn't change preemption state.
294: * N.B. Racy, of course.
295: */
296: ENTRY(hw_lock_held)
297: FRAME
298: movl L_ARG0,%edx /* fetch lock pointer */
299:
300: movb $1,%cl
301: testb %cl,0(%edx) /* check lock value */
302: jne 1f /* non-zero means locked */
303: xorl %eax,%eax /* tell caller: lock wasn't locked */
304: EMARF
305: ret
306:
307: 1: movl $1,%eax /* tell caller: lock was locked */
308: EMARF
309: ret
310:
311:
312:
313: #if 0
314:
315:
316: ENTRY(_usimple_lock_init)
317: FRAME
318: movl L_ARG0,%edx /* fetch lock pointer */
319: xorl %eax,%eax
320: movb %al,USL_INTERLOCK(%edx) /* unlock the HW lock */
321: EMARF
322: ret
323:
324: ENTRY(_simple_lock)
325: FRAME
326: movl L_ARG0,%edx /* fetch lock pointer */
327:
328: CHECK_SIMPLE_LOCK_TYPE()
329:
330: DISABLE_PREEMPTION(%eax)
331:
332: sl_get_hw:
333: movb $1,%cl
334: xchgb USL_INTERLOCK(%edx),%cl /* try to acquire the HW lock */
335: testb %cl,%cl /* did we succeed? */
336:
337: #if MACH_LDEBUG
338: je 5f
339: CHECK_MYLOCK(S_THREAD)
340: jmp sl_get_hw
341: 5:
342: #else /* MACH_LDEBUG */
343: jne sl_get_hw /* no, try again */
344: #endif /* MACH_LDEBUG */
345:
346: #if MACH_LDEBUG
347: movl L_PC,%ecx
348: movl %ecx,S_PC
349: movl $CPD_ACTIVE_THREAD,%eax
350: movl %gs:(%eax),%ecx
351: movl %ecx,S_THREAD
352: incl CX(EXT(simple_lock_count),%eax)
353: #if 0
354: METER_SIMPLE_LOCK_LOCK(%edx)
355: #endif
356: #if NCPUS == 1
357: pushf
358: pushl %edx
359: cli
360: call EXT(lock_stack_push)
361: popl %edx
362: popfl
363: #endif /* NCPUS == 1 */
364: #endif /* MACH_LDEBUG */
365:
366: EMARF
367: ret
368:
369: ENTRY(_simple_lock_try)
370: FRAME
371: movl L_ARG0,%edx /* fetch lock pointer */
372:
373: CHECK_SIMPLE_LOCK_TYPE()
374:
375: DISABLE_PREEMPTION(%eax)
376:
377: movb $1,%cl
378: xchgb USL_INTERLOCK(%edx),%cl /* try to acquire the HW lock */
379: testb %cl,%cl /* did we succeed? */
380: jne 1f /* no, return failure */
381:
382: #if MACH_LDEBUG
383: movl L_PC,%ecx
384: movl %ecx,S_PC
385: movl $CPD_ACTIVE_THREAD,%eax
386: movl %gs:(%eax),%ecx
387: movl %ecx,S_THREAD
388: incl CX(EXT(simple_lock_count),%eax)
389: #if 0
390: METER_SIMPLE_LOCK_LOCK(%edx)
391: #endif
392: #if NCPUS == 1
393: pushf
394: pushl %edx
395: cli
396: call EXT(lock_stack_push)
397: popl %edx
398: popfl
399: #endif /* NCPUS == 1 */
400: #endif /* MACH_LDEBUG */
401:
402: movl $1,%eax /* return success */
403:
404: EMARF
405: ret
406:
407: 1:
408: ENABLE_PREEMPTION(%eax)
409:
410: xorl %eax,%eax /* and return failure */
411:
412: EMARF
413: ret
414:
415: ENTRY(_simple_unlock)
416: FRAME
417: movl L_ARG0,%edx /* fetch lock pointer */
418:
419: CHECK_SIMPLE_LOCK_TYPE()
420: CHECK_THREAD(S_THREAD)
421:
422: #if MACH_LDEBUG
423: xorl %eax,%eax
424: movl %eax,S_THREAD /* disown thread */
425: MP_DISABLE_PREEMPTION(%eax)
426: CPU_NUMBER(%eax)
427: decl CX(EXT(simple_lock_count),%eax)
428: MP_ENABLE_PREEMPTION(%eax)
429: #if 0
430: METER_SIMPLE_LOCK_UNLOCK(%edx)
431: #endif
432: #if NCPUS == 1
433: pushf
434: pushl %edx
435: cli
436: call EXT(lock_stack_pop)
437: popl %edx
438: popfl
439: #endif /* NCPUS == 1 */
440: #endif /* MACH_LDEBUG */
441:
442: xorb %cl,%cl
443: xchgb USL_INTERLOCK(%edx),%cl /* unlock the HW lock */
444:
445: ENABLE_PREEMPTION(%eax)
446:
447: EMARF
448: ret
449:
450: #endif /* 0 */
451:
452:
453: ENTRY(mutex_init)
454: FRAME
455: movl L_ARG0,%edx /* fetch lock pointer */
456: xorl %eax,%eax
457: movb %al,M_ILK /* clear interlock */
458: movb %al,M_LOCKED /* clear locked flag */
459: movw %ax,M_WAITERS /* init waiter count */
460:
461: #if MACH_LDEBUG
462: movl $MUTEX_TAG,M_TYPE /* set lock type */
463: movl %eax,M_PC /* init caller pc */
464: movl %eax,M_THREAD /* and owning thread */
465: #endif
466: #if ETAP_LOCK_TRACE
467: movl L_ARG1,%ecx /* fetch event type */
468: pushl %ecx /* push event type */
469: pushl %edx /* push mutex address */
470: call EXT(etap_mutex_init) /* init ETAP data */
471: addl $8,%esp
472: #endif /* ETAP_LOCK_TRACE */
473:
474: EMARF
475: ret
476:
477: ENTRY(_mutex_lock)
478: FRAME
479:
480: #if ETAP_LOCK_TRACE
481: subl $12,%esp /* make room for locals */
482: movl $0,SWT_HI /* set wait time to zero (HI) */
483: movl $0,SWT_LO /* set wait time to zero (LO) */
484: movl $0,MISSED /* clear local miss marker */
485: #endif /* ETAP_LOCK_TRACE */
486:
487: movl L_ARG0,%edx /* fetch lock pointer */
488:
489: CHECK_MUTEX_TYPE()
490: CHECK_NO_SIMPLELOCKS()
491: CHECK_PREEMPTION_LEVEL()
492:
493: ml_retry:
494: DISABLE_PREEMPTION(%eax)
495:
496: ml_get_hw:
497: movb $1,%cl
498: xchgb %cl,M_ILK
499: testb %cl,%cl /* did we succeed? */
500: jne ml_get_hw /* no, try again */
501:
502: /*
503: / Beware of a race between this code path and the inline ASM fast-path locking
504: / sequence which attempts to lock a mutex by directly setting the locked flag
505: /
506: */
507:
508: movb $1,%cl
509: xchgb %cl,M_LOCKED /* try to set locked flag */
510: testb %cl,%cl /* is the mutex locked? */
511: jne ml_fail /* yes, we lose */
512:
513: #if MACH_LDEBUG
514: movl L_PC,%ecx
515: movl %ecx,M_PC
516: movl $CPD_ACTIVE_THREAD,%eax
517: movl %gs:(%eax),%ecx
518: movl %ecx,M_THREAD
519: testl %ecx,%ecx
520: je 3f
521: incl TH_MUTEX_COUNT(%ecx)
522: 3:
523: #endif
524:
525: xorb %cl,%cl
526: xchgb %cl,M_ILK
527:
528: ENABLE_PREEMPTION(%eax)
529:
530: #if ETAP_LOCK_TRACE
531: movl L_PC,%eax /* fetch pc */
532: pushl SWT_LO /* push wait time (low) */
533: pushl SWT_HI /* push wait time (high) */
534: pushl %eax /* push pc */
535: pushl %edx /* push mutex address */
536: call EXT(etap_mutex_hold) /* collect hold timestamp */
537: addl $16+12,%esp /* clean up stack, adjusting for locals */
538: #endif /* ETAP_LOCK_TRACE */
539:
540: EMARF
541: ret
542:
543: ml_fail:
544: #if ETAP_LOCK_TRACE
545: cmp $0,MISSED /* did we already take a wait timestamp? */
546: jne ml_block /* yup. carry-on */
547: pushl %edx /* push mutex address */
548: call EXT(etap_mutex_miss) /* get wait timestamp */
549: movl %eax,SWT_HI /* set wait time (high word) */
550: movl %edx,SWT_LO /* set wait time (low word) */
551: popl %edx /* clean up stack */
552: movl $1,MISSED /* mark wait timestamp as taken */
553: #endif /* ETAP_LOCK_TRACE */
554:
555: ml_block:
556: CHECK_MYLOCK(M_THREAD)
557: pushl %edx /* push mutex address */
558: call EXT(mutex_lock_wait) /* wait for the lock */
559: addl $4,%esp
560: movl L_ARG0,%edx /* refetch lock pointer */
561: jmp ml_retry /* and try again */
562:
563: ENTRY(_mutex_try)
564: FRAME
565:
566: #if ETAP_LOCK_TRACE
567: subl $8,%esp /* make room for locals */
568: movl $0,SWT_HI /* set wait time to zero (HI) */
569: movl $0,SWT_LO /* set wait time to zero (LO) */
570: #endif /* ETAP_LOCK_TRACE */
571:
572: movl L_ARG0,%edx /* fetch lock pointer */
573:
574: CHECK_MUTEX_TYPE()
575: CHECK_NO_SIMPLELOCKS()
576:
577: xorl %eax,%eax
578: movb $1,%al /* locked value for mutex */
579: xchgb %al,M_LOCKED /* swap locked values */
580: xorb $1,%al /* generate return value */
581:
582: #if MACH_LDEBUG || ETAP_LOCK_TRACE
583: testl %eax,%eax /* did we succeed? */
584: je 2f /* no, skip */
585: #endif
586:
587: #if MACH_LDEBUG
588: movl L_PC,%ecx
589: movl %ecx,M_PC
590: movl $CPD_ACTIVE_THREAD,%ecx
591: movl %gs:(%ecx),%ecx
592: movl %ecx,M_THREAD
593: testl %ecx,%ecx
594: je 1f
595: incl TH_MUTEX_COUNT(%ecx)
596: 1:
597: #endif
598:
599: #if ETAP_LOCK_TRACE
600: movl L_PC,%eax /* fetch pc */
601: pushl SWT_LO /* push wait time (low) */
602: pushl SWT_HI /* push wait time (high) */
603: pushl %eax /* push pc */
604: pushl %edx /* push mutex address */
605: call EXT(etap_mutex_hold) /* get start hold timestamp */
606: addl $16,%esp /* clean up stack, adjusting for locals */
607: movl $1,%eax /* put back successful return value */
608: #endif /* ETAP_LOCK_TRACE */
609:
610: #if MACH_LDEBUG || ETAP_LOCK_TRACE
611: 2:
612: #if ETAP_LOCK_TRACE
613: addl $8,%esp /* pop stack claimed on entry */
614: #endif
615: #endif
616:
617: EMARF
618: ret
619:
620: ENTRY(mutex_unlock)
621: FRAME
622: movl L_ARG0,%edx /* fetch lock pointer */
623:
624: #if ETAP_LOCK_TRACE
625: pushl %edx /* push mutex address */
626: call EXT(etap_mutex_unlock) /* collect ETAP data */
627: popl %edx /* restore mutex address */
628: #endif /* ETAP_LOCK_TRACE */
629:
630: CHECK_MUTEX_TYPE()
631: CHECK_THREAD(M_THREAD)
632:
633: DISABLE_PREEMPTION(%eax)
634:
635: mu_get_hw:
636: movb $1,%cl
637: xchgb %cl,M_ILK
638: testb %cl,%cl /* did we succeed? */
639: jne mu_get_hw /* no, try again */
640:
641: cmpw $0,M_WAITERS /* are there any waiters? */
642: jne mu_wakeup /* yes, more work to do */
643:
644: mu_doit:
645: #if MACH_LDEBUG
646: xorl %eax,%eax
647: movl %eax,M_THREAD /* disown thread */
648: movl $CPD_ACTIVE_THREAD,%eax
649: movl %gs:(%eax),%ecx
650: testl %ecx,%ecx
651: je 0f
652: decl TH_MUTEX_COUNT(%ecx)
653: 0:
654: #endif
655:
656: xorb %cl,%cl
657: xchgb %cl,M_LOCKED /* unlock the mutex */
658:
659: xorb %cl,%cl
660: xchgb %cl,M_ILK
661:
662: ENABLE_PREEMPTION(%eax)
663:
664: EMARF
665: ret
666:
667: mu_wakeup:
668: pushl %edx /* push mutex address */
669: call EXT(mutex_unlock_wakeup)/* yes, wake a thread */
670: addl $4,%esp
671: movl L_ARG0,%edx /* refetch lock pointer */
672: jmp mu_doit
673:
674: ENTRY(interlock_unlock)
675: FRAME
676: movl L_ARG0,%edx
677:
678: xorb %cl,%cl
679: xchgb %cl,M_ILK
680:
681: ENABLE_PREEMPTION(%eax)
682:
683: EMARF
684: ret
685:
686:
687: ENTRY(_disable_preemption)
688: #if MACH_RT
689: _DISABLE_PREEMPTION(%eax)
690: #endif /* MACH_RT */
691: ret
692:
693: ENTRY(_enable_preemption)
694: #if MACH_RT
695: #if MACH_ASSERT
696: movl $CPD_PREEMPTION_LEVEL,%eax
697: cmpl $0,%gs:(%eax)
698: jg 1f
699: pushl %gs:(%eax)
700: pushl $2f
701: call EXT(panic)
702: hlt
703: .data
704: 2: String "_enable_preemption: preemption_level(%d) < 0!"
705: .text
706: 1:
707: #endif /* MACH_ASSERT */
708: _ENABLE_PREEMPTION(%eax)
709: #endif /* MACH_RT */
710: ret
711:
712: ENTRY(_enable_preemption_no_check)
713: #if MACH_RT
714: #if MACH_ASSERT
715: movl $CPD_PREEMPTION_LEVEL,%eax
716: cmpl $0,%gs:(%eax)
717: jg 1f
718: pushl $2f
719: call EXT(panic)
720: hlt
721: .data
722: 2: String "_enable_preemption_no_check: preemption_level <= 0!"
723: .text
724: 1:
725: #endif /* MACH_ASSERT */
726: _ENABLE_PREEMPTION_NO_CHECK(%eax)
727: #endif /* MACH_RT */
728: ret
729:
730:
731: ENTRY(_mp_disable_preemption)
732: #if MACH_RT && NCPUS > 1
733: _DISABLE_PREEMPTION(%eax)
734: #endif /* MACH_RT && NCPUS > 1*/
735: ret
736:
737: ENTRY(_mp_enable_preemption)
738: #if MACH_RT && NCPUS > 1
739: #if MACH_ASSERT
740: movl $CPD_PREEMPTION_LEVEL,%eax
741: cmpl $0,%gs:(%eax)
742: jg 1f
743: pushl %gs:(%eax)
744: pushl $2f
745: call EXT(panic)
746: hlt
747: .data
748: 2: String "_mp_enable_preemption: preemption_level (%d) <= 0!"
749: .text
750: 1:
751: #endif /* MACH_ASSERT */
752: _ENABLE_PREEMPTION(%eax)
753: #endif /* MACH_RT && NCPUS > 1 */
754: ret
755:
756: ENTRY(_mp_enable_preemption_no_check)
757: #if MACH_RT && NCPUS > 1
758: #if MACH_ASSERT
759: movl $CPD_PREEMPTION_LEVEL,%eax
760: cmpl $0,%gs:(%eax)
761: jg 1f
762: pushl $2f
763: call EXT(panic)
764: hlt
765: .data
766: 2: String "_mp_enable_preemption_no_check: preemption_level <= 0!"
767: .text
768: 1:
769: #endif /* MACH_ASSERT */
770: _ENABLE_PREEMPTION_NO_CHECK(%eax)
771: #endif /* MACH_RT && NCPUS > 1 */
772: ret
773:
774:
775: ENTRY(i_bit_set)
776: movl S_ARG0,%edx
777: movl S_ARG1,%eax
778: lock
779: bts %dl,(%eax)
780: ret
781:
782: ENTRY(i_bit_clear)
783: movl S_ARG0,%edx
784: movl S_ARG1,%eax
785: lock
786: btr %dl,(%eax)
787: ret
788:
789: ENTRY(bit_lock)
790: movl S_ARG0,%ecx
791: movl S_ARG1,%eax
792: 1:
793: lock
794: bts %ecx,(%eax)
795: jb 1b
796: ret
797:
798: ENTRY(bit_lock_try)
799: movl S_ARG0,%ecx
800: movl S_ARG1,%eax
801: lock
802: bts %ecx,(%eax)
803: jb bit_lock_failed
804: ret /* %eax better not be null ! */
805: bit_lock_failed:
806: xorl %eax,%eax
807: ret
808:
809: ENTRY(bit_unlock)
810: movl S_ARG0,%ecx
811: movl S_ARG1,%eax
812: lock
813: btr %ecx,(%eax)
814: ret
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.