Import 2.2.2pre5
[davej-history.git] / include / asm-i386 / semaphore.h
blobccf69385cb68247ca3856e23200faf863d8063b3
1 #ifndef _I386_SEMAPHORE_H
2 #define _I386_SEMAPHORE_H
4 #include <linux/linkage.h>
6 /*
7 * SMP- and interrupt-safe semaphores..
9 * (C) Copyright 1996 Linus Torvalds
11 * Modified 1996-12-23 by Dave Grothe <dave@gcom.com> to fix bugs in
12 * the original code and to make semaphore waits
13 * interruptible so that processes waiting on
14 * semaphores can be killed.
15 * Modified 1999-02-14 by Andrea Arcangeli, split the sched.c helper
16 * functions in asm/sempahore-helper.h while fixing a
17 * potential and subtle race discovered by Ulrich Schmid
18 * in down_interruptible(). Since I started to play here I
19 * also implemented the `trylock' semaphore operation.
21 * If you would like to see an analysis of this implementation, please
22 * ftp to gcom.com and download the file
23 * /pub/linux/src/semaphore/semaphore-2.0.24.tar.gz.
27 #include <asm/system.h>
28 #include <asm/atomic.h>
29 #include <asm/spinlock.h>
31 struct semaphore {
32 atomic_t count;
33 int waking;
34 struct wait_queue * wait;
37 #define MUTEX ((struct semaphore) { ATOMIC_INIT(1), 0, NULL })
38 #define MUTEX_LOCKED ((struct semaphore) { ATOMIC_INIT(0), 0, NULL })
40 asmlinkage void__down_failed(void/* special register calling convention */);
41 asmlinkage int__down_failed_interruptible(void/* params in registers */);
42 asmlinkage int__down_failed_trylock(void/* params in registers */);
43 asmlinkage void__up_wakeup(void/* special register calling convention */);
45 asmlinkage void__down(struct semaphore * sem);
46 asmlinkage int__down_interruptible(struct semaphore * sem);
47 asmlinkage int__down_trylock(struct semaphore * sem);
48 asmlinkage void__up(struct semaphore * sem);
50 extern spinlock_t semaphore_wake_lock;
52 #define sema_init(sem, val) atomic_set(&((sem)->count), (val))
55 * This is ugly, but we want the default case to fall through.
56 * "down_failed" is a special asm handler that calls the C
57 * routine that actually waits. See arch/i386/lib/semaphore.S
59 extern inlinevoiddown(struct semaphore * sem)
61 __asm__ __volatile__(
62 "# atomic down operation\n\t"
63 #ifdef __SMP__
64 "lock ; "
65 #endif
66 "decl 0(%0)\n\t"
67 "js 2f\n"
68 "1:\n"
69 ".section .text.lock,\"ax\"\n"
70 "2:\tpushl $1b\n\t"
71 "jmp __down_failed\n"
72 ".previous"
73 :/* no outputs */
74 :"c"(sem)
75 :"memory");
78 extern inlineintdown_interruptible(struct semaphore * sem)
80 int result;
82 __asm__ __volatile__(
83 "# atomic interruptible down operation\n\t"
84 #ifdef __SMP__
85 "lock ; "
86 #endif
87 "decl 0(%1)\n\t"
88 "js 2f\n\t"
89 "xorl %0,%0\n"
90 "1:\n"
91 ".section .text.lock,\"ax\"\n"
92 "2:\tpushl $1b\n\t"
93 "jmp __down_failed_interruptible\n"
94 ".previous"
95 :"=a"(result)
96 :"c"(sem)
97 :"memory");
98 return result;
101 extern inlineintdown_trylock(struct semaphore * sem)
103 int result;
105 __asm__ __volatile__(
106 "# atomic interruptible down operation\n\t"
107 #ifdef __SMP__
108 "lock ; "
109 #endif
110 "decl 0(%1)\n\t"
111 "js 2f\n\t"
112 "xorl %0,%0\n"
113 "1:\n"
114 ".section .text.lock,\"ax\"\n"
115 "2:\tpushl $1b\n\t"
116 "jmp __down_failed_trylock\n"
117 ".previous"
118 :"=a"(result)
119 :"c"(sem)
120 :"memory");
121 return result;
125 * Note! This is subtle. We jump to wake people up only if
126 * the semaphore was negative (== somebody was waiting on it).
127 * The default case (no contention) will result in NO
128 * jumps for both down() and up().
130 extern inlinevoidup(struct semaphore * sem)
132 __asm__ __volatile__(
133 "# atomic up operation\n\t"
134 #ifdef __SMP__
135 "lock ; "
136 #endif
137 "incl 0(%0)\n\t"
138 "jle 2f\n"
139 "1:\n"
140 ".section .text.lock,\"ax\"\n"
141 "2:\tpushl $1b\n\t"
142 "jmp __up_wakeup\n"
143 ".previous"
144 :/* no outputs */
145 :"c"(sem)
146 :"memory");
149 #endif
close