|
|
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.