]>
code.delx.au - pulseaudio/blob - src/pulsecore/fdsem.c
4 This file is part of PulseAudio.
6 Copyright 2006 Lennart Poettering
8 PulseAudio is free software; you can redistribute it and/or modify
9 it under the terms of the GNU Lesser General Public License as
10 published by the Free Software Foundation; either version 2.1 of the
11 License, or (at your option) any later version.
13 PulseAudio is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public
19 License along with PulseAudio; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
28 #ifdef HAVE_SYS_SYSCALL_H
29 #include <sys/syscall.h>
35 #include <pulsecore/atomic.h>
36 #include <pulsecore/log.h>
37 #include <pulsecore/thread.h>
38 #include <pulsecore/macro.h>
39 #include <pulsecore/core-util.h>
40 #include <pulse/xmalloc.h>
43 #include <pulsecore/pipe.h>
48 #if !defined(__NR_eventfd) && defined(__i386__)
49 #define __NR_eventfd 323
52 #if !defined(__NR_eventfd) && defined(__x86_64__)
53 #define __NR_eventfd 284
56 #if !defined(SYS_eventfd) && defined(__NR_eventfd)
57 #define SYS_eventfd __NR_eventfd
63 static inline long eventfd(unsigned count
) {
64 return syscall(SYS_eventfd
, count
);
78 pa_atomic_t signalled
;
82 pa_fdsem
*pa_fdsem_new(void) {
85 f
= pa_xnew(pa_fdsem
, 1);
88 if ((f
->efd
= eventfd(0)) >= 0) {
89 pa_make_fd_cloexec(f
->efd
);
90 f
->fds
[0] = f
->fds
[1] = -1;
95 if (pipe(f
->fds
) < 0) {
100 pa_make_fd_cloexec(f
->fds
[0]);
101 pa_make_fd_cloexec(f
->fds
[1]);
104 pa_atomic_store(&f
->waiting
, 0);
105 pa_atomic_store(&f
->signalled
, 0);
106 pa_atomic_store(&f
->in_pipe
, 0);
111 void pa_fdsem_free(pa_fdsem
*f
) {
118 pa_close_pipe(f
->fds
);
123 static void flush(pa_fdsem
*f
) {
127 if (pa_atomic_load(&f
->in_pipe
) <= 0)
137 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
138 pa_assert(r
< 0 && errno
== EINTR
);
145 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
146 pa_assert(r
< 0 && errno
== EINTR
);
150 } while (pa_atomic_sub(&f
->in_pipe
, r
) > r
);
153 void pa_fdsem_post(pa_fdsem
*f
) {
156 if (pa_atomic_cmpxchg(&f
->signalled
, 0, 1)) {
158 if (pa_atomic_load(&f
->waiting
)) {
162 pa_atomic_inc(&f
->in_pipe
);
170 if ((r
= write(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
171 pa_assert(r
< 0 && errno
== EINTR
);
177 if ((r
= write(f
->fds
[1], &x
, 1)) != 1) {
178 pa_assert(r
< 0 && errno
== EINTR
);
188 void pa_fdsem_wait(pa_fdsem
*f
) {
193 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
196 pa_atomic_inc(&f
->waiting
);
198 while (!pa_atomic_cmpxchg(&f
->signalled
, 1, 0)) {
206 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
207 pa_assert(r
< 0 && errno
== EINTR
);
215 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
216 pa_assert(r
< 0 && errno
== EINTR
);
220 pa_atomic_sub(&f
->in_pipe
, r
);
223 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
226 int pa_fdsem_try(pa_fdsem
*f
) {
231 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
237 int pa_fdsem_get(pa_fdsem
*f
) {
248 int pa_fdsem_before_poll(pa_fdsem
*f
) {
253 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
256 pa_atomic_inc(&f
->waiting
);
258 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0)) {
259 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
265 int pa_fdsem_after_poll(pa_fdsem
*f
) {
268 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
272 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))