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 <pthread-errnos.h>
22#include <structsem.h>
23
24
25	.text
26
27	.globl	sem_wait
28	.type	sem_wait,@function
29	.align	16
30sem_wait:
31.LSTARTCODE:
32	cfi_startproc
33
34#if VALUE == 0
35	movl	(%rdi), %eax
36#else
37	movl	VALUE(%rdi), %eax
38#endif
392:	testl	%eax, %eax
40	je	1f
41
42	leal	-1(%rax), %edx
43	LOCK
44#if VALUE == 0
45	cmpxchgl %edx, (%rdi)
46#else
47	cmpxchgl %edx, VALUE(%rdi)
48#endif
49	jne	2b
50
51	xorl	%eax, %eax
52	retq
53
54	/* This push is only needed to store the sem_t pointer for the
55	   exception handler.  */
561:	pushq	%rdi
57	cfi_adjust_cfa_offset(8)
58
59	LOCK
60	addq	$1, NWAITERS(%rdi)
61
62.LcleanupSTART:
636:	call	__pthread_enable_asynccancel
64	movl	%eax, %r8d
65
66	xorq	%r10, %r10
67	movl	$SYS_futex, %eax
68#if FUTEX_WAIT == 0
69	movl	PRIVATE(%rdi), %esi
70#else
71	movl	$FUTEX_WAIT, %esi
72	orl	PRIVATE(%rdi), %esi
73#endif
74	xorl	%edx, %edx
75	syscall
76	movq	%rax, %rcx
77
78	xchgq	%r8, %rdi
79	call	__pthread_disable_asynccancel
80.LcleanupEND:
81	movq	%r8, %rdi
82
83	testq	%rcx, %rcx
84	je	3f
85	cmpq	$-EWOULDBLOCK, %rcx
86	jne	4f
87
883:
89#if VALUE == 0
90	movl	(%rdi), %eax
91#else
92	movl	VALUE(%rdi), %eax
93#endif
945:	testl	%eax, %eax
95	je	6b
96
97	leal	-1(%rax), %edx
98	LOCK
99#if VALUE == 0
100	cmpxchgl %edx, (%rdi)
101#else
102	cmpxchgl %edx, VALUE(%rdi)
103#endif
104	jne	5b
105
106	xorl	%eax, %eax
107
1089:	LOCK
109	subq	$1, NWAITERS(%rdi)
110
111	leaq	8(%rsp), %rsp
112	cfi_adjust_cfa_offset(-8)
113
114	retq
115
116	cfi_adjust_cfa_offset(8)
1174:	negq	%rcx
118#if USE___THREAD
119	movq	errno@gottpoff(%rip), %rdx
120	movl	%ecx, %fs:(%rdx)
121#else
122# error "not supported.  %rcx and %rdi must be preserved"
123	callq	__errno_location@plt
124	movl	%ecx, (%rax)
125#endif
126	orl	$-1, %eax
127
128	jmp 9b
129	.size	sem_wait,.-sem_wait
130
131
132	.type	sem_wait_cleanup,@function
133sem_wait_cleanup:
134	movq	(%rsp), %rdi
135	LOCK
136	subq	$1, NWAITERS(%rdi)
137	movq	%rax, %rdi
138.LcallUR:
139	call	_Unwind_Resume@PLT
140	hlt
141.LENDCODE:
142	cfi_endproc
143	.size	sem_wait_cleanup,.-sem_wait_cleanup
144
145
146	.section .gcc_except_table,"a",@progbits
147.LexceptSTART:
148	.byte	DW_EH_PE_omit			# @LPStart format
149	.byte	DW_EH_PE_omit			# @TType format
150	.byte	DW_EH_PE_uleb128		# call-site format
151	.uleb128 .Lcstend-.Lcstbegin
152.Lcstbegin:
153	.uleb128 .LcleanupSTART-.LSTARTCODE
154	.uleb128 .LcleanupEND-.LcleanupSTART
155	.uleb128 sem_wait_cleanup-.LSTARTCODE
156	.uleb128  0
157	.uleb128 .LcallUR-.LSTARTCODE
158	.uleb128 .LENDCODE-.LcallUR
159	.uleb128 0
160	.uleb128  0
161.Lcstend:
162
163
164#ifdef SHARED
165	.hidden	DW.ref.__gcc_personality_v0
166	.weak	DW.ref.__gcc_personality_v0
167	.section .gnu.linkonce.d.DW.ref.__gcc_personality_v0,"aw",@progbits
168	.align	8
169	.type	DW.ref.__gcc_personality_v0, @object
170	.size	DW.ref.__gcc_personality_v0, 8
171DW.ref.__gcc_personality_v0:
172	.quad	__gcc_personality_v0
173#endif
174