Pull bugzilla-3241 into release branch
[linux-2.6] / arch / i386 / kernel / semaphore.c
1 /*
2  * i386 semaphore implementation.
3  *
4  * (C) Copyright 1999 Linus Torvalds
5  *
6  * Portions Copyright 1999 Red Hat, Inc.
7  *
8  *      This program is free software; you can redistribute it and/or
9  *      modify it under the terms of the GNU General Public License
10  *      as published by the Free Software Foundation; either version
11  *      2 of the License, or (at your option) any later version.
12  *
13  * rw semaphores implemented November 1999 by Benjamin LaHaise <bcrl@kvack.org>
14  */
15 #include <asm/semaphore.h>
16
17 /*
18  * The semaphore operations have a special calling sequence that
19  * allow us to do a simpler in-line version of them. These routines
20  * need to convert that sequence back into the C sequence when
21  * there is contention on the semaphore.
22  *
23  * %eax contains the semaphore pointer on entry. Save the C-clobbered
24  * registers (%eax, %edx and %ecx) except %eax whish is either a return
25  * value or just clobbered..
26  */
27 asm(
28 ".section .sched.text\n"
29 ".align 4\n"
30 ".globl __down_failed\n"
31 "__down_failed:\n\t"
32 #if defined(CONFIG_FRAME_POINTER)
33         "pushl %ebp\n\t"
34         "movl  %esp,%ebp\n\t"
35 #endif
36         "pushl %edx\n\t"
37         "pushl %ecx\n\t"
38         "call __down\n\t"
39         "popl %ecx\n\t"
40         "popl %edx\n\t"
41 #if defined(CONFIG_FRAME_POINTER)
42         "movl %ebp,%esp\n\t"
43         "popl %ebp\n\t"
44 #endif
45         "ret"
46 );
47
48 asm(
49 ".section .sched.text\n"
50 ".align 4\n"
51 ".globl __down_failed_interruptible\n"
52 "__down_failed_interruptible:\n\t"
53 #if defined(CONFIG_FRAME_POINTER)
54         "pushl %ebp\n\t"
55         "movl  %esp,%ebp\n\t"
56 #endif
57         "pushl %edx\n\t"
58         "pushl %ecx\n\t"
59         "call __down_interruptible\n\t"
60         "popl %ecx\n\t"
61         "popl %edx\n\t"
62 #if defined(CONFIG_FRAME_POINTER)
63         "movl %ebp,%esp\n\t"
64         "popl %ebp\n\t"
65 #endif
66         "ret"
67 );
68
69 asm(
70 ".section .sched.text\n"
71 ".align 4\n"
72 ".globl __down_failed_trylock\n"
73 "__down_failed_trylock:\n\t"
74 #if defined(CONFIG_FRAME_POINTER)
75         "pushl %ebp\n\t"
76         "movl  %esp,%ebp\n\t"
77 #endif
78         "pushl %edx\n\t"
79         "pushl %ecx\n\t"
80         "call __down_trylock\n\t"
81         "popl %ecx\n\t"
82         "popl %edx\n\t"
83 #if defined(CONFIG_FRAME_POINTER)
84         "movl %ebp,%esp\n\t"
85         "popl %ebp\n\t"
86 #endif
87         "ret"
88 );
89
90 asm(
91 ".section .sched.text\n"
92 ".align 4\n"
93 ".globl __up_wakeup\n"
94 "__up_wakeup:\n\t"
95         "pushl %edx\n\t"
96         "pushl %ecx\n\t"
97         "call __up\n\t"
98         "popl %ecx\n\t"
99         "popl %edx\n\t"
100         "ret"
101 );
102
103 /*
104  * rw spinlock fallbacks
105  */
106 #if defined(CONFIG_SMP)
107 asm(
108 ".section .sched.text\n"
109 ".align 4\n"
110 ".globl __write_lock_failed\n"
111 "__write_lock_failed:\n\t"
112         LOCK_PREFIX "addl       $" RW_LOCK_BIAS_STR ",(%eax)\n"
113 "1:     rep; nop\n\t"
114         "cmpl   $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
115         "jne    1b\n\t"
116         LOCK_PREFIX "subl       $" RW_LOCK_BIAS_STR ",(%eax)\n\t"
117         "jnz    __write_lock_failed\n\t"
118         "ret"
119 );
120
121 asm(
122 ".section .sched.text\n"
123 ".align 4\n"
124 ".globl __read_lock_failed\n"
125 "__read_lock_failed:\n\t"
126         LOCK_PREFIX "incl       (%eax)\n"
127 "1:     rep; nop\n\t"
128         "cmpl   $1,(%eax)\n\t"
129         "js     1b\n\t"
130         LOCK_PREFIX "decl       (%eax)\n\t"
131         "js     __read_lock_failed\n\t"
132         "ret"
133 );
134 #endif