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_wrlock
30	.type	__pthread_rwlock_wrlock,@function
31	.protected	__pthread_rwlock_wrlock
32	.align	16
33__pthread_rwlock_wrlock:
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, NR_READERS(%rdi)
52	je	5f
53
543:	incl	WRITERS_QUEUED(%rdi)
55	je	4f
56
57	movl	WRITERS_WAKEUP(%rdi), %edx
58
59	LOCK
60#if MUTEX == 0
61	decl	(%rdi)
62#else
63	decl	MUTEX(%rdi)
64#endif
65	jne	10f
66
6711:
68#ifdef __ASSUME_PRIVATE_FUTEX
69	movl	$FUTEX_PRIVATE_FLAG|FUTEX_WAIT, %esi
70	xorl	PSHARED(%rdi), %esi
71#else
72# if FUTEX_WAIT == 0
73	movl	PSHARED(%rdi), %esi
74# else
75	movl	$FUTEX_WAIT, %esi
76	orl	PSHARED(%rdi), %esi
77# endif
78	xorl	%fs:PRIVATE_FUTEX, %esi
79#endif
80	addq	$WRITERS_WAKEUP, %rdi
81	movl	$SYS_futex, %eax
82	syscall
83
84	subq	$WRITERS_WAKEUP, %rdi
85
86	/* Reget the lock.  */
87	movl	$1, %esi
88	xorl	%eax, %eax
89	LOCK
90#if MUTEX == 0
91	cmpxchgl %esi, (%rdi)
92#else
93	cmpxchgl %esi, MUTEX(%rdi)
94#endif
95	jnz	12f
96
9713:	decl	WRITERS_QUEUED(%rdi)
98	jmp	2b
99
1005:	xorl	%edx, %edx
101	movl	%fs:TID, %eax
102	movl	%eax, WRITER(%rdi)
1039:	LOCK
104#if MUTEX == 0
105	decl	(%rdi)
106#else
107	decl	MUTEX(%rdi)
108#endif
109	jne	6f
1107:
111
112	movq	%rdx, %rax
113	retq
114
1151:	movl	PSHARED(%rdi), %esi
116#if MUTEX != 0
117	addq	$MUTEX, %rdi
118#endif
119	callq	__lll_lock_wait
120#if MUTEX != 0
121	subq	$MUTEX, %rdi
122#endif
123	jmp	2b
124
12514:	cmpl	%fs:TID, %eax
126	jne	3b
127	movl	$EDEADLK, %edx
128	jmp	9b
129
1306:	movl	PSHARED(%rdi), %esi
131#if MUTEX != 0
132	addq	$MUTEX, %rdi
133#endif
134	callq	__lll_unlock_wake
135	jmp	7b
136
1374:	decl	WRITERS_QUEUED(%rdi)
138	movl	$EAGAIN, %edx
139	jmp	9b
140
14110:	movl	PSHARED(%rdi), %esi
142#if MUTEX != 0
143	addq	$MUTEX, %rdi
144#endif
145	callq	__lll_unlock_wake
146#if MUTEX != 0
147	subq	$MUTEX, %rdi
148#endif
149	jmp	11b
150
15112:	movl	PSHARED(%rdi), %esi
152#if MUTEX != 0
153	addq	$MUTEX, %rdi
154#endif
155	callq	__lll_lock_wait
156#if MUTEX != 0
157	subq	$MUTEX, %rdi
158#endif
159	jmp	13b
160	cfi_endproc
161	.size	__pthread_rwlock_wrlock,.-__pthread_rwlock_wrlock
162
163	.globl	pthread_rwlock_wrlock
164pthread_rwlock_wrlock = __pthread_rwlock_wrlock
165
166	.globl	__pthread_rwlock_wrlock_internal
167__pthread_rwlock_wrlock_internal = __pthread_rwlock_wrlock
168