src/xcalls/condvar/lowlevellock.h

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

Generated on Wed Dec 9 20:32:39 2009 for xCalls by  doxygen 1.4.7