1 /* Copyright (C) 2002 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
3 Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
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.
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.
15 You should have received a copy of the GNU Lesser General Public
16 License along with the GNU C Library; if not, write to the Free
17 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
24 #define SYS_gettimeofday __NR_gettimeofday
33 /* Offsets in the pthread_rwlock_t structure. */
36 #define READERS_WAKEUP 8
37 #define WRITERS_WAKEUP 12
38 #define READERS_QUEUED 16
39 #define WRITERS_QUEUED 20
50 .globl __pthread_rwlock_rdlock
51 .type __pthread_rwlock_rdlock,@function
53 __pthread_rwlock_rdlock:
64 xaddl %eax, MUTEX(%ebx)
68 2: movl WRITER(%ebx), %eax
71 cmp $0, WRITERS_QUEUED(%ebx)
76 3: incl READERS_QUEUED(%ebx)
83 11: addl $READERS_WAKEUP-MUTEX, %ebx
84 movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
88 subl $READERS_WAKEUP-MUTEX, %ebx
93 xaddl %eax, MUTEX(%ebx)
97 13: decl READERS_QUEUED(%ebx)
99 movl $0, READERS_WAKEUP(%ebx)
103 incl NR_READERS(%ebx)
116 call __lll_mutex_lock_wait
121 /* Deadlock detected. */
126 call __lll_mutex_unlock_wake
130 8: decl NR_READERS(%ebx)
135 4: decl READERS_QUEUED(%ebx)
140 call __lll_mutex_unlock_wake
144 call __lll_mutex_lock_wait
146 .size __pthread_rwlock_rdlock,.-__pthread_rwlock_rdlock
148 .globl pthread_rwlock_rdlock
149 pthread_rwlock_rdlock = __pthread_rwlock_rdlock
152 .globl pthread_rwlock_timedrdlock
153 .type pthread_rwlock_timedrdlock,@function
155 pthread_rwlock_timedrdlock:
168 xaddl %eax, MUTEX(%ebp)
172 2: movl WRITER(%ebp), %eax
175 cmp $0, WRITERS_QUEUED(%ebp)
180 3: incl READERS_QUEUED(%ebp)
187 /* Get current time. */
190 movl $SYS_gettimeofday, %eax
193 /* Compute relative timeout. */
196 mul %edx /* Milli seconds to nano seconds. */
202 addl $1000000000, %edx
205 js 16f /* Time is already up. */
208 movl %ecx, (%esp) /* Store relative timeout. */
210 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
213 leal READERS_WAKEUP(%ebp), %ebx
214 movl $SYS_futex, %eax
219 /* Reget the lock. */
222 xaddl %eax, MUTEX(%ebp)
226 13: cmpl $-ETIMEDOUT, %ecx
228 decl READERS_QUEUED(%ebp)
230 movl $0, READERS_WAKEUP(%ebp)
235 incl NR_READERS(%ebp)
251 call __lll_mutex_lock_wait
260 call __lll_mutex_unlock_wake
264 8: decl NR_READERS(%ebp)
269 4: decl READERS_QUEUED(%ebp)
274 call __lll_mutex_unlock_wake
278 call __lll_mutex_lock_wait
281 16: movl $-ETIMEDOUT, %ecx
284 18: movl $ETIMEDOUT, %ecx
286 .size pthread_rwlock_timedrdlock,.-pthread_rwlock_timedrdlock
289 .globl __pthread_rwlock_wrlock
290 .type __pthread_rwlock_wrlock,@function
292 __pthread_rwlock_wrlock:
303 xaddl %eax, MUTEX(%ebx)
307 2: movl WRITER(%ebx), %eax
310 cmp $0, NR_READERS(%ebx)
313 3: incl WRITERS_QUEUED(%ebx)
320 11: addl $WRITERS_WAKEUP-MUTEX, %ebx
321 movl %esi, %ecx /* movl $FUTEX_WAIT, %ecx */
322 movl $SYS_futex, %eax
325 subl $WRITERS_WAKEUP-MUTEX, %ebx
327 /* Reget the lock. */
330 xaddl %eax, MUTEX(%ebx)
334 13: decl WRITERS_QUEUED(%ebx)
335 movl $0, WRITERS_WAKEUP(%ebx)
340 movl %eax, WRITER(%ebx)
352 call __lll_mutex_lock_wait
361 call __lll_mutex_unlock_wake
364 4: decl WRITERS_QUEUED(%ebx)
369 call __lll_mutex_unlock_wake
373 call __lll_mutex_lock_wait
375 .size __pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
377 .globl pthread_rwlock_wrlock
378 pthread_rwlock_wrlock = __pthread_rwlock_wrlock
381 .globl pthread_rwlock_timedwrlock
382 .type pthread_rwlock_timedwrlock,@function
384 pthread_rwlock_timedwrlock:
397 xaddl %eax, MUTEX(%ebp)
401 2: movl WRITER(%ebp), %eax
404 cmp $0, NR_READERS(%ebp)
407 3: incl WRITERS_QUEUED(%ebp)
414 /* Get current time. */
417 movl $SYS_gettimeofday, %eax
420 /* Compute relative timeout. */
423 mul %edx /* Milli seconds to nano seconds. */
429 addl $1000000000, %edx
432 js 16f /* Time is already up. */
435 movl %ecx, (%esp) /* Store relative timeout. */
437 xorl %ecx, %ecx /* movl $FUTEX_WAIT, %ecx */
440 leal WRITERS_WAKEUP(%ebp), %ebx
441 movl $SYS_futex, %eax
446 /* Reget the lock. */
449 xaddl %eax, MUTEX(%ebp)
453 13: cmpl $-ETIMEDOUT, %ecx
455 decl WRITERS_QUEUED(%ebp)
456 movl $0, WRITERS_WAKEUP(%ebp)
462 movl %eax, WRITER(%ebp)
477 call __lll_mutex_lock_wait
486 call __lll_mutex_unlock_wake
490 4: decl WRITERS_QUEUED(%ebp)
495 call __lll_mutex_unlock_wake
499 call __lll_mutex_lock_wait
502 16: movl $-ETIMEDOUT, %ecx
505 18: movl $ETIMEDOUT, %ecx
507 .size pthread_rwlock_timedwrlock,.-pthread_rwlock_timedwrlock
509 .globl __pthread_rwlock_unlock
510 .type __pthread_rwlock_unlock,@function
512 __pthread_rwlock_unlock:
524 xaddl %eax, MUTEX(%edi)
528 2: cmpl $0, WRITER(%edi)
530 decl NR_READERS(%edi)
533 5: movl $0, WRITER(%edi)
535 movl $0x7fffffff, %edx
536 leal READERS_WAKEUP(%edi), %ebx
538 leal WRITERS_WAKEUP(%edi), %eax
539 cmpl $0, WRITERS_QUEUED(%edi)
549 movl $SYS_futex, %eax
563 call __lll_mutex_lock_wait
567 call __lll_mutex_unlock_wake
570 .size __pthread_rwlock_unlock,.-__pthread_rwlock_unlock
572 .globl pthread_rwlock_unlock
573 pthread_rwlock_unlock = __pthread_rwlock_unlock