|
|
1.1 ! root 1: #ifndef _I386_SEMAPHORE_H ! 2: #define _I386_SEMAPHORE_H ! 3: ! 4: #include <linux/linkage.h> ! 5: #include <asm/system.h> ! 6: ! 7: /* ! 8: * SMP- and interrupt-safe semaphores.. ! 9: * ! 10: * (C) Copyright 1996 Linus Torvalds ! 11: * ! 12: * Modified 1996-12-23 by Dave Grothe <[email protected]> to fix bugs in ! 13: * the original code and to make semaphore waits ! 14: * interruptible so that processes waiting on ! 15: * semaphores can be killed. ! 16: * ! 17: * If you would like to see an analysis of this implementation, please ! 18: * ftp to gcom.com and download the file ! 19: * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz. ! 20: * ! 21: */ ! 22: ! 23: struct semaphore { ! 24: int count; ! 25: int waking; ! 26: int lock ; /* to make waking testing atomic */ ! 27: struct wait_queue * wait; ! 28: }; ! 29: ! 30: #define MUTEX ((struct semaphore) { 1, 0, 0, NULL }) ! 31: #define MUTEX_LOCKED ((struct semaphore) { 0, 0, 0, NULL }) ! 32: ! 33: asmlinkage void down_failed(void /* special register calling convention */); ! 34: asmlinkage void up_wakeup(void /* special register calling convention */); ! 35: ! 36: extern void __down(struct semaphore * sem); ! 37: extern void __up(struct semaphore * sem); ! 38: ! 39: /* ! 40: * This is ugly, but we want the default case to fall through. ! 41: * "down_failed" is a special asm handler that calls the C ! 42: * routine that actually waits. See arch/i386/lib/semaphore.S ! 43: */ ! 44: extern inline void down(struct semaphore * sem) ! 45: { ! 46: __asm__ __volatile__( ! 47: "# atomic down operation\n\t" ! 48: "movl $1f,%%eax\n\t" ! 49: #ifdef __SMP__ ! 50: "lock ; " ! 51: #endif ! 52: "decl 0(%0)\n\t" ! 53: "js " SYMBOL_NAME_STR(down_failed) "\n" ! 54: "1:\n" ! 55: :/* no outputs */ ! 56: :"c" (sem) ! 57: :"ax","dx","memory"); ! 58: } ! 59: ! 60: /* ! 61: * Primitives to spin on a lock. Needed only for SMP version. ! 62: */ ! 63: extern inline void get_buzz_lock(int *lock_ptr) ! 64: { ! 65: #ifdef __SMP__ ! 66: while (xchg(lock_ptr,1) != 0) ; ! 67: #endif ! 68: } /* get_buzz_lock */ ! 69: ! 70: extern inline void give_buzz_lock(int *lock_ptr) ! 71: { ! 72: #ifdef __SMP__ ! 73: *lock_ptr = 0 ; ! 74: #endif ! 75: } /* give_buzz_lock */ ! 76: ! 77: asmlinkage int down_failed_interruptible(void); /* params in registers */ ! 78: ! 79: /* ! 80: * This version waits in interruptible state so that the waiting ! 81: * process can be killed. The down_failed_interruptible routine ! 82: * returns negative for signalled and zero for semaphore acquired. ! 83: */ ! 84: extern inline int down_interruptible(struct semaphore * sem) ! 85: { ! 86: int ret ; ! 87: ! 88: __asm__ __volatile__( ! 89: "# atomic interruptible down operation\n\t" ! 90: "movl $2f,%%eax\n\t" ! 91: #ifdef __SMP__ ! 92: "lock ; " ! 93: #endif ! 94: "decl 0(%1)\n\t" ! 95: "js " SYMBOL_NAME_STR(down_failed_interruptible) "\n\t" ! 96: "xorl %%eax,%%eax\n" ! 97: "2:\n" ! 98: :"=a" (ret) ! 99: :"c" (sem) ! 100: :"ax","dx","memory"); ! 101: ! 102: return(ret) ; ! 103: } ! 104: ! 105: /* ! 106: * Note! This is subtle. We jump to wake people up only if ! 107: * the semaphore was negative (== somebody was waiting on it). ! 108: * The default case (no contention) will result in NO ! 109: * jumps for both down() and up(). ! 110: */ ! 111: extern inline void up(struct semaphore * sem) ! 112: { ! 113: __asm__ __volatile__( ! 114: "# atomic up operation\n\t" ! 115: "movl $1f,%%eax\n\t" ! 116: #ifdef __SMP__ ! 117: "lock ; " ! 118: #endif ! 119: "incl 0(%0)\n\t" ! 120: "jle " SYMBOL_NAME_STR(up_wakeup) ! 121: "\n1:" ! 122: :/* no outputs */ ! 123: :"c" (sem) ! 124: :"ax", "dx", "memory"); ! 125: } ! 126: ! 127: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.