1/* Copyright (C) 2002, 2003, 2005, 2007, 2009 Free Software Foundation, Inc. 2 This file is part of the GNU C Library. 3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <http://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20#include <lowlevellock.h> 21#include <lowlevelrwlock.h> 22#include <pthread-errnos.h> 23#include <bits/kernel-features.h> 24#include <tcb-offsets.h> 25 26 27 .text 28 29 .globl __pthread_rwlock_rdlock 30 .type __pthread_rwlock_rdlock,@function 31 .protected __pthread_rwlock_rdlock 32 .align 16 33__pthread_rwlock_rdlock: 34 cfi_startproc 35 xorq %r10, %r10 36 37 /* Get the lock. */ 38 movl $1, %esi 39 xorl %eax, %eax 40 LOCK 41#if MUTEX == 0 42 cmpxchgl %esi, (%rdi) 43#else 44 cmpxchgl %esi, MUTEX(%rdi) 45#endif 46 jnz 1f 47 482: movl WRITER(%rdi), %eax 49 testl %eax, %eax 50 jne 14f 51 cmpl $0, WRITERS_QUEUED(%rdi) 52 je 5f 53 cmpl $0, FLAGS(%rdi) 54 je 5f 55 563: incl READERS_QUEUED(%rdi) 57 je 4f 58 59 movl READERS_WAKEUP(%rdi), %edx 60 61 LOCK 62#if MUTEX == 0 63 decl (%rdi) 64#else 65 decl MUTEX(%rdi) 66#endif 67 jne 10f 68 6911: 70#ifdef __ASSUME_PRIVATE_FUTEX 71 movl $FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi 72 xorl PSHARED(%rdi), %esi 73#else 74# if FUTEX_WAIT == 0 75 movl PSHARED(%rdi), %esi 76# else 77 movl $FUTEX_WAIT, %esi 78 orl PSHARED(%rdi), %esi 79# endif 80 xorl %fs:PRIVATE_FUTEX, %esi 81#endif 82 addq $READERS_WAKEUP, %rdi 83 movl $SYS_futex, %eax 84 syscall 85 86 subq $READERS_WAKEUP, %rdi 87 88 /* Reget the lock. */ 89 movl $1, %esi 90 xorl %eax, %eax 91 LOCK 92#if MUTEX == 0 93 cmpxchgl %esi, (%rdi) 94#else 95 cmpxchgl %esi, MUTEX(%rdi) 96#endif 97 jnz 12f 98 9913: decl READERS_QUEUED(%rdi) 100 jmp 2b 101 1025: xorl %edx, %edx 103 incl NR_READERS(%rdi) 104 je 8f 1059: LOCK 106#if MUTEX == 0 107 decl (%rdi) 108#else 109 decl MUTEX(%rdi) 110#endif 111 jne 6f 1127: 113 114 movq %rdx, %rax 115 retq 116 1171: movl PSHARED(%rdi), %esi 118#if MUTEX != 0 119 addq $MUTEX, %rdi 120#endif 121 callq __lll_lock_wait 122#if MUTEX != 0 123 subq $MUTEX, %rdi 124#endif 125 jmp 2b 126 12714: cmpl %fs:TID, %eax 128 jne 3b 129 /* Deadlock detected. */ 130 movl $EDEADLK, %edx 131 jmp 9b 132 1336: movl PSHARED(%rdi), %esi 134#if MUTEX != 0 135 addq $MUTEX, %rdi 136#endif 137 callq __lll_unlock_wake 138#if MUTEX != 0 139 subq $MUTEX, %rdi 140#endif 141 jmp 7b 142 143 /* Overflow. */ 1448: decl NR_READERS(%rdi) 145 movl $EAGAIN, %edx 146 jmp 9b 147 148 /* Overflow. */ 1494: decl READERS_QUEUED(%rdi) 150 movl $EAGAIN, %edx 151 jmp 9b 152 15310: movl PSHARED(%rdi), %esi 154#if MUTEX != 0 155 addq $MUTEX, %rdi 156#endif 157 callq __lll_unlock_wake 158#if MUTEX != 0 159 subq $MUTEX, %rdi 160#endif 161 jmp 11b 162 16312: movl PSHARED(%rdi), %esi 164#if MUTEX == 0 165 addq $MUTEX, %rdi 166#endif 167 callq __lll_lock_wait 168#if MUTEX != 0 169 subq $MUTEX, %rdi 170#endif 171 jmp 13b 172 cfi_endproc 173 .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock 174 175 .globl pthread_rwlock_rdlock 176pthread_rwlock_rdlock = __pthread_rwlock_rdlock 177 178 .globl __pthread_rwlock_rdlock_internal 179__pthread_rwlock_rdlock_internal = __pthread_rwlock_rdlock 180