Merge branch 'generic-dispatch' of git://brick.kernel.dk/data/git/linux-2.6-block
[linux-2.6] / include / asm-x86_64 / rwlock.h
1 /* include/asm-x86_64/rwlock.h
2  *
3  *      Helpers used by both rw spinlocks and rw semaphores.
4  *
5  *      Based in part on code from semaphore.h and
6  *      spinlock.h Copyright 1996 Linus Torvalds.
7  *
8  *      Copyright 1999 Red Hat, Inc.
9  *      Copyright 2001,2002 SuSE labs 
10  *
11  *      Written by Benjamin LaHaise.
12  *
13  *      This program is free software; you can redistribute it and/or
14  *      modify it under the terms of the GNU General Public License
15  *      as published by the Free Software Foundation; either version
16  *      2 of the License, or (at your option) any later version.
17  */
18 #ifndef _ASM_X86_64_RWLOCK_H
19 #define _ASM_X86_64_RWLOCK_H
20
21 #include <linux/stringify.h>
22
23 #define RW_LOCK_BIAS             0x01000000
24 #define RW_LOCK_BIAS_STR        "0x01000000"
25
26 #define __build_read_lock_ptr(rw, helper)   \
27         asm volatile(LOCK "subl $1,(%0)\n\t" \
28                      "js 2f\n" \
29                      "1:\n" \
30                     LOCK_SECTION_START("") \
31                      "2:\tcall " helper "\n\t" \
32                      "jmp 1b\n" \
33                     LOCK_SECTION_END \
34                      ::"a" (rw) : "memory")
35
36 #define __build_read_lock_const(rw, helper)   \
37         asm volatile(LOCK "subl $1,%0\n\t" \
38                      "js 2f\n" \
39                      "1:\n" \
40                     LOCK_SECTION_START("") \
41                      "2:\tpushq %%rax\n\t" \
42                      "leaq %0,%%rax\n\t" \
43                      "call " helper "\n\t" \
44                      "popq %%rax\n\t" \
45                      "jmp 1b\n" \
46                     LOCK_SECTION_END \
47                      :"=m" (*((volatile int *)rw))::"memory")
48
49 #define __build_read_lock(rw, helper)   do { \
50                                                 if (__builtin_constant_p(rw)) \
51                                                         __build_read_lock_const(rw, helper); \
52                                                 else \
53                                                         __build_read_lock_ptr(rw, helper); \
54                                         } while (0)
55
56 #define __build_write_lock_ptr(rw, helper) \
57         asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
58                      "jnz 2f\n" \
59                      "1:\n" \
60                      LOCK_SECTION_START("") \
61                      "2:\tcall " helper "\n\t" \
62                      "jmp 1b\n" \
63                      LOCK_SECTION_END \
64                      ::"a" (rw) : "memory")
65
66 #define __build_write_lock_const(rw, helper) \
67         asm volatile(LOCK "subl $" RW_LOCK_BIAS_STR ",(%0)\n\t" \
68                      "jnz 2f\n" \
69                      "1:\n" \
70                     LOCK_SECTION_START("") \
71                      "2:\tpushq %%rax\n\t" \
72                      "leaq %0,%%rax\n\t" \
73                      "call " helper "\n\t" \
74                      "popq %%rax\n\t" \
75                      "jmp 1b\n" \
76                     LOCK_SECTION_END \
77                      :"=m" (*((volatile long *)rw))::"memory")
78
79 #define __build_write_lock(rw, helper)  do { \
80                                                 if (__builtin_constant_p(rw)) \
81                                                         __build_write_lock_const(rw, helper); \
82                                                 else \
83                                                         __build_write_lock_ptr(rw, helper); \
84                                         } while (0)
85
86 #endif