1 /* Copyright (C) 2006-2022 Free Software Foundation, Inc.
2    This file is part of the GNU C Library.
3 
4    The GNU C Library is free software; you can redistribute it and/or
5    modify it under the terms of the GNU Lesser General Public
6    License as published by the Free Software Foundation; either
7    version 2.1 of the License, or (at your option) any later version.
8 
9    The GNU C Library is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12    Lesser General Public License for more details.
13 
14    You should have received a copy of the GNU Lesser General Public
15    License along with the GNU C Library; if not, see
16    <https://www.gnu.org/licenses/>.  */
17 
18 /* We define a special synchronization primitive for AIO.  POSIX
19    conditional variables would be ideal but the pthread_cond_*wait
20    operations do not return on EINTR.  This is a requirement for
21    correct aio_suspend and lio_listio implementations.  */
22 
23 #include <assert.h>
24 #include <pthreadP.h>
25 #include <futex-internal.h>
26 
27 #define DONT_NEED_AIO_MISC_COND	1
28 
29 #define AIO_MISC_NOTIFY(waitlist) \
30   do {									      \
31     if (*waitlist->counterp > 0 && --*waitlist->counterp == 0)		      \
32       futex_wake ((unsigned int *) waitlist->counterp, 1, FUTEX_PRIVATE);     \
33   } while (0)
34 
35 #define AIO_MISC_WAIT(result, futex, timeout, cancel)			      \
36   do {									      \
37     volatile unsigned int *futexaddr = &futex;				      \
38     unsigned int oldval = futex;					      \
39 									      \
40     if (oldval != 0)							      \
41       {									      \
42 	__pthread_mutex_unlock (&__aio_requests_mutex);			      \
43 									      \
44 	int status;							      \
45 	do								      \
46 	  {								      \
47 	    if (cancel)							      \
48 	      status = __futex_abstimed_wait_cancelable64 (		      \
49 		(unsigned int *) futexaddr, oldval, CLOCK_MONOTONIC, timeout, \
50 		FUTEX_PRIVATE);						      \
51 	    else							      \
52 	      status = __futex_abstimed_wait64 ((unsigned int *) futexaddr,   \
53 		oldval, CLOCK_REALTIME, timeout, FUTEX_PRIVATE); 	      \
54 	    if (status != EAGAIN)					      \
55 	      break;							      \
56 									      \
57 	    oldval = *futexaddr;					      \
58 	  }								      \
59 	while (oldval != 0);						      \
60 									      \
61 	if (status == EINTR)						      \
62 	  result = EINTR;						      \
63 	else if (status == ETIMEDOUT)					      \
64 	  result = EAGAIN;						      \
65 	else if (status == EOVERFLOW)					      \
66 	  result = EOVERFLOW;						      \
67 	else								      \
68 	  assert (status == 0 || status == EAGAIN);			      \
69 									      \
70 	__pthread_mutex_lock (&__aio_requests_mutex);			      \
71       }									      \
72   } while (0)
73 
74 #include_next <aio_misc.h>
75