1 /* Notify initiator of AIO request.
2 Copyright (C) 1997, 1998, 1999, 2000, 2001, 2003, 2004
3 Free Software Foundation, Inc.
4 This file is part of the GNU C Library.
5 Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
7 The GNU C Library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
12 The GNU C Library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with the GNU C Library; if not, write to the Free
19 Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 #ifndef aio_start_notify_thread
29 # define aio_start_notify_thread() do { } while (0)
34 void (*func
) (sigval_t
);
39 notify_func_wrapper (void *arg
)
41 aio_start_notify_thread ();
42 struct notify_func
*const n
= arg
;
43 void (*func
) (sigval_t
) = n
->func
;
44 sigval_t value
= n
->value
;
53 #ifdef BROKEN_THREAD_SIGNALS
54 __aio_notify_only (struct sigevent
*sigev
, pid_t caller_pid
)
56 __aio_notify_only (struct sigevent
*sigev
)
61 /* Send the signal to notify about finished processing of the request. */
62 if (__builtin_expect (sigev
->sigev_notify
== SIGEV_THREAD
, 0))
64 /* We have to start a thread. */
66 pthread_attr_t attr
, *pattr
;
68 pattr
= (pthread_attr_t
*) sigev
->sigev_notify_attributes
;
71 pthread_attr_init (&attr
);
72 pthread_attr_setdetachstate (&attr
, PTHREAD_CREATE_DETACHED
);
76 /* SIGEV may be freed as soon as we return, so we cannot let the
77 notification thread use that pointer. Even though a sigval_t is
78 only one word and the same size as a void *, we cannot just pass
79 the value through pthread_create as the argument and have the new
80 thread run the user's function directly, because on some machines
81 the calling convention for a union like sigval_t is different from
82 that for a pointer type like void *. */
83 struct notify_func
*nf
= malloc (sizeof *nf
);
88 nf
->func
= sigev
->sigev_notify_function
;
89 nf
->value
= sigev
->sigev_value
;
90 if (pthread_create (&tid
, pattr
, notify_func_wrapper
, nf
) < 0)
97 else if (sigev
->sigev_notify
== SIGEV_SIGNAL
)
99 /* We have to send a signal. */
100 #if _POSIX_REALTIME_SIGNALS
101 /* Note that the standard gives us the option of using a plain
102 non-queuing signal here when SA_SIGINFO is not set for the signal. */
103 # ifdef BROKEN_THREAD_SIGNALS
104 if (__aio_sigqueue (sigev
->sigev_signo
, sigev
->sigev_value
, caller_pid
)
108 if (__aio_sigqueue (sigev
->sigev_signo
, sigev
->sigev_value
, getpid ())
113 /* There are no queued signals on this system at all. */
114 result
= raise (sigev
->sigev_signo
);
124 __aio_notify (struct requestlist
*req
)
126 struct waitlist
*waitlist
;
127 struct aiocb
*aiocbp
= &req
->aiocbp
->aiocb
;
129 #ifdef BROKEN_THREAD_SIGNALS
130 if (__aio_notify_only (&aiocbp
->aio_sigevent
, req
->caller_pid
) != 0)
132 if (__aio_notify_only (&aiocbp
->aio_sigevent
) != 0)
135 /* XXX What shall we do if already an error is set by
137 aiocbp
->__error_code
= errno
;
138 aiocbp
->__return_value
= -1;
141 /* Now also notify possibly waiting threads. */
142 waitlist
= req
->waiting
;
143 while (waitlist
!= NULL
)
145 struct waitlist
*next
= waitlist
->next
;
147 /* Decrement the counter. This is used in both cases. */
148 --*waitlist
->counterp
;
150 if (waitlist
->sigevp
== NULL
)
151 pthread_cond_signal (waitlist
->cond
);
153 /* This is part of a asynchronous `lio_listio' operation. If
154 this request is the last one, send the signal. */
155 if (*waitlist
->counterp
== 0)
157 #ifdef BROKEN_THREAD_SIGNALS
158 __aio_notify_only (waitlist
->sigevp
, waitlist
->caller_pid
);
160 __aio_notify_only (waitlist
->sigevp
);
162 /* This is tricky. See lio_listio.c for the reason why
164 free ((void *) waitlist
->counterp
);