diff options
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h')
-rw-r--r-- | nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h | 95 |
1 files changed, 74 insertions, 21 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h index aa963f77e7..474b39ae18 100644 --- a/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h +++ b/nptl/sysdeps/unix/sysv/linux/i386/lowlevellock.h @@ -23,6 +23,8 @@ #include <time.h> #include <sys/param.h> #include <bits/pthreadtypes.h> +#include <kernel-features.h> +#include <tcb-offsets.h> #ifndef LOCK_INSTR # ifdef UP @@ -41,6 +43,13 @@ #define FUTEX_PRIVATE_FLAG 128 +/* Values for 'private' parameter of locking macros. Yes, the + definition seems to be backwards. But it is not. The bit will be + reversed before passing to the system call. */ +#define LLL_PRIVATE 0 +#define LLL_SHARED FUTEX_PRIVATE_FLAG + + /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED (1) @@ -145,7 +154,11 @@ LLL_STUB_UNWIND_INFO_START \ LLL_STUB_UNWIND_INFO_END -#define lll_futex_wait(futex, val) \ +#define lll_futex_wait(futex, val, private) \ + lll_futex_timed_wait (futex, val, NULL, private) + + +#define lll_futex_timed_wait(futex, val, timeout, private) \ ({ \ int __status; \ register __typeof (val) _val asm ("edx") = (val); \ @@ -153,7 +166,7 @@ LLL_STUB_UNWIND_INFO_END LLL_ENTER_KERNEL \ LLL_EBX_LOAD \ : "=a" (__status) \ - : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0), \ + : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ "c" (FUTEX_WAIT), "d" (_val), \ "i" (offsetof (tcbhead_t, sysinfo)) \ : "memory"); \ @@ -161,7 +174,27 @@ LLL_STUB_UNWIND_INFO_END }) -#define lll_futex_timed_wait(futex, val, timeout) \ +#define lll_futex_wake(futex, nr, private) \ + do { \ + int __ignore; \ + register __typeof (nr) _nr asm ("edx") = (nr); \ + __asm __volatile (LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore) \ + : "0" (SYS_futex), LLL_EBX_REG (futex), \ + "c" (FUTEX_WAKE), "d" (_nr), \ + "i" (0) /* phony, to align next arg's number */, \ + "i" (offsetof (tcbhead_t, sysinfo))); \ + } while (0) + + +#define lll_private_futex_wait(futex, val) \ + lll_private_futex_timed_wait (futex, val, NULL) + + +#ifdef __ASSUME_PRIVATE_FUTEX +# define lll_private_futex_timed_wait(futex, val, timeout) \ ({ \ int __status; \ register __typeof (val) _val asm ("edx") = (val); \ @@ -170,14 +203,14 @@ LLL_STUB_UNWIND_INFO_END LLL_EBX_LOAD \ : "=a" (__status) \ : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ - "c" (FUTEX_WAIT), "d" (_val), \ + "c" (FUTEX_WAIT | FUTEX_PRIVATE_FLAG)), "d" (_val), \ "i" (offsetof (tcbhead_t, sysinfo)) \ : "memory"); \ __status; \ }) -#define lll_futex_wake(futex, nr) \ +# define lll_private_futex_wake(futex, nr) \ do { \ int __ignore; \ register __typeof (nr) _nr asm ("edx") = (nr); \ @@ -186,10 +219,45 @@ LLL_STUB_UNWIND_INFO_END LLL_EBX_LOAD \ : "=a" (__ignore) \ : "0" (SYS_futex), LLL_EBX_REG (futex), \ - "c" (FUTEX_WAKE), "d" (_nr), \ + "c" (FUTEX_WAKE | FUTEX_PRIVATE_FLAG), "d" (_nr), \ "i" (0) /* phony, to align next arg's number */, \ "i" (offsetof (tcbhead_t, sysinfo))); \ } while (0) +#else +# define lll_private_futex_timed_wait(futex, val, timeout) \ + ({ \ + int __status; \ + int __ignore; \ + register __typeof (val) _val asm ("edx") = (val); \ + __asm __volatile ("movl %%gs:%P7, %%ecx\n\t" \ + LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__status), "=c" (__ignore) \ + : LLL_EBX_REG (futex), "0" (SYS_futex), "S" (timeout), \ + "d" (_val), "i" (offsetof (tcbhead_t, sysinfo)), \ + "i" (PRIVATE_FUTEX) \ + : "memory"); \ + __status; \ + }) + + +# define lll_private_futex_wake(futex, nr) \ + do { \ + int __ignore; \ + int __ignore2; \ + register __typeof (nr) _nr asm ("edx") = (nr); \ + __asm __volatile ("orl %%gs:%P7, %%ecx\n\t" \ + LLL_EBX_LOAD \ + LLL_ENTER_KERNEL \ + LLL_EBX_LOAD \ + : "=a" (__ignore), "=c" (__ignore2) \ + : LLL_EBX_REG (futex), "0" (SYS_futex), \ + "1" (FUTEX_WAKE), "d" (_nr), \ + "i" (offsetof (tcbhead_t, sysinfo)), \ + "i" (PRIVATE_FUTEX)); \ + } while (0) +#endif /* Does not preserve %eax and %ecx. */ @@ -415,21 +483,6 @@ extern int __lll_mutex_unlock_wake (int *__futex) "i" (offsetof (tcbhead_t, sysinfo))); }) -#define lll_futex_wake(futex, nr) \ - do { \ - int __ignore; \ - register __typeof (nr) _nr asm ("edx") = (nr); \ - __asm __volatile (LLL_EBX_LOAD \ - LLL_ENTER_KERNEL \ - LLL_EBX_LOAD \ - : "=a" (__ignore) \ - : "0" (SYS_futex), LLL_EBX_REG (futex), \ - "c" (FUTEX_WAKE), "d" (_nr), \ - "i" (0) /* phony, to align next arg's number */, \ - "i" (offsetof (tcbhead_t, sysinfo))); \ - } while (0) - - #define lll_mutex_islocked(futex) \ (futex != 0) |