]>
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 #include <sys/syscall.h>
32 #include <pulsecore/atomic.h>
33 #include <pulsecore/log.h>
34 #include <pulsecore/thread.h>
35 #include <pulsecore/macro.h>
36 #include <pulsecore/core-util.h>
37 #include <pulse/xmalloc.h>
41 #if !defined(__NR_eventfd) && defined(__i386__)
42 #define __NR_eventfd 323
45 #if !defined(__NR_eventfd) && defined(__x86_64__)
46 #define __NR_eventfd 284
49 #if !defined(SYS_eventfd) && defined(__NR_eventfd)
50 #define SYS_eventfd __NR_eventfd
56 static inline long eventfd(unsigned count
) {
57 return syscall(SYS_eventfd
, count
);
71 pa_atomic_t signalled
;
75 pa_fdsem
*pa_fdsem_new(void) {
78 f
= pa_xnew(pa_fdsem
, 1);
81 if ((f
->efd
= eventfd(0)) >= 0) {
82 pa_make_fd_cloexec(f
->efd
);
83 f
->fds
[0] = f
->fds
[1] = -1;
88 if (pipe(f
->fds
) < 0) {
93 pa_make_fd_cloexec(f
->fds
[0]);
94 pa_make_fd_cloexec(f
->fds
[1]);
97 pa_atomic_store(&f
->waiting
, 0);
98 pa_atomic_store(&f
->signalled
, 0);
99 pa_atomic_store(&f
->in_pipe
, 0);
104 void pa_fdsem_free(pa_fdsem
*f
) {
111 pa_close_pipe(f
->fds
);
116 static void flush(pa_fdsem
*f
) {
120 if (pa_atomic_load(&f
->in_pipe
) <= 0)
130 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
131 pa_assert(r
< 0 && errno
== EINTR
);
138 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
139 pa_assert(r
< 0 && errno
== EINTR
);
143 } while (pa_atomic_sub(&f
->in_pipe
, r
) > r
);
146 void pa_fdsem_post(pa_fdsem
*f
) {
149 if (pa_atomic_cmpxchg(&f
->signalled
, 0, 1)) {
151 if (pa_atomic_load(&f
->waiting
)) {
155 pa_atomic_inc(&f
->in_pipe
);
163 if ((r
= write(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
164 pa_assert(r
< 0 && errno
== EINTR
);
170 if ((r
= write(f
->fds
[1], &x
, 1)) != 1) {
171 pa_assert(r
< 0 && errno
== EINTR
);
181 void pa_fdsem_wait(pa_fdsem
*f
) {
186 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
189 pa_atomic_inc(&f
->waiting
);
191 while (!pa_atomic_cmpxchg(&f
->signalled
, 1, 0)) {
199 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
200 pa_assert(r
< 0 && errno
== EINTR
);
208 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
209 pa_assert(r
< 0 && errno
== EINTR
);
213 pa_atomic_sub(&f
->in_pipe
, r
);
216 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
219 int pa_fdsem_try(pa_fdsem
*f
) {
224 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
230 int pa_fdsem_get(pa_fdsem
*f
) {
241 int pa_fdsem_before_poll(pa_fdsem
*f
) {
246 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
249 pa_atomic_inc(&f
->waiting
);
251 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0)) {
252 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
258 int pa_fdsem_after_poll(pa_fdsem
*f
) {
261 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
265 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))