|
|
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:
1.1.1.2 ! root 33: /* Special register calling convention:
! 34: * eax contains return address
! 35: * ecx contains semaphore address
! 36: */
1.1 root 37: asmlinkage void down_failed(void /* special register calling convention */);
38: asmlinkage void up_wakeup(void /* special register calling convention */);
39:
40: extern void __down(struct semaphore * sem);
41: extern void __up(struct semaphore * sem);
42:
43: /*
44: * This is ugly, but we want the default case to fall through.
45: * "down_failed" is a special asm handler that calls the C
46: * routine that actually waits. See arch/i386/lib/semaphore.S
47: */
1.1.1.2 ! root 48: static inline void down(struct semaphore * sem)
1.1 root 49: {
1.1.1.2 ! root 50: int d0;
1.1 root 51: __asm__ __volatile__(
52: "# atomic down operation\n\t"
53: "movl $1f,%%eax\n\t"
54: #ifdef __SMP__
55: "lock ; "
56: #endif
1.1.1.2 ! root 57: "decl %1\n\t"
1.1 root 58: "js " SYMBOL_NAME_STR(down_failed) "\n"
59: "1:\n"
1.1.1.2 ! root 60: :"=&a" (d0), "=m" (sem->count)
1.1 root 61: :"c" (sem)
1.1.1.2 ! root 62: :"memory");
1.1 root 63: }
64:
65: /*
66: * Primitives to spin on a lock. Needed only for SMP version.
67: */
68: extern inline void get_buzz_lock(int *lock_ptr)
69: {
70: #ifdef __SMP__
71: while (xchg(lock_ptr,1) != 0) ;
72: #endif
73: } /* get_buzz_lock */
74:
75: extern inline void give_buzz_lock(int *lock_ptr)
76: {
77: #ifdef __SMP__
78: *lock_ptr = 0 ;
79: #endif
80: } /* give_buzz_lock */
81:
82: asmlinkage int down_failed_interruptible(void); /* params in registers */
83:
84: /*
85: * This version waits in interruptible state so that the waiting
86: * process can be killed. The down_failed_interruptible routine
87: * returns negative for signalled and zero for semaphore acquired.
88: */
1.1.1.2 ! root 89: static inline int down_interruptible(struct semaphore * sem)
1.1 root 90: {
91: int ret ;
92:
93: __asm__ __volatile__(
94: "# atomic interruptible down operation\n\t"
95: "movl $2f,%%eax\n\t"
96: #ifdef __SMP__
97: "lock ; "
98: #endif
1.1.1.2 ! root 99: "decl %1\n\t"
1.1 root 100: "js " SYMBOL_NAME_STR(down_failed_interruptible) "\n\t"
101: "xorl %%eax,%%eax\n"
102: "2:\n"
1.1.1.2 ! root 103: :"=&a" (ret), "=m" (sem->count)
1.1 root 104: :"c" (sem)
1.1.1.2 ! root 105: :"memory");
1.1 root 106:
107: return(ret) ;
108: }
109:
110: /*
111: * Note! This is subtle. We jump to wake people up only if
112: * the semaphore was negative (== somebody was waiting on it).
113: * The default case (no contention) will result in NO
114: * jumps for both down() and up().
115: */
1.1.1.2 ! root 116: static inline void up(struct semaphore * sem)
1.1 root 117: {
1.1.1.2 ! root 118: int d0;
1.1 root 119: __asm__ __volatile__(
120: "# atomic up operation\n\t"
121: "movl $1f,%%eax\n\t"
122: #ifdef __SMP__
123: "lock ; "
124: #endif
1.1.1.2 ! root 125: "incl %1\n\t"
1.1 root 126: "jle " SYMBOL_NAME_STR(up_wakeup)
127: "\n1:"
1.1.1.2 ! root 128: :"=&a" (d0), "=m" (sem->count)
1.1 root 129: :"c" (sem)
1.1.1.2 ! root 130: :"memory");
1.1 root 131: }
132:
133: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.