| 12
 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
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 
 | /* Copyright (C) 2002-2014 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, see
   <http://www.gnu.org/licenses/>.  */
#include <sysdep.h>
#include <lowlevellock.h>
#include <lowlevelrwlock.h>
#include <kernel-features.h>
	.text
	.globl	__pthread_rwlock_unlock
	.type	__pthread_rwlock_unlock,@function
	.align	16
__pthread_rwlock_unlock:
	cfi_startproc
	pushl	%ebx
	cfi_adjust_cfa_offset(4)
	pushl	%edi
	cfi_adjust_cfa_offset(4)
	cfi_offset(%ebx, -8)
	cfi_offset(%edi, -12)
	movl	12(%esp), %edi
	/* Get the lock.  */
	movl	$1, %edx
	xorl	%eax, %eax
	LOCK
#if MUTEX == 0
	cmpxchgl %edx, (%edi)
#else
	cmpxchgl %edx, MUTEX(%edi)
#endif
	jnz	1f
2:	cmpl	$0, WRITER(%edi)
	jne	5f
	subl	$1, NR_READERS(%edi)
	jnz	6f
5:	movl	$0, WRITER(%edi)
	movl	$1, %edx
	leal	WRITERS_WAKEUP(%edi), %ebx
	cmpl	$0, WRITERS_QUEUED(%edi)
	jne	0f
	/* If also no readers waiting nothing to do.  */
	cmpl	$0, READERS_QUEUED(%edi)
	je	6f
	movl	$0x7fffffff, %edx
	leal	READERS_WAKEUP(%edi), %ebx
0:	addl	$1, (%ebx)
	LOCK
#if MUTEX == 0
	subl	$1, (%edi)
#else
	subl	$1, MUTEX(%edi)
#endif
	jne	7f
8:
#ifdef __ASSUME_PRIVATE_FUTEX
	movzbl	PSHARED(%edi), %ecx
	xorl	$FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %ecx
#else
	movzbl	PSHARED(%edi), %ecx
	orl	$FUTEX_WAKE, %ecx
	xorl	%gs:PRIVATE_FUTEX, %ecx
#endif
	movl	$SYS_futex, %eax
	ENTER_KERNEL
	xorl	%eax, %eax
	popl	%edi
	cfi_adjust_cfa_offset(-4)
	cfi_restore(%edi)
	popl	%ebx
	cfi_adjust_cfa_offset(-4)
	cfi_restore(%ebx)
	ret
	cfi_adjust_cfa_offset(8)
	cfi_offset(%ebx, -8)
	cfi_offset(%edi, -12)
	.align	16
6:	LOCK
#if MUTEX == 0
	subl	$1, (%edi)
#else
	subl	$1, MUTEX(%edi)
#endif
	jne	3f
4:	xorl	%eax, %eax
	popl	%edi
	popl	%ebx
	ret
1:
#if MUTEX == 0
	movl	%edi, %edx
#else
	leal	MUTEX(%edi), %edx
#endif
	movzbl	PSHARED(%edi), %ecx
	call	__lll_lock_wait
	jmp	2b
3:
#if MUTEX == 0
	movl	%edi, %eax
#else
	leal	MUTEX(%edi), %eax
#endif
	movzbl	PSHARED(%edi), %ecx
	call	__lll_unlock_wake
	jmp	4b
7:
#if MUTEX == 0
	movl	%edi, %eax
#else
	leal	MUTEX(%edi), %eax
#endif
	movzbl	PSHARED(%edi), %ecx
	call	__lll_unlock_wake
	jmp	8b
	cfi_endproc
	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock
strong_alias (__pthread_rwlock_unlock, pthread_rwlock_unlock)
hidden_def (__pthread_rwlock_unlock)
 |