]>
code.delx.au - pulseaudio/blob - src/pulsecore/fdsem.c
59eec18ef12dda165e0829ea6c004a06989342b2
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
);
82 pa_atomic_t signalled
;
86 pa_fdsem
*pa_fdsem_new(void) {
89 f
= pa_xnew(pa_fdsem
, 1);
92 if ((f
->efd
= eventfd(0)) >= 0) {
93 pa_make_fd_cloexec(f
->efd
);
94 f
->fds
[0] = f
->fds
[1] = -1;
99 if (pipe(f
->fds
) < 0) {
104 pa_make_fd_cloexec(f
->fds
[0]);
105 pa_make_fd_cloexec(f
->fds
[1]);
108 pa_atomic_store(&f
->waiting
, 0);
109 pa_atomic_store(&f
->signalled
, 0);
110 pa_atomic_store(&f
->in_pipe
, 0);
115 void pa_fdsem_free(pa_fdsem
*f
) {
122 pa_close_pipe(f
->fds
);
127 static void flush(pa_fdsem
*f
) {
131 if (pa_atomic_load(&f
->in_pipe
) <= 0)
141 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
142 pa_assert(r
< 0 && errno
== EINTR
);
149 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
150 pa_assert(r
< 0 && errno
== EINTR
);
154 } while (pa_atomic_sub(&f
->in_pipe
, r
) > r
);
157 void pa_fdsem_post(pa_fdsem
*f
) {
160 if (pa_atomic_cmpxchg(&f
->signalled
, 0, 1)) {
162 if (pa_atomic_load(&f
->waiting
)) {
166 pa_atomic_inc(&f
->in_pipe
);
174 if ((r
= write(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
175 pa_assert(r
< 0 && errno
== EINTR
);
181 if ((r
= write(f
->fds
[1], &x
, 1)) != 1) {
182 pa_assert(r
< 0 && errno
== EINTR
);
192 void pa_fdsem_wait(pa_fdsem
*f
) {
197 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
200 pa_atomic_inc(&f
->waiting
);
202 while (!pa_atomic_cmpxchg(&f
->signalled
, 1, 0)) {
210 if ((r
= read(f
->efd
, &u
, sizeof(u
))) != sizeof(u
)) {
211 pa_assert(r
< 0 && errno
== EINTR
);
219 if ((r
= read(f
->fds
[0], &x
, sizeof(x
))) <= 0) {
220 pa_assert(r
< 0 && errno
== EINTR
);
224 pa_atomic_sub(&f
->in_pipe
, r
);
227 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
230 int pa_fdsem_try(pa_fdsem
*f
) {
235 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
241 int pa_fdsem_get(pa_fdsem
*f
) {
252 int pa_fdsem_before_poll(pa_fdsem
*f
) {
257 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))
260 pa_atomic_inc(&f
->waiting
);
262 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0)) {
263 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
269 int pa_fdsem_after_poll(pa_fdsem
*f
) {
272 pa_assert_se(pa_atomic_dec(&f
->waiting
) >= 1);
276 if (pa_atomic_cmpxchg(&f
->signalled
, 1, 0))