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 87