Back to index

glibc  2.9
lowlevellock.h
Go to the documentation of this file.
00001 /* Copyright (C) 2002, 2003, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
00002    This file is part of the GNU C Library.
00003    Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
00004 
00005    The GNU C Library is free software; you can redistribute it and/or
00006    modify it under the terms of the GNU Lesser General Public
00007    License as published by the Free Software Foundation; either
00008    version 2.1 of the License, or (at your option) any later version.
00009 
00010    The GNU C Library is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY; without even the implied warranty of
00012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013    Lesser General Public License for more details.
00014 
00015    You should have received a copy of the GNU Lesser General Public
00016    License along with the GNU C Library; if not, write to the Free
00017    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00018    02111-1307 USA.  */
00019 
00020 #ifndef _LOWLEVELLOCK_H
00021 #define _LOWLEVELLOCK_H     1
00022 
00023 #ifndef __ASSEMBLER__
00024 # include <time.h>
00025 # include <sys/param.h>
00026 # include <bits/pthreadtypes.h>
00027 # include <kernel-features.h>
00028 # include <tcb-offsets.h>
00029 
00030 # ifndef LOCK_INSTR
00031 #  ifdef UP
00032 #   define LOCK_INSTR       /* nothing */
00033 #  else
00034 #   define LOCK_INSTR "lock;"
00035 #  endif
00036 # endif
00037 #else
00038 # ifndef LOCK
00039 #  ifdef UP
00040 #   define LOCK
00041 #  else
00042 #   define LOCK lock
00043 #  endif
00044 # endif
00045 #endif
00046 
00047 #define SYS_futex           240
00048 #define FUTEX_WAIT          0
00049 #define FUTEX_WAKE          1
00050 #define FUTEX_CMP_REQUEUE   4
00051 #define FUTEX_WAKE_OP              5
00052 #define FUTEX_LOCK_PI              6
00053 #define FUTEX_UNLOCK_PI            7
00054 #define FUTEX_TRYLOCK_PI    8
00055 #define FUTEX_PRIVATE_FLAG  128
00056 
00057 #define FUTEX_OP_CLEAR_WAKE_IF_GT_ONE     ((4 << 24) | 1)
00058 
00059 /* Values for 'private' parameter of locking macros.  Yes, the
00060    definition seems to be backwards.  But it is not.  The bit will be
00061    reversed before passing to the system call.  */
00062 #define LLL_PRIVATE  0
00063 #define LLL_SHARED   FUTEX_PRIVATE_FLAG
00064 
00065 
00066 #if !defined NOT_IN_libc || defined IS_IN_rtld
00067 /* In libc.so or ld.so all futexes are private.  */
00068 # ifdef __ASSUME_PRIVATE_FUTEX
00069 #  define __lll_private_flag(fl, private) \
00070   ((fl) | FUTEX_PRIVATE_FLAG)
00071 # else
00072 #  define __lll_private_flag(fl, private) \
00073   ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))
00074 # endif
00075 #else
00076 # ifdef __ASSUME_PRIVATE_FUTEX
00077 #  define __lll_private_flag(fl, private) \
00078   (((fl) | FUTEX_PRIVATE_FLAG) ^ (private))
00079 # else
00080 #  define __lll_private_flag(fl, private) \
00081   (__builtin_constant_p (private)                                    \
00082    ? ((private) == 0                                                 \
00083       ? ((fl) | THREAD_GETMEM (THREAD_SELF, header.private_futex))          \
00084       : (fl))                                                        \
00085    : ({ unsigned int __fl = ((private) ^ FUTEX_PRIVATE_FLAG);               \
00086        asm ("andl %%gs:%P1, %0" : "+r" (__fl)                               \
00087             : "i" (offsetof (struct pthread, header.private_futex)));       \
00088        __fl | (fl); }))
00089 # endif             
00090 #endif
00091 
00092 #ifndef __ASSEMBLER__
00093 
00094 /* Initializer for compatibility lock.  */
00095 #define LLL_LOCK_INITIALIZER              (0)
00096 #define LLL_LOCK_INITIALIZER_LOCKED       (1)
00097 #define LLL_LOCK_INITIALIZER_WAITERS      (2)
00098 
00099 
00100 #ifdef PIC
00101 # define LLL_EBX_LOAD       "xchgl %2, %%ebx\n"
00102 # define LLL_EBX_REG "D"
00103 #else
00104 # define LLL_EBX_LOAD
00105 # define LLL_EBX_REG "b"
00106 #endif
00107 
00108 #ifdef I386_USE_SYSENTER
00109 # ifdef SHARED
00110 #  define LLL_ENTER_KERNEL  "call *%%gs:%P6\n\t"
00111 # else
00112 #  define LLL_ENTER_KERNEL  "call *_dl_sysinfo\n\t"
00113 # endif
00114 #else
00115 # define LLL_ENTER_KERNEL   "int $0x80\n\t"
00116 #endif
00117 
00118 /* Delay in spinlock loop.  */
00119 #define BUSY_WAIT_NOP       asm ("rep; nop")
00120 
00121 
00122 #define LLL_STUB_UNWIND_INFO_START \
00123        ".section     .eh_frame,\"a\",@progbits\n"              \
00124 "5:\t" ".long 7f-6f  # Length of Common Information Entry\n"   \
00125 "6:\t" ".long 0x0    # CIE Identifier Tag\n\t"          \
00126        ".byte 0x1    # CIE Version\n\t"                 \
00127        ".ascii \"zR\\0\"    # CIE Augmentation\n\t"            \
00128        ".uleb128 0x1 # CIE Code Alignment Factor\n\t"   \
00129        ".sleb128 -4  # CIE Data Alignment Factor\n\t"   \
00130        ".byte 0x8    # CIE RA Column\n\t"               \
00131        ".uleb128 0x1 # Augmentation size\n\t"           \
00132        ".byte 0x1b   # FDE Encoding (pcrel sdata4)\n\t" \
00133        ".byte 0xc    # DW_CFA_def_cfa\n\t"                     \
00134        ".uleb128 0x4\n\t"                               \
00135        ".uleb128 0x0\n\t"                               \
00136        ".align 4\n"                                     \
00137 "7:\t" ".long 17f-8f # FDE Length\n"                           \
00138 "8:\t" ".long 8b-5b  # FDE CIE offset\n\t"                     \
00139        ".long 1b-.   # FDE initial location\n\t"        \
00140        ".long 4b-1b  # FDE address range\n\t"           \
00141        ".uleb128 0x0 # Augmentation size\n\t"           \
00142        ".byte 0x16   # DW_CFA_val_expression\n\t"              \
00143        ".uleb128 0x8\n\t"                               \
00144        ".uleb128 10f-9f\n"                              \
00145 "9:\t" ".byte 0x78   # DW_OP_breg8\n\t"                 \
00146        ".sleb128 3b-1b\n"
00147 #define LLL_STUB_UNWIND_INFO_END \
00148        ".byte 0x16   # DW_CFA_val_expression\n\t"              \
00149        ".uleb128 0x8\n\t"                               \
00150        ".uleb128 12f-11f\n"                             \
00151 "11:\t"       ".byte 0x78   # DW_OP_breg8\n\t"                 \
00152        ".sleb128 3b-2b\n"                               \
00153 "12:\t"       ".byte 0x40 + (3b-2b-1) # DW_CFA_advance_loc\n\t"       \
00154        ".byte 0x16   # DW_CFA_val_expression\n\t"              \
00155        ".uleb128 0x8\n\t"                               \
00156        ".uleb128 16f-13f\n"                             \
00157 "13:\t"       ".byte 0x78   # DW_OP_breg8\n\t"                 \
00158        ".sleb128 15f-14f\n\t"                                  \
00159        ".byte 0x0d   # DW_OP_const4s\n"                 \
00160 "14:\t"       ".4byte       3b-.\n\t"                                 \
00161        ".byte 0x1c   # DW_OP_minus\n\t"                 \
00162        ".byte 0x0d   # DW_OP_const4s\n"                 \
00163 "15:\t"       ".4byte       18f-.\n\t"                                \
00164        ".byte 0x22   # DW_OP_plus\n"                           \
00165 "16:\t"       ".align 4\n"                                     \
00166 "17:\t"       ".previous\n"
00167 
00168 /* Unwind info for
00169    1: lea ..., ...
00170    2: call ...
00171    3: jmp 18f
00172    4:
00173    snippet.  */
00174 #define LLL_STUB_UNWIND_INFO_3 \
00175 LLL_STUB_UNWIND_INFO_START                              \
00176 "10:\t"       ".byte 0x40 + (2b-1b) # DW_CFA_advance_loc\n\t"  \
00177 LLL_STUB_UNWIND_INFO_END
00178 
00179 /* Unwind info for
00180    1: lea ..., ...
00181    0: movl ..., ...
00182    2: call ...
00183    3: jmp 18f
00184    4:
00185    snippet.  */
00186 #define LLL_STUB_UNWIND_INFO_4 \
00187 LLL_STUB_UNWIND_INFO_START                              \
00188 "10:\t"       ".byte 0x40 + (0b-1b) # DW_CFA_advance_loc\n\t"  \
00189        ".byte 0x16   # DW_CFA_val_expression\n\t"              \
00190        ".uleb128 0x8\n\t"                               \
00191        ".uleb128 20f-19f\n"                             \
00192 "19:\t"       ".byte 0x78   # DW_OP_breg8\n\t"                 \
00193        ".sleb128 3b-0b\n"                               \
00194 "20:\t"       ".byte 0x40 + (2b-0b) # DW_CFA_advance_loc\n\t"  \
00195 LLL_STUB_UNWIND_INFO_END
00196 
00197 
00198 #define lll_futex_wait(futex, val, private) \
00199   lll_futex_timed_wait (futex, val, NULL, private)
00200 
00201 
00202 #define lll_futex_timed_wait(futex, val, timeout, private) \
00203   ({                                                                 \
00204     int __status;                                                    \
00205     register __typeof (val) _val asm ("edx") = (val);                       \
00206     __asm __volatile (LLL_EBX_LOAD                                   \
00207                     LLL_ENTER_KERNEL                                        \
00208                     LLL_EBX_LOAD                                     \
00209                     : "=a" (__status)                                       \
00210                     : "0" (SYS_futex), LLL_EBX_REG (futex), "S" (timeout),  \
00211                      "c" (__lll_private_flag (FUTEX_WAIT, private)),        \
00212                      "d" (_val), "i" (offsetof (tcbhead_t, sysinfo))        \
00213                     : "memory");                                     \
00214     __status;                                                        \
00215   })
00216 
00217 
00218 #define lll_futex_wake(futex, nr, private) \
00219   do {                                                               \
00220     int __ignore;                                                    \
00221     register __typeof (nr) _nr asm ("edx") = (nr);                          \
00222     __asm __volatile (LLL_EBX_LOAD                                   \
00223                     LLL_ENTER_KERNEL                                        \
00224                     LLL_EBX_LOAD                                     \
00225                     : "=a" (__ignore)                                       \
00226                     : "0" (SYS_futex), LLL_EBX_REG (futex),                 \
00227                      "c" (__lll_private_flag (FUTEX_WAKE, private)),        \
00228                      "d" (_nr),                                      \
00229                      "i" (0) /* phony, to align next arg's number */,      \
00230                      "i" (offsetof (tcbhead_t, sysinfo)));                  \
00231   } while (0)
00232 
00233 
00234 /* NB: in the lll_trylock macro we simply return the value in %eax
00235    after the cmpxchg instruction.  In case the operation succeded this
00236    value is zero.  In case the operation failed, the cmpxchg instruction
00237    has loaded the current value of the memory work which is guaranteed
00238    to be nonzero.  */
00239 #if defined NOT_IN_libc || defined UP
00240 # define __lll_trylock_asm LOCK_INSTR "cmpxchgl %2, %1"
00241 #else
00242 # define __lll_trylock_asm "cmpl $0, %%gs:%P5\n\t" \
00243                         "je 0f\n\t"                                         \
00244                         "lock\n"                                     \
00245                         "0:\tcmpxchgl %2, %1"
00246 #endif
00247 
00248 #define lll_trylock(futex) \
00249   ({ int ret;                                                        \
00250      __asm __volatile (__lll_trylock_asm                             \
00251                      : "=a" (ret), "=m" (futex)                      \
00252                      : "r" (LLL_LOCK_INITIALIZER_LOCKED), "m" (futex),      \
00253                       "0" (LLL_LOCK_INITIALIZER),                           \
00254                       "i" (MULTIPLE_THREADS_OFFSET)                         \
00255                      : "memory");                                    \
00256      ret; })
00257 
00258 #define lll_robust_trylock(futex, id) \
00259   ({ int ret;                                                        \
00260      __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"                         \
00261                      : "=a" (ret), "=m" (futex)                      \
00262                      : "r" (id), "m" (futex),                               \
00263                       "0" (LLL_LOCK_INITIALIZER)                     \
00264                      : "memory");                                    \
00265      ret; })
00266 
00267 
00268 #define lll_cond_trylock(futex) \
00269   ({ int ret;                                                        \
00270      __asm __volatile (LOCK_INSTR "cmpxchgl %2, %1"                         \
00271                      : "=a" (ret), "=m" (futex)                      \
00272                      : "r" (LLL_LOCK_INITIALIZER_WAITERS),                  \
00273                       "m" (futex), "0" (LLL_LOCK_INITIALIZER)        \
00274                      : "memory");                                    \
00275      ret; })
00276 
00277 #if defined NOT_IN_libc || defined UP
00278 # define __lll_lock_asm_start LOCK_INSTR "cmpxchgl %1, %2\n\t"
00279 #else
00280 # define __lll_lock_asm_start "cmpl $0, %%gs:%P6\n\t"                       \
00281                            "je 0f\n\t"                               \
00282                            "lock\n"                                         \
00283                            "0:\tcmpxchgl %1, %2\n\t"
00284 #endif
00285 
00286 #define lll_lock(futex, private) \
00287   (void)                                                             \
00288     ({ int ignore1, ignore2;                                                \
00289        if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)             \
00290         __asm __volatile (__lll_lock_asm_start                              \
00291                         "jnz _L_lock_%=\n\t"                                \
00292                         ".subsection 1\n\t"                                 \
00293                         ".type _L_lock_%=,@function\n"               \
00294                         "_L_lock_%=:\n"                              \
00295                         "1:\tleal %2, %%ecx\n"                       \
00296                         "2:\tcall __lll_lock_wait_private\n"         \
00297                         "3:\tjmp 18f\n"                              \
00298                         "4:\t.size _L_lock_%=, 4b-1b\n\t"                   \
00299                         ".previous\n"                                \
00300                         LLL_STUB_UNWIND_INFO_3                       \
00301                         "18:"                                        \
00302                         : "=a" (ignore1), "=c" (ignore2), "=m" (futex)     \
00303                         : "0" (0), "1" (1), "m" (futex),                    \
00304                           "i" (MULTIPLE_THREADS_OFFSET)              \
00305                         : "memory");                                        \
00306        else                                                          \
00307         {                                                            \
00308           int ignore3;                                                      \
00309           __asm __volatile (__lll_lock_asm_start                     \
00310                           "jnz _L_lock_%=\n\t"                       \
00311                           ".subsection 1\n\t"                        \
00312                           ".type _L_lock_%=,@function\n"                    \
00313                           "_L_lock_%=:\n"                            \
00314                           "1:\tleal %2, %%edx\n"                     \
00315                           "0:\tmovl %8, %%ecx\n"                     \
00316                           "2:\tcall __lll_lock_wait\n"               \
00317                           "3:\tjmp 18f\n"                            \
00318                           "4:\t.size _L_lock_%=, 4b-1b\n\t"                 \
00319                           ".previous\n"                              \
00320                           LLL_STUB_UNWIND_INFO_4                     \
00321                           "18:"                                      \
00322                           : "=a" (ignore1), "=c" (ignore2),                 \
00323                             "=m" (futex), "=&d" (ignore3)                   \
00324                           : "1" (1), "m" (futex),                           \
00325                             "i" (MULTIPLE_THREADS_OFFSET), "0" (0),         \
00326                             "g" ((int) (private))                           \
00327                           : "memory");                               \
00328         }                                                            \
00329     })
00330 
00331 #define lll_robust_lock(futex, id, private) \
00332   ({ int result, ignore1, ignore2;                                   \
00333      __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"                     \
00334                      "jnz _L_robust_lock_%=\n\t"                     \
00335                      ".subsection 1\n\t"                             \
00336                      ".type _L_robust_lock_%=,@function\n"                  \
00337                      "_L_robust_lock_%=:\n"                                 \
00338                      "1:\tleal %2, %%edx\n"                                 \
00339                      "0:\tmovl %7, %%ecx\n"                                 \
00340                      "2:\tcall __lll_robust_lock_wait\n"                    \
00341                      "3:\tjmp 18f\n"                                        \
00342                      "4:\t.size _L_robust_lock_%=, 4b-1b\n\t"               \
00343                      ".previous\n"                                   \
00344                      LLL_STUB_UNWIND_INFO_4                                 \
00345                      "18:"                                           \
00346                      : "=a" (result), "=c" (ignore1), "=m" (futex),         \
00347                       "=&d" (ignore2)                                \
00348                      : "0" (0), "1" (id), "m" (futex), "g" ((int) (private))\
00349                      : "memory");                                    \
00350      result; })
00351 
00352 
00353 /* Special version of lll_lock which causes the unlock function to
00354    always wakeup waiters.  */
00355 #define lll_cond_lock(futex, private) \
00356   (void)                                                             \
00357     ({ int ignore1, ignore2, ignore3;                                       \
00358        __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"                   \
00359                       "jnz _L_cond_lock_%=\n\t"                      \
00360                       ".subsection 1\n\t"                            \
00361                       ".type _L_cond_lock_%=,@function\n"                   \
00362                       "_L_cond_lock_%=:\n"                                  \
00363                       "1:\tleal %2, %%edx\n"                                \
00364                       "0:\tmovl %7, %%ecx\n"                                \
00365                       "2:\tcall __lll_lock_wait\n"                          \
00366                       "3:\tjmp 18f\n"                                \
00367                       "4:\t.size _L_cond_lock_%=, 4b-1b\n\t"                \
00368                       ".previous\n"                                         \
00369                       LLL_STUB_UNWIND_INFO_4                                \
00370                       "18:"                                          \
00371                       : "=a" (ignore1), "=c" (ignore2), "=m" (futex),      \
00372                         "=&d" (ignore3)                              \
00373                       : "0" (0), "1" (2), "m" (futex), "g" ((int) (private))\
00374                       : "memory");                                   \
00375     })
00376 
00377 
00378 #define lll_robust_cond_lock(futex, id, private) \
00379   ({ int result, ignore1, ignore2;                                   \
00380      __asm __volatile (LOCK_INSTR "cmpxchgl %1, %2\n\t"                     \
00381                      "jnz _L_robust_cond_lock_%=\n\t"                       \
00382                      ".subsection 1\n\t"                             \
00383                      ".type _L_robust_cond_lock_%=,@function\n"             \
00384                      "_L_robust_cond_lock_%=:\n"                     \
00385                      "1:\tleal %2, %%edx\n"                                 \
00386                      "0:\tmovl %7, %%ecx\n"                                 \
00387                      "2:\tcall __lll_robust_lock_wait\n"                    \
00388                      "3:\tjmp 18f\n"                                        \
00389                      "4:\t.size _L_robust_cond_lock_%=, 4b-1b\n\t"          \
00390                      ".previous\n"                                   \
00391                      LLL_STUB_UNWIND_INFO_4                                 \
00392                      "18:"                                           \
00393                      : "=a" (result), "=c" (ignore1), "=m" (futex),         \
00394                       "=&d" (ignore2)                                \
00395                      : "0" (0), "1" (id | FUTEX_WAITERS), "m" (futex),      \
00396                       "g" ((int) (private))                                 \
00397                      : "memory");                                    \
00398      result; })
00399 
00400 
00401 #define lll_timedlock(futex, timeout, private) \
00402   ({ int result, ignore1, ignore2, ignore3;                                 \
00403      __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"                     \
00404                      "jnz _L_timedlock_%=\n\t"                       \
00405                      ".subsection 1\n\t"                             \
00406                      ".type _L_timedlock_%=,@function\n"                    \
00407                      "_L_timedlock_%=:\n"                            \
00408                      "1:\tleal %3, %%ecx\n"                                 \
00409                      "0:\tmovl %8, %%edx\n"                                 \
00410                      "2:\tcall __lll_timedlock_wait\n"               \
00411                      "3:\tjmp 18f\n"                                        \
00412                      "4:\t.size _L_timedlock_%=, 4b-1b\n\t"                 \
00413                      ".previous\n"                                   \
00414                      LLL_STUB_UNWIND_INFO_4                                 \
00415                      "18:"                                           \
00416                      : "=a" (result), "=c" (ignore1), "=&d" (ignore2),      \
00417                       "=m" (futex), "=S" (ignore3)                          \
00418                      : "0" (0), "1" (1), "m" (futex), "m" (timeout),        \
00419                       "4" ((int) (private))                                 \
00420                      : "memory");                                    \
00421      result; })
00422 
00423 
00424 #define lll_robust_timedlock(futex, timeout, id, private) \
00425   ({ int result, ignore1, ignore2, ignore3;                                 \
00426      __asm __volatile (LOCK_INSTR "cmpxchgl %1, %3\n\t"                     \
00427                      "jnz _L_robust_timedlock_%=\n\t"                       \
00428                      ".subsection 1\n\t"                             \
00429                      ".type _L_robust_timedlock_%=,@function\n"             \
00430                      "_L_robust_timedlock_%=:\n"                     \
00431                      "1:\tleal %3, %%ecx\n"                                 \
00432                      "0:\tmovl %8, %%edx\n"                                 \
00433                      "2:\tcall __lll_robust_timedlock_wait\n"               \
00434                      "3:\tjmp 18f\n"                                        \
00435                      "4:\t.size _L_robust_timedlock_%=, 4b-1b\n\t"          \
00436                      ".previous\n"                                   \
00437                      LLL_STUB_UNWIND_INFO_4                                 \
00438                      "18:"                                           \
00439                      : "=a" (result), "=c" (ignore1), "=&d" (ignore2),      \
00440                       "=m" (futex), "=S" (ignore3)                          \
00441                      : "0" (0), "1" (id), "m" (futex), "m" (timeout),       \
00442                       "4" ((int) (private))                                 \
00443                      : "memory");                                    \
00444      result; })
00445 
00446 #if defined NOT_IN_libc || defined UP
00447 # define __lll_unlock_asm LOCK_INSTR "subl $1, %0\n\t"
00448 #else
00449 # define __lll_unlock_asm "cmpl $0, %%gs:%P3\n\t"                           \
00450                        "je 0f\n\t"                                   \
00451                        "lock\n"                                      \
00452                        "0:\tsubl $1,%0\n\t"
00453 #endif
00454 
00455 #define lll_unlock(futex, private) \
00456   (void)                                                             \
00457     ({ int ignore;                                                   \
00458        if (__builtin_constant_p (private) && (private) == LLL_PRIVATE)             \
00459         __asm __volatile (__lll_unlock_asm                                  \
00460                         "jne _L_unlock_%=\n\t"                       \
00461                         ".subsection 1\n\t"                                 \
00462                         ".type _L_unlock_%=,@function\n"                    \
00463                         "_L_unlock_%=:\n"                            \
00464                         "1:\tleal %0, %%eax\n"                       \
00465                         "2:\tcall __lll_unlock_wake_private\n"       \
00466                         "3:\tjmp 18f\n"                              \
00467                         "4:\t.size _L_unlock_%=, 4b-1b\n\t"                 \
00468                         ".previous\n"                                \
00469                         LLL_STUB_UNWIND_INFO_3                       \
00470                         "18:"                                        \
00471                         : "=m" (futex), "=&a" (ignore)               \
00472                         : "m" (futex), "i" (MULTIPLE_THREADS_OFFSET)        \
00473                         : "memory");                                        \
00474        else                                                          \
00475         {                                                            \
00476           int ignore2;                                                      \
00477           __asm __volatile (__lll_unlock_asm                                \
00478                           "jne _L_unlock_%=\n\t"                     \
00479                           ".subsection 1\n\t"                        \
00480                           ".type _L_unlock_%=,@function\n"                  \
00481                           "_L_unlock_%=:\n"                                 \
00482                           "1:\tleal %0, %%eax\n"                     \
00483                           "0:\tmovl %5, %%ecx\n"                     \
00484                           "2:\tcall __lll_unlock_wake\n"                    \
00485                           "3:\tjmp 18f\n"                            \
00486                           "4:\t.size _L_unlock_%=, 4b-1b\n\t"        \
00487                           ".previous\n"                              \
00488                           LLL_STUB_UNWIND_INFO_4                     \
00489                           "18:"                                      \
00490                           : "=m" (futex), "=&a" (ignore), "=&c" (ignore2)  \
00491                           : "i" (MULTIPLE_THREADS_OFFSET), "m" (futex),    \
00492                             "g" ((int) (private))                           \
00493                           : "memory");                               \
00494         }                                                            \
00495     })
00496 
00497 #define lll_robust_unlock(futex, private) \
00498   (void)                                                             \
00499     ({ int ignore, ignore2;                                          \
00500        __asm __volatile (LOCK_INSTR "andl %3, %0\n\t"                       \
00501                       "jne _L_robust_unlock_%=\n\t"                         \
00502                       ".subsection 1\n\t"                            \
00503                       ".type _L_robust_unlock_%=,@function\n"        \
00504                       "_L_robust_unlock_%=:\n\t"                     \
00505                       "1:\tleal %0, %%eax\n"                                \
00506                       "0:\tmovl %5, %%ecx\n"                                \
00507                       "2:\tcall __lll_unlock_wake\n"                        \
00508                       "3:\tjmp 18f\n"                                \
00509                       "4:\t.size _L_robust_unlock_%=, 4b-1b\n\t"            \
00510                       ".previous\n"                                         \
00511                       LLL_STUB_UNWIND_INFO_4                                \
00512                       "18:"                                          \
00513                       : "=m" (futex), "=&a" (ignore), "=&c" (ignore2)      \
00514                       : "i" (FUTEX_WAITERS), "m" (futex),                   \
00515                         "g" ((int) (private))                        \
00516                       : "memory");                                   \
00517     })
00518 
00519 
00520 #define lll_robust_dead(futex, private) \
00521   (void)                                                             \
00522     ({ int __ignore;                                                 \
00523        register int _nr asm ("edx") = 1;                             \
00524        __asm __volatile (LOCK_INSTR "orl %5, (%2)\n\t"                      \
00525                       LLL_EBX_LOAD                                   \
00526                       LLL_ENTER_KERNEL                               \
00527                       LLL_EBX_LOAD                                   \
00528                       : "=a" (__ignore)                              \
00529                       : "0" (SYS_futex), LLL_EBX_REG (&(futex)),            \
00530                         "c" (__lll_private_flag (FUTEX_WAKE, private)),    \
00531                         "d" (_nr), "i" (FUTEX_OWNER_DIED),                  \
00532                         "i" (offsetof (tcbhead_t, sysinfo)));        \
00533     })
00534 
00535 #define lll_islocked(futex) \
00536   (futex != LLL_LOCK_INITIALIZER)
00537 
00538 /* The kernel notifies a process with uses CLONE_CLEARTID via futex
00539    wakeup when the clone terminates.  The memory location contains the
00540    thread ID while the clone is running and is reset to zero
00541    afterwards.
00542 
00543    The macro parameter must not have any side effect.  */
00544 #define lll_wait_tid(tid) \
00545   do {                                                               \
00546     int __ignore;                                                    \
00547     register __typeof (tid) _tid asm ("edx") = (tid);                       \
00548     if (_tid != 0)                                                   \
00549       __asm __volatile (LLL_EBX_LOAD                                        \
00550                      "1:\tmovl %1, %%eax\n\t"                        \
00551                      LLL_ENTER_KERNEL                                \
00552                      "cmpl $0, (%%ebx)\n\t"                                 \
00553                      "jne 1b\n\t"                                    \
00554                      LLL_EBX_LOAD                                    \
00555                      : "=&a" (__ignore)                              \
00556                      : "i" (SYS_futex), LLL_EBX_REG (&tid), "S" (0),        \
00557                        "c" (FUTEX_WAIT), "d" (_tid),                        \
00558                        "i" (offsetof (tcbhead_t, sysinfo))                  \
00559                      : "memory");                                    \
00560   } while (0)
00561 
00562 extern int __lll_timedwait_tid (int *tid, const struct timespec *abstime)
00563      __attribute__ ((regparm (2))) attribute_hidden;
00564 #define lll_timedwait_tid(tid, abstime) \
00565   ({                                                                 \
00566     int __result = 0;                                                       \
00567     if (tid != 0)                                                    \
00568       {                                                                     \
00569        if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)          \
00570          __result = EINVAL;                                          \
00571        else                                                          \
00572          __result = __lll_timedwait_tid (&tid, abstime);                    \
00573       }                                                                     \
00574     __result; })
00575 
00576 #endif  /* !__ASSEMBLER__ */
00577 
00578 #endif /* lowlevellock.h */