]>
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(__NR_eventfd) && defined(__arm__)
57 #define __NR_eventfd (__NR_SYSCALL_BASE+351)
60 #if !defined(SYS_eventfd) && defined(__NR_eventfd)
61 #define SYS_eventfd __NR_eventfd
67 static inline long eventfd(unsigned count
) {
68 return syscall(SYS_eventfd
, count
);
85 pa_fdsem
*pa_fdsem_new(void) {
88 f
= pa_xmalloc(PA_ALIGN(sizeof(pa_fdsem
)) + PA_ALIGN(sizeof(pa_fdsem_data
)));
91 if ((f
->efd
= eventfd(0)) >= 0) {
92 pa_make_fd_cloexec(f
->efd
);
93 f
->fds
[0] = f
->fds
[1] = -1;
97 if (pipe(f
->fds
) < 0) {
102 pa_make_fd_cloexec(f
->fds
[0]);
103 pa_make_fd_cloexec(f
->fds
[1]);
106 f
->data
= (pa_fdsem_data
*) ((uint8_t*) f
+ PA_ALIGN(sizeof(pa_fdsem
)));
108 pa_atomic_store(&f
->data
->waiting
, 0);
109 pa_atomic_store(&f
->data
->signalled
, 0);
110 pa_atomic_store(&f
->data
->in_pipe
, 0);
115 pa_fdsem
*pa_fdsem_open_shm(pa_fdsem_data
*data
, int event_fd
) {
119 pa_assert(event_fd
>= 0);
122 f
= pa_xnew(pa_fdsem
, 1);
125 pa_make_fd_cloexec(f
->efd
);
126 f
->fds
[0] = f
->fds
[1] = -1;
133 pa_fdsem
*pa_fdsem_new_shm(pa_fdsem_data
*data
, int* event_fd
) {
141 f
= pa_xnew(pa_fdsem
, 1);
143 if ((f
->efd
= eventfd(0)) < 0) {
148 pa_make_fd_cloexec(f
->efd
);
149 f
->fds
[0] = f
->fds
[1] = -1;
152 pa_atomic_store(&f
->data
->waiting
, 0);
153 pa_atomic_store(&f
->data
->signalled
, 0);
154 pa_atomic_store(&f
->data
->in_pipe
, 0);
161 void pa_fdsem_free(pa_fdsem
*f
) {
168 pa_close_pipe(f
->fds
);
173 static void flush(pa_fdsem
*f
) {
177 if (pa_atomic_load(&f
->data
->in_pipe
) <= 0)
187 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
188 pa_assert(r
< 0 && errno
== EINTR
);
195 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
196 pa_assert(r
< 0 && errno
== EINTR
);
200 } while (pa_atomic_sub(&f
->data
->in_pipe
, r
) > r
);
203 void pa_fdsem_post(pa_fdsem
*f
) {
206 if (pa_atomic_cmpxchg(&f
->data
->signalled
, 0, 1)) {
208 if (pa_atomic_load(&f
->data
->waiting
)) {
212 pa_atomic_inc(&f
->data
->in_pipe
);
220 if ((r
= write(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
221 pa_assert(r
< 0 && errno
== EINTR
);
227 if ((r
= write(f
->fds
[1], &x
, 1)) != 1) {
228 pa_assert(r
< 0 && errno
== EINTR
);
238 void pa_fdsem_wait(pa_fdsem
*f
) {
243 if (pa_atomic_cmpxchg(&f
->data
->signalled
, 1, 0))
246 pa_atomic_inc(&f
->data
->waiting
);
248 while (!pa_atomic_cmpxchg(&f
->data
->signalled
, 1, 0)) {
256 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
257 pa_assert(r
< 0 && errno
== EINTR
);
265 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
266 pa_assert(r
< 0 && errno
== EINTR
);
270 pa_atomic_sub(&f
->data
->in_pipe
, r
);
273 pa_assert_se(pa_atomic_dec(&f
->data
->waiting
) >= 1);
276 int pa_fdsem_try(pa_fdsem
*f
) {
281 if (pa_atomic_cmpxchg(&f
->data
->signalled
, 1, 0))
287 int pa_fdsem_get(pa_fdsem
*f
) {
298 int pa_fdsem_before_poll(pa_fdsem
*f
) {
303 if (pa_atomic_cmpxchg(&f
->data
->signalled
, 1, 0))
306 pa_atomic_inc(&f
->data
->waiting
);
308 if (pa_atomic_cmpxchg(&f
->data
->signalled
, 1, 0)) {
309 pa_assert_se(pa_atomic_dec(&f
->data
->waiting
) >= 1);
315 int pa_fdsem_after_poll(pa_fdsem
*f
) {
318 pa_assert_se(pa_atomic_dec(&f
->data
->waiting
) >= 1);
322 if (pa_atomic_cmpxchg(&f
->data
->signalled
, 1, 0))