Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
git-mirror
/
glibc
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Pull requests
0
Actions
Projects
0
Security
Insights
Additional navigation options
Code
Pull requests
Actions
Projects
Security
Insights
Files
d5ba53f
abilist
aout
argp
assert
bits
catgets
conf
conform
crypt
csu
ctype
debug
dirent
dlfcn
elf
gmon
gnulib
grp
hesiod
hurd
iconv
iconvdata
include
inet
intl
io
libidn
libio
locale
localedata
login
mach
malloc
manual
math
misc
nis
nptl
sysdeps
alpha
i386
ia64
powerpc
pthread
s390
sh
sparc
unix/sysv/linux
alpha
bits
i386
bits
i486
i586
i686
clone.S
createthread.c
dl-sysdep.h
fork.c
lowlevellock.h
not-cancel.h
pt-vfork.S
pthread_once.S
pthread_spin_init.c
pthread_spin_unlock.S
sysdep-cancel.h
vfork.S
ia64
powerpc
s390
sh
sparc
x86_64
Implies
Makefile
Versions
aio_misc.h
allocrtsig.c
createthread.c
fork.c
fork.h
getpid.c
internaltypes.h
jmp-unwind.c
kernel-posix-timers.h
libc-lowlevellock.c
libc_multiple_threads.c
libc_pthread_init.c
lowlevelbarrier.sym
lowlevelcond.sym
lowlevellock.c
lowlevelrobustlock.c
lowlevelrobustlock.sym
lowlevelrwlock.sym
mq_notify.c
pt-fork.c
pt-raise.c
pthread-pi-defines.sym
pthread_attr_getaffinity.c
pthread_attr_setaffinity.c
pthread_getaffinity.c
pthread_getcpuclockid.c
pthread_kill.c
pthread_mutex_cond_lock.c
pthread_setaffinity.c
pthread_yield.c
raise.c
register-atfork.c
sem_post.c
sem_timedwait.c
sem_trywait.c
sem_wait.c
sigtimedwait.c
sigwait.c
sigwaitinfo.c
sleep.c
smp.h
timer_create.c
timer_delete.c
timer_getoverr.c
timer_gettime.c
timer_routines.c
timer_settime.c
unregister-atfork.c
unwindbuf.sym
x86_64
ANNOUNCE
Banner
ChangeLog
DESIGN-barrier.txt
DESIGN-condvar.txt
DESIGN-rwlock.txt
DESIGN-sem.txt
Makeconfig
Makefile
TODO
TODO-kernel
TODO-testing
Versions
alloca_cutoff.c
allocatestack.c
cancellation.c
cleanup.c
cleanup_compat.c
cleanup_defer.c
cleanup_defer_compat.c
cleanup_routine.c
cond-perf.c
configure
descr.h
eintr.c
errno-loc.c
events.c
forward.c
herrno.c
init.c
libc-cancellation.c
lowlevellock.h
old_pthread_atfork.c
old_pthread_cond_broadcast.c
old_pthread_cond_destroy.c
old_pthread_cond_init.c
old_pthread_cond_signal.c
old_pthread_cond_timedwait.c
old_pthread_cond_wait.c
perf.c
pt-allocrtsig.c
pt-cleanup.c
pt-raise.c
pt-system.c
pthread-errnos.sym
pthreadP.h
pthread_atfork.c
pthread_attr_destroy.c
pthread_attr_getdetachstate.c
pthread_attr_getguardsize.c
pthread_attr_getinheritsched.c
pthread_attr_getschedparam.c
pthread_attr_getschedpolicy.c
pthread_attr_getscope.c
pthread_attr_getstack.c
pthread_attr_getstackaddr.c
pthread_attr_getstacksize.c
pthread_attr_init.c
pthread_attr_setdetachstate.c
pthread_attr_setguardsize.c
pthread_attr_setinheritsched.c
pthread_attr_setschedparam.c
pthread_attr_setschedpolicy.c
pthread_attr_setscope.c
pthread_attr_setstack.c
pthread_attr_setstackaddr.c
pthread_attr_setstacksize.c
pthread_barrier_destroy.c
pthread_barrier_init.c
pthread_barrierattr_destroy.c
pthread_barrierattr_getpshared.c
pthread_barrierattr_init.c
pthread_barrierattr_setpshared.c
pthread_cancel.c
pthread_clock_gettime.c
pthread_clock_settime.c
pthread_cond_destroy.c
pthread_cond_init.c
pthread_condattr_destroy.c
pthread_condattr_getclock.c
pthread_condattr_getpshared.c
pthread_condattr_init.c
pthread_condattr_setclock.c
pthread_condattr_setpshared.c
pthread_create.c
pthread_detach.c
pthread_equal.c
pthread_exit.c
pthread_getattr_np.c
pthread_getconcurrency.c
pthread_getschedparam.c
pthread_getspecific.c
pthread_join.c
pthread_key_create.c
pthread_key_delete.c
pthread_kill_other_threads.c
pthread_mutex_consistent.c
pthread_mutex_destroy.c
pthread_mutex_getprioceiling.c
pthread_mutex_init.c
pthread_mutex_lock.c
pthread_mutex_setprioceiling.c
pthread_mutex_timedlock.c
pthread_mutex_trylock.c
pthread_mutex_unlock.c
pthread_mutexattr_destroy.c
pthread_mutexattr_getprioceiling.c
pthread_mutexattr_getprotocol.c
pthread_mutexattr_getpshared.c
pthread_mutexattr_getrobust.c
pthread_mutexattr_gettype.c
pthread_mutexattr_init.c
pthread_mutexattr_setprioceiling.c
pthread_mutexattr_setprotocol.c
pthread_mutexattr_setpshared.c
pthread_mutexattr_setrobust.c
pthread_mutexattr_settype.c
pthread_rwlock_destroy.c
pthread_rwlock_init.c
pthread_rwlock_tryrdlock.c
pthread_rwlock_trywrlock.c
pthread_rwlockattr_destroy.c
pthread_rwlockattr_getkind_np.c
pthread_rwlockattr_getpshared.c
pthread_rwlockattr_init.c
pthread_rwlockattr_setkind_np.c
pthread_rwlockattr_setpshared.c
pthread_self.c
pthread_setcancelstate.c
pthread_setcanceltype.c
pthread_setconcurrency.c
pthread_setegid.c
pthread_seteuid.c
pthread_setgid.c
pthread_setregid.c
pthread_setresgid.c
pthread_setresuid.c
pthread_setreuid.c
pthread_setschedparam.c
pthread_setschedprio.c
pthread_setspecific.c
pthread_setuid.c
pthread_testcancel.c
pthread_timedjoin.c
pthread_tryjoin.c
res.c
sem_close.c
sem_destroy.c
sem_getvalue.c
sem_init.c
sem_open.c
sem_unlink.c
semaphore.h
semaphoreP.h
shlib-versions
sigaction.c
sockperf.c
tst-_res1.c
tst-_res1mod1.c
tst-_res1mod2.c
tst-align.c
tst-align2.c
tst-align3.c
tst-atfork1.c
tst-atfork2.c
tst-atfork2mod.c
tst-attr1.c
tst-attr2.c
tst-attr3.c
tst-backtrace1.c
tst-barrier1.c
tst-barrier2.c
tst-barrier3.c
tst-barrier4.c
tst-basic1.c
tst-basic2.c
tst-basic3.c
tst-basic4.c
tst-basic5.c
tst-basic6.c
tst-cancel-wrappers.sh
tst-cancel1.c
tst-cancel10.c
tst-cancel11.c
tst-cancel12.c
tst-cancel13.c
tst-cancel14.c
tst-cancel15.c
tst-cancel16.c
tst-cancel17.c
tst-cancel18.c
tst-cancel19.c
tst-cancel2.c
tst-cancel20.c
tst-cancel21.c
tst-cancel22.c
tst-cancel23.c
tst-cancel24.cc
tst-cancel3.c
tst-cancel4.c
tst-cancel5.c
tst-cancel6.c
tst-cancel7.c
tst-cancel8.c
tst-cancel9.c
tst-cancelx1.c
tst-cancelx10.c
tst-cancelx11.c
tst-cancelx12.c
tst-cancelx13.c
tst-cancelx14.c
tst-cancelx15.c
tst-cancelx16.c
tst-cancelx17.c
tst-cancelx18.c
tst-cancelx2.c
tst-cancelx20.c
tst-cancelx21.c
tst-cancelx3.c
tst-cancelx4.c
tst-cancelx5.c
tst-cancelx6.c
tst-cancelx7.c
tst-cancelx8.c
tst-cancelx9.c
tst-cleanup0.c
tst-cleanup0.expect
tst-cleanup1.c
tst-cleanup2.c
tst-cleanup3.c
tst-cleanup4.c
tst-cleanup4aux.c
tst-cleanupx0.c
tst-cleanupx0.expect
tst-cleanupx1.c
tst-cleanupx2.c
tst-cleanupx3.c
tst-cleanupx4.c
tst-clock1.c
tst-clock2.c
tst-cond1.c
tst-cond10.c
tst-cond11.c
tst-cond12.c
tst-cond13.c
tst-cond14.c
tst-cond15.c
tst-cond16.c
tst-cond17.c
tst-cond18.c
tst-cond19.c
tst-cond2.c
tst-cond20.c
tst-cond21.c
tst-cond3.c
tst-cond4.c
tst-cond5.c
tst-cond6.c
tst-cond7.c
tst-cond8.c
tst-cond9.c
tst-context1.c
tst-detach1.c
tst-dlsym1.c
tst-eintr1.c
tst-eintr2.c
tst-eintr3.c
tst-eintr4.c
tst-eintr5.c
tst-exec1.c
tst-exec2.c
tst-exec3.c
tst-exec4.c
tst-execstack-mod.c
tst-execstack.c
tst-exit1.c
tst-exit2.c
tst-exit3.c
tst-fini1.c
tst-fini1mod.c
tst-flock1.c
tst-flock2.c
tst-fork1.c
tst-fork2.c
tst-fork3.c
tst-fork4.c
tst-getpid1.c
tst-getpid2.c
tst-initializers1-c89.c
tst-initializers1-c99.c
tst-initializers1-gnu89.c
tst-initializers1-gnu99.c
tst-initializers1.c
tst-join1.c
tst-join2.c
tst-join3.c
tst-join4.c
tst-join5.c
tst-key1.c
tst-key2.c
tst-key3.c
tst-key4.c
tst-kill1.c
tst-kill2.c
tst-kill3.c
tst-kill4.c
tst-kill5.c
tst-kill6.c
tst-locale1.c
tst-locale2.c
tst-mutex1.c
tst-mutex2.c
tst-mutex3.c
tst-mutex4.c
tst-mutex5.c
tst-mutex5a.c
tst-mutex6.c
tst-mutex7.c
tst-mutex7a.c
tst-mutex8.c
tst-mutex9.c
tst-mutexpi1.c
tst-mutexpi2.c
tst-mutexpi3.c
tst-mutexpi4.c
tst-mutexpi5.c
tst-mutexpi5a.c
tst-mutexpi6.c
tst-mutexpi7.c
tst-mutexpi7a.c
tst-mutexpi8.c
tst-mutexpi9.c
tst-oddstacklimit.c
tst-once1.c
tst-once2.c
tst-once3.c
tst-once4.c
tst-oncex3.c
tst-oncex4.c
tst-popen1.c
tst-raise1.c
tst-robust1.c
tst-robust2.c
tst-robust3.c
tst-robust4.c
tst-robust5.c
tst-robust6.c
tst-robust7.c
tst-robust8.c
tst-robustpi1.c
tst-robustpi2.c
tst-robustpi3.c
tst-robustpi4.c
tst-robustpi5.c
tst-robustpi6.c
tst-robustpi7.c
tst-robustpi8.c
tst-rwlock1.c
tst-rwlock10.c
tst-rwlock11.c
tst-rwlock12.c
tst-rwlock13.c
tst-rwlock14.c
tst-rwlock2.c
tst-rwlock3.c
tst-rwlock4.c
tst-rwlock5.c
tst-rwlock6.c
tst-rwlock7.c
tst-rwlock8.c
tst-rwlock9.c
tst-sched1.c
tst-sem1.c
tst-sem2.c
tst-sem3.c
tst-sem4.c
tst-sem5.c
tst-sem6.c
tst-sem7.c
tst-sem8.c
tst-sem9.c
tst-setuid1-static.c
tst-setuid1.c
tst-signal1.c
tst-signal2.c
tst-signal3.c
tst-signal4.c
tst-signal5.c
tst-signal6.c
tst-signal7.c
tst-spin1.c
tst-spin2.c
tst-spin3.c
tst-stack1.c
tst-stack2.c
tst-stack3.c
tst-stackguard1-static.c
tst-stackguard1.c
tst-stdio1.c
tst-stdio2.c
tst-sysconf.c
tst-tls1.c
tst-tls2.c
tst-tls3.c
tst-tls3mod.c
tst-tls4.c
tst-tls4moda.c
tst-tls4modb.c
tst-tls5.c
tst-tls5.h
tst-tls5mod.c
tst-tls5moda.c
tst-tls5modb.c
tst-tls5modc.c
tst-tls5modd.c
tst-tls5mode.c
tst-tls5modf.c
tst-tls6.sh
tst-tsd1.c
tst-tsd2.c
tst-tsd3.c
tst-tsd4.c
tst-tsd5.c
tst-typesizes.c
tst-umask1.c
tst-unload.c
tst-vfork1.c
tst-vfork1x.c
tst-vfork2.c
tst-vfork2x.c
unwind.c
vars.c
version.c
nptl_db
nscd
nss
po
posix
pwd
resolv
resource
rt
scripts
setjmp
shadow
signal
socket
soft-fp
stdio-common
stdlib
streams
string
sunrpc
sysdeps
sysvipc
termios
time
timezone
wcsmbs
wctype
.cvsignore
BUGS
CANCEL-FCT-WAIVE
CANCEL-FILE-WAIVE
CONFORMANCE
COPYING
COPYING.LIB
ChangeLog
ChangeLog.1
ChangeLog.10
ChangeLog.11
ChangeLog.12
ChangeLog.13
ChangeLog.14
ChangeLog.15
ChangeLog.16
ChangeLog.2
ChangeLog.3
ChangeLog.4
ChangeLog.5
ChangeLog.6
ChangeLog.7
ChangeLog.8
ChangeLog.9
FAQ
FAQ.in
INSTALL
LICENSES
Makeconfig
Makefile
Makefile.in
Makerules
NAMESPACE
NEWS
NOTES
PROJECTS
README
README.libm
README.template
Rules
Versions.def
WUR-REPORT
abi-tags
aclocal.m4
config-name.in
config.h.in
config.make.in
configure
configure.in
cppflags-iterator.mk
extra-lib.mk
extra-modules.mk
o-iterator.mk
shlib-versions
test-skeleton.c
tls.make.c
version.h
Breadcrumbs
glibc
/
nptl
/
sysdeps
/
unix
/
sysv
/
linux
/
i386
/
lowlevellock.h
Blame
Blame
Latest commit
History
History
512 lines (434 loc) · 17.8 KB
Breadcrumbs
glibc
/
nptl
/
sysdeps
/
unix
/
sysv
/
linux
/
i386
/
lowlevellock.h
Top
File metadata and controls
Code
Blame
512 lines (434 loc) · 17.8 KB
Raw
/* Copyright (C) 2002, 2003, 2004, 2006 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #ifndef _LOWLEVELLOCK_H #define _LOWLEVELLOCK_H 1 #include <time.h> #include <sys/param.h> #include <bits/pthreadtypes.h> #ifndef LOCK_INSTR # ifdef UP # define LOCK_INSTR /* nothing */ # else # define LOCK_INSTR "lock;" # endif #endif #define SYS_futex 240 #define FUTEX_WAIT 0 #define FUTEX_WAKE 1 #define FUTEX_LOCK_PI 6 #define FUTEX_UNLOCK_PI 7 #define FUTEX_TRYLOCK_PI 8 /* Initializer for compatibility lock. */ #define LLL_MUTEX_LOCK_INITIALIZER (0) #define LLL_MUTEX_LOCK_INITIALIZER_LOCKED (1) #define LLL_MUTEX_LOCK_INITIALIZER_WAITERS (2) #ifdef PIC # define LLL_EBX_LOAD "xchgl %2, %%ebx\n" # define LLL_EBX_REG "D" #else # define LLL_EBX_LOAD # define LLL_EBX_REG "b" #endif #ifdef I386_USE_SYSENTER # ifdef SHARED # define LLL_ENTER_KERNEL "call *%%gs:%P6\n\t" # else # define LLL_ENTER_KERNEL "call *_dl_sysinfo\n\t" # endif #else # define LLL_ENTER_KERNEL "int $0x80\n\t" #endif /* Delay in spinlock loop. */ #define BUSY_WAIT_NOP asm ("rep; nop") #define lll_futex_wait(futex, val) \ ({ \ int __status; \ register __typeof (val) _val asm ("edx") = (val); \ __asm __volatile (LLL_EBX_LOAD \ LLL_ENTER_KERNEL \ LLL_EBX_LOAD \ : "=a" (__status) \ : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (0), \ "c" (FUTEX_WAIT), "d" (_val), \ "i" (offsetof (tcbhead_t, sysinfo)) \ : "memory"); \ __status; \ }) #define lll_futex_timed_wait(futex, val, timeout) \ ({ \ int __status; \ register __typeof (val) _val asm ("edx") = (val); \ __asm __volatile (LLL_EBX_LOAD \ LLL_ENTER_KERNEL \ LLL_EBX_LOAD \ : "=a" (__status) \ : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout), \ "c" (FUTEX_WAIT), "d" (_val), \ "i" (offsetof (tcbhead_t, sysinfo)) \ : "memory"); \ __status; \ }) #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) /* Does not preserve %eax and %ecx. */ extern int __lll_mutex_lock_wait (int val, int *__futex) __attribute ((regparm (2))) attribute_hidden; /* Does not preserve %eax, %ecx, and %edx. */ extern int __lll_mutex_timedlock_wait (int val, int *__futex, const struct timespec *abstime) __attribute ((regparm (3))) attribute_hidden; /* Preserves all registers but %eax. */ extern int __lll_mutex_unlock_wake (int *__futex) __attribute ((regparm (1))) attribute_hidden; /* NB: in the lll_mutex_trylock macro we simply return the value in %eax after the cmpxchg instruction. In case the operation succeded this value is zero. In case the operation failed, the cmpxchg instruction has loaded the current value of the memory work which is guaranteed to be nonzero. */ #define lll_mutex_trylock(futex) \ ({ int ret; \ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (futex) \ : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ "0" (LLL_MUTEX_LOCK_INITIALIZER) \ : "memory"); \ ret; }) #define lll_robust_mutex_trylock(futex, id) \ ({ int ret; \ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (futex) \ : "r" (id), "m" (futex), \ "0" (LLL_MUTEX_LOCK_INITIALIZER) \ : "memory"); \ ret; }) #define lll_mutex_cond_trylock(futex) \ ({ int ret; \ __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1" \ : "=a" (ret), "=m" (futex) \ : "r" (LLL_MUTEX_LOCK_INITIALIZER_WAITERS), \ "m" (futex), "0" (LLL_MUTEX_LOCK_INITIALIZER) \ : "memory"); \ ret; }) #define lll_mutex_lock(futex) \ (void) ({ int ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ "jnz _L_mutex_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_lock_%=,@function\n" \ "_L_mutex_lock_%=:\n\t" \ "leal %2, %%ecx\n\t" \ "call __lll_mutex_lock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \ ".previous\n" \ "1:" \ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (1), "m" (futex) \ : "memory"); }) #define lll_robust_mutex_lock(futex, id) \ ({ int result, ignore; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ "jnz _L_mutex_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_lock_%=,@function\n" \ "_L_mutex_lock_%=:\n\t" \ "leal %2, %%ecx\n\t" \ "call __lll_robust_mutex_lock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \ ".previous\n" \ "1:" \ : "=a" (result), "=c" (ignore), "=m" (futex) \ : "0" (0), "1" (id), "m" (futex) \ : "memory"); \ result; }) /* Special version of lll_mutex_lock which causes the unlock function to always wakeup waiters. */ #define lll_mutex_cond_lock(futex) \ (void) ({ int ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ "jnz _L_mutex_cond_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_cond_lock_%=,@function\n" \ "_L_mutex_cond_lock_%=:\n\t" \ "leal %2, %%ecx\n\t" \ "call __lll_mutex_lock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n" \ ".previous\n" \ "1:" \ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (2), "m" (futex) \ : "memory"); }) #define lll_robust_mutex_cond_lock(futex, id) \ ({ int result, ignore; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t" \ "jnz _L_mutex_cond_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_cond_lock_%=,@function\n" \ "_L_mutex_cond_lock_%=:\n\t" \ "leal %2, %%ecx\n\t" \ "call __lll_robust_mutex_lock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_cond_lock_%=,.-_L_mutex_cond_lock_%=\n"\ ".previous\n" \ "1:" \ : "=a" (result), "=c" (ignore), "=m" (futex) \ : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex) \ : "memory"); \ result; }) #define lll_mutex_timedlock(futex, timeout) \ ({ int result, ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ "jnz _L_mutex_timedlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_timedlock_%=,@function\n" \ "_L_mutex_timedlock_%=:\n\t" \ "leal %3, %%ecx\n\t" \ "movl %7, %%edx\n\t" \ "call __lll_mutex_timedlock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\ ".previous\n" \ "1:" \ : "=a" (result), "=c" (ignore1), "=&d" (ignore2), \ "=m" (futex) \ : "0" (0), "1" (1), "m" (futex), "m" (timeout) \ : "memory"); \ result; }) #define lll_robust_mutex_timedlock(futex, timeout, id) \ ({ int result, ignore1, ignore2; \ __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t" \ "jnz _L_mutex_timedlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_timedlock_%=,@function\n" \ "_L_mutex_timedlock_%=:\n\t" \ "leal %3, %%ecx\n\t" \ "movl %7, %%edx\n\t" \ "call __lll_robust_mutex_timedlock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_timedlock_%=,.-_L_mutex_timedlock_%=\n"\ ".previous\n" \ "1:" \ : "=a" (result), "=c" (ignore1), "=&d" (ignore2), \ "=m" (futex) \ : "0" (0), "1" (id), "m" (futex), "m" (timeout) \ : "memory"); \ result; }) #define lll_mutex_unlock(futex) \ (void) ({ int ignore; \ __asm __volatile (LOCK_INSTR "subl $1, %0\n\t" \ "jne _L_mutex_unlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_unlock_%=,@function\n" \ "_L_mutex_unlock_%=:\n\t" \ "leal %0, %%eax\n\t" \ "call __lll_mutex_unlock_wake\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ ".previous\n" \ "1:" \ : "=m" (futex), "=&a" (ignore) \ : "m" (futex) \ : "memory"); }) #define lll_robust_mutex_unlock(futex) \ (void) ({ int ignore; \ __asm __volatile (LOCK_INSTR "andl %2, %0\n\t" \ "jne _L_mutex_unlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_unlock_%=,@function\n" \ "_L_mutex_unlock_%=:\n\t" \ "leal %0, %%eax\n\t" \ "call __lll_mutex_unlock_wake\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ ".previous\n" \ "1:" \ : "=m" (futex), "=&a" (ignore) \ : "i" (FUTEX_WAITERS), "m" (futex) \ : "memory"); }) #define lll_robust_mutex_dead(futex) \ (void) ({ int __ignore; \ register int _nr asm ("edx") = 1; \ __asm __volatile (LOCK_INSTR "orl %5, (%2)\n\t" \ LLL_EBX_LOAD \ LLL_ENTER_KERNEL \ LLL_EBX_LOAD \ : "=a" (__ignore) \ : "0" (SYS_futex), LLL_EBX_REG (&(futex)), \ "c" (FUTEX_WAKE), "d" (_nr), \ "i" (FUTEX_OWNER_DIED), \ "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) /* We have a separate internal lock implementation which is not tied to binary compatibility. */ /* Type for lock object. */ typedef int lll_lock_t; /* Initializers for lock. */ #define LLL_LOCK_INITIALIZER (0) #define LLL_LOCK_INITIALIZER_LOCKED (1) extern int __lll_lock_wait (int val, int *__futex) __attribute ((regparm (2))) attribute_hidden; extern int __lll_unlock_wake (int *__futex) __attribute ((regparm (1))) attribute_hidden; extern int lll_unlock_wake_cb (int *__futex) attribute_hidden; /* The states of a lock are: 0 - untaken 1 - taken by one user 2 - taken by more users */ #if defined NOT_IN_libc || defined UP # define lll_trylock(futex) lll_mutex_trylock (futex) # define lll_lock(futex) lll_mutex_lock (futex) # define lll_unlock(futex) lll_mutex_unlock (futex) #else /* Special versions of the macros for use in libc itself. They avoid the lock prefix when the thread library is not used. XXX In future we might even want to avoid it on UP machines. */ # include <tls.h> # define lll_trylock(futex) \ ({ unsigned char ret; \ __asm __volatile ("cmpl $0, %%gs:%P5\n\t" \ "je 0f\n\t" \ "lock\n" \ "0:\tcmpxchgl %2, %1; setne %0" \ : "=a" (ret), "=m" (futex) \ : "r" (LLL_MUTEX_LOCK_INITIALIZER_LOCKED), "m" (futex),\ "0" (LLL_MUTEX_LOCK_INITIALIZER), \ "i" (offsetof (tcbhead_t, multiple_threads)) \ : "memory"); \ ret; }) # define lll_lock(futex) \ (void) ({ int ignore1, ignore2; \ __asm __volatile ("cmpl $0, %%gs:%P6\n\t" \ "je 0f\n\t" \ "lock\n" \ "0:\tcmpxchgl %1, %2\n\t" \ "jnz _L_mutex_lock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_lock_%=,@function\n" \ "_L_mutex_lock_%=:\n\t" \ "leal %2, %%ecx\n\t" \ "call __lll_mutex_lock_wait\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_lock_%=,.-_L_mutex_lock_%=\n" \ ".previous\n" \ "1:" \ : "=a" (ignore1), "=c" (ignore2), "=m" (futex) \ : "0" (0), "1" (1), "m" (futex), \ "i" (offsetof (tcbhead_t, multiple_threads)) \ : "memory"); }) # define lll_unlock(futex) \ (void) ({ int ignore; \ __asm __volatile ("cmpl $0, %%gs:%P3\n\t" \ "je 0f\n\t" \ "lock\n" \ "0:\tsubl $1,%0\n\t" \ "jne _L_mutex_unlock_%=\n\t" \ ".subsection 1\n\t" \ ".type _L_mutex_unlock_%=,@function\n" \ "_L_mutex_unlock_%=:\n\t" \ "leal %0, %%eax\n\t" \ "call __lll_mutex_unlock_wake\n\t" \ "jmp 1f\n\t" \ ".size _L_mutex_unlock_%=,.-_L_mutex_unlock_%=\n" \ ".previous\n" \ "1:" \ : "=m" (futex), "=&a" (ignore) \ : "m" (futex), \ "i" (offsetof (tcbhead_t, multiple_threads)) \ : "memory"); }) #endif #define lll_islocked(futex) \ (futex != LLL_LOCK_INITIALIZER) /* The kernel notifies a process with uses CLONE_CLEARTID via futex wakeup when the clone terminates. The memory location contains the thread ID while the clone is running and is reset to zero afterwards. The macro parameter must not have any side effect. */ #define lll_wait_tid(tid) \ do { \ int __ignore; \ register __typeof (tid) _tid asm ("edx") = (tid); \ if (_tid != 0) \ __asm __volatile (LLL_EBX_LOAD \ "1:\tmovl %1, %%eax\n\t" \ LLL_ENTER_KERNEL \ "cmpl $0, (%%ebx)\n\t" \ "jne 1b\n\t" \ LLL_EBX_LOAD \ : "=&a" (__ignore) \ : "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0), \ "c" (FUTEX_WAIT), "d" (_tid), \ "i" (offsetof (tcbhead_t, sysinfo)) \ : "memory"); \ } while (0) extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime) __attribute__ ((regparm (2))) attribute_hidden; #define lll_timedwait_tid(tid, abstime) \ ({ \ int __result = 0; \ if (tid != 0) \ { \ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000) \ __result = EINVAL; \ else \ __result = __lll_timedwait_tid (&tid, abstime); \ } \ __result; }) /* Conditional variable handling. */ extern void __lll_cond_wait (pthread_cond_t *cond) __attribute ((regparm (1))) attribute_hidden; extern int __lll_cond_timedwait (pthread_cond_t *cond, const struct timespec *abstime) __attribute ((regparm (2))) attribute_hidden; extern void __lll_cond_wake (pthread_cond_t *cond) __attribute ((regparm (1))) attribute_hidden; extern void __lll_cond_broadcast (pthread_cond_t *cond) __attribute ((regparm (1))) attribute_hidden; #define lll_cond_wait(cond) \ __lll_cond_wait (cond) #define lll_cond_timedwait(cond, abstime) \ __lll_cond_timedwait (cond, abstime) #define lll_cond_wake(cond) \ __lll_cond_wake (cond) #define lll_cond_broadcast(cond) \ __lll_cond_broadcast (cond) #endif /* lowlevellock.h */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
You can’t perform that action at this time.