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 <bits/kernel-features.h>
23
24
25	.text
26
27	.globl	__pthread_rwlock_unlock
28	.type	__pthread_rwlock_unlock,@function
29	.protected	__pthread_rwlock_unlock
30	.align	16
31__pthread_rwlock_unlock:
32	cfi_startproc
33	/* Get the lock.  */
34	movl	$1, %esi
35	xorl	%eax, %eax
36	LOCK
37#if MUTEX == 0
38	cmpxchgl %esi, (%rdi)
39#else
40	cmpxchgl %esi, MUTEX(%rdi)
41#endif
42	jnz	1f
43
442:	cmpl	$0, WRITER(%rdi)
45	jne	5f
46	decl	NR_READERS(%rdi)
47	jnz	6f
48
495:	movl	$0, WRITER(%rdi)
50
51	movl	$1, %edx
52	leaq	WRITERS_WAKEUP(%rdi), %r10
53	cmpl	$0, WRITERS_QUEUED(%rdi)
54	jne	0f
55
56	/* If also no readers waiting nothing to do.  */
57	cmpl	$0, READERS_QUEUED(%rdi)
58	je	6f
59
60	movl	$0x7fffffff, %edx
61	leaq	READERS_WAKEUP(%rdi), %r10
62
630:	incl	(%r10)
64	LOCK
65#if MUTEX == 0
66	decl	(%rdi)
67#else
68	decl	MUTEX(%rdi)
69#endif
70	jne	7f
71
728:
73#ifdef __ASSUME_PRIVATE_FUTEX
74	movl	$FUTEX_PRIVATE_FLAG|FUTEX_WAKE, %esi
75	xorl	PSHARED(%rdi), %esi
76#else
77	movl	$FUTEX_WAKE, %esi
78	orl	PSHARED(%rdi), %esi
79	xorl	%fs:PRIVATE_FUTEX, %esi
80#endif
81	movl	$SYS_futex, %eax
82	movq	%r10, %rdi
83	syscall
84
85	xorl	%eax, %eax
86	retq
87
88	.align	16
896:	LOCK
90#if MUTEX == 0
91	decl	(%rdi)
92#else
93	decl	MUTEX(%rdi)
94#endif
95	jne	3f
96
974:	xorl	%eax, %eax
98	retq
99
1001:	movl	PSHARED(%rdi), %esi
101#if MUTEX != 0
102	addq	$MUTEX, %rdi
103#endif
104	callq	__lll_lock_wait
105#if MUTEX != 0
106	subq	$MUTEX, %rdi
107#endif
108	jmp	2b
109
1103:	movl	PSHARED(%rdi), %esi
111#if MUTEX != 0
112	addq	$MUTEX, %rdi
113#endif
114	callq	__lll_unlock_wake
115	jmp	4b
116
1177:	movl	PSHARED(%rdi), %esi
118#if MUTEX != 0
119	addq	$MUTEX, %rdi
120#endif
121	callq	__lll_unlock_wake
122	jmp	8b
123	cfi_endproc
124	.size	__pthread_rwlock_unlock,.-__pthread_rwlock_unlock
125
126	.globl	pthread_rwlock_unlock
127pthread_rwlock_unlock = __pthread_rwlock_unlock
128
129	.globl	__pthread_rwlock_unlock_internal
130__pthread_rwlock_unlock_internal = __pthread_rwlock_unlock
131