Merge remote branch 'zonque/topic/osx'

This commit is contained in:
Lennart Poettering 2010-01-05 22:52:57 +01:00
commit 6dfb1ee27e
18 changed files with 1723 additions and 86 deletions

View file

@ -37,6 +37,7 @@
#include <CoreServices/CoreServices.h>
#include <mach/mach.h>
#include <mach/mach_time.h>
#include <unistd.h>
#endif
#include <pulse/timeval.h>
@ -54,7 +55,19 @@ pa_usec_t pa_rtclock_age(const struct timeval *tv) {
struct timeval *pa_rtclock_get(struct timeval *tv) {
#if defined(HAVE_CLOCK_GETTIME)
#if defined(OS_IS_DARWIN)
uint64_t val, abs_time = mach_absolute_time();
Nanoseconds nanos;
nanos = AbsoluteToNanoseconds(*(AbsoluteTime *) &abs_time);
val = *(uint64_t *) &nanos;
tv->tv_sec = val / PA_NSEC_PER_SEC;
tv->tv_usec = (val % PA_NSEC_PER_SEC) / PA_NSEC_PER_USEC;
return tv;
#elif defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
#ifdef CLOCK_MONOTONIC
@ -75,52 +88,14 @@ struct timeval *pa_rtclock_get(struct timeval *tv) {
tv->tv_usec = ts.tv_nsec / PA_NSEC_PER_USEC;
return tv;
#elif defined(OS_IS_DARWIN)
static mach_timebase_info_data_t tbi;
uint64_t nticks;
uint64_t time_nsec;
/* Refer Apple ADC QA1398
Also: http://devworld.apple.com/documentation/Darwin/Conceptual/KernelProgramming/services/services.html
Note: argument is timespec NOT timeval (timespec uses nsec, timeval uses usec)
*/
/* try and be a mite efficient - maybe I should keep the N/D as a float !? */
if (tbi.denom == 0)
mach_timebase_info(&tbi);
nticks = mach_absolute_time();
time_nsec = nticks * tbi.numer / tbi.denom; // see above
tv->tv_sec = time_nsec / PA_NSEC_PER_SEC;
tv->tv_usec = time_nsec / PA_NSEC_PER_USEC;
return tv;
#else /* OS_IS_DARWIN */
#endif /* HAVE_CLOCK_GETTIME */
return pa_gettimeofday(tv);
#endif
}
pa_bool_t pa_rtclock_hrtimer(void) {
#if defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
#ifdef CLOCK_MONOTONIC
if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#endif /* CLOCK_MONOTONIC */
pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#elif defined (OS_IS_DARWIN)
#if defined (OS_IS_DARWIN)
mach_timebase_info_data_t tbi;
uint64_t time_nsec;
@ -130,10 +105,22 @@ pa_bool_t pa_rtclock_hrtimer(void) {
time_nsec = tbi.numer / tbi.denom;
return time_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#else /* OS_IS_DARWIN */
return FALSE;
#elif defined(HAVE_CLOCK_GETTIME)
struct timespec ts;
#endif
#ifdef CLOCK_MONOTONIC
if (clock_getres(CLOCK_MONOTONIC, &ts) >= 0)
return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#endif /* CLOCK_MONOTONIC */
pa_assert_se(clock_getres(CLOCK_REALTIME, &ts) == 0);
return ts.tv_sec == 0 && ts.tv_nsec <= (long) (PA_HRTIMER_THRESHOLD_USEC*PA_NSEC_PER_USEC);
#endif /* HAVE_CLOCK_GETTIME */
return FALSE;
}
#define TIMER_SLACK_NS (int) ((500 * PA_NSEC_PER_USEC))

View file

@ -33,6 +33,7 @@
#include <pulse/i18n.h>
#include <pulse/xmalloc.h>
#include <pulsecore/poll.h>
#include <pulsecore/mutex.h>
#include <pulsecore/thread.h>
#include <pulsecore/core-util.h>
@ -182,7 +183,7 @@ static void wait_for_ping(void) {
pfd.fd = pipe_fd[0];
pfd.events = POLLIN;
if ((k = poll(&pfd, 1, -1)) != 1) {
if ((k = pa_poll(&pfd, 1, -1)) != 1) {
pa_assert(k < 0);
pa_assert(errno == EINTR);
} else if ((s = read(pipe_fd[0], &x, 1)) != 1) {

View file

@ -35,6 +35,10 @@
#include <config.h>
#endif
#ifdef HAVE_SYS_IOCTL_H
#include <sys/ioctl.h>
#endif
#include <errno.h>
#ifdef HAVE_SYS_SELECT_H
@ -43,19 +47,26 @@
#include "winsock.h"
#ifndef HAVE_POLL_H
#include <pulsecore/core-util.h>
#include <pulse/util.h>
#include "poll.h"
int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
/* Mac OSX fails to implement poll() in a working way since 10.4. IOW, for
* several years. We need to enable a dirty workaround and emulate that call
* with select(), just like for Windows. sic! */
#if !defined(HAVE_POLL_H) || defined(OS_IS_DARWIN)
int pa_poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
struct timeval tv;
fd_set rset, wset, xset;
struct pollfd *f;
int ready;
int maxfd = 0;
#ifdef OS_IS_WIN32
char data[64];
#endif
FD_ZERO (&rset);
FD_ZERO (&wset);
@ -98,6 +109,7 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
ready = select ((SELECT_TYPE_ARG1) maxfd + 1, SELECT_TYPE_ARG234 &rset,
SELECT_TYPE_ARG234 &wset, SELECT_TYPE_ARG234 &xset,
SELECT_TYPE_ARG5 (timeout == -1 ? NULL : &tv));
if ((ready == -1) && (errno == EBADF)) {
ready = 0;
@ -160,6 +172,8 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
#endif
if (ready > 0) {
int r;
ready = 0;
for (f = fds; f < &fds[nfds]; ++f) {
f->revents = 0;
@ -167,6 +181,18 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
if (FD_ISSET (f->fd, &rset)) {
/* support for POLLHUP. An hung up descriptor does not
increase the return value! */
#ifdef OS_IS_DARWIN
/* There is a bug in Mac OS X that causes it to ignore MSG_PEEK
* for some kinds of descriptors. Detect if this descriptor is a
* connected socket, a server socket, or something else using a
* 0-byte recv, and use ioctl(2) to detect POLLHUP. */
r = recv(f->fd, NULL, 0, MSG_PEEK);
if (r == 0 || (r < 0 && errno == ENOTSOCK))
ioctl(f->fd, FIONREAD, &r);
if (r == 0)
f->revents |= POLLHUP;
#else /* !OS_IS_DARWIN */
if (recv (f->fd, data, 64, MSG_PEEK) == -1) {
if (errno == ESHUTDOWN || errno == ECONNRESET ||
errno == ECONNABORTED || errno == ENETRESET) {
@ -174,6 +200,7 @@ int poll (struct pollfd *fds, unsigned long int nfds, int timeout) {
f->revents |= POLLHUP;
}
}
#endif
if (f->revents == 0)
f->revents |= POLLIN;

View file

@ -24,6 +24,10 @@
Copyright (C) 1994,96,97,98,99,2000,2001,2004 Free Software Foundation, Inc.
***/
#if defined(HAVE_POLL_H)
#include <poll.h>
#else
/* Event types that can be polled for. These bits may be set in `events'
to indicate the interesting event types; they will appear in `revents'
to indicate the status of the file descriptor. */
@ -38,10 +42,6 @@
#define POLLHUP 0x010 /* Hung up. */
#define POLLNVAL 0x020 /* Invalid polling request. */
/* Type used for the number of file descriptors. */
typedef unsigned long int nfds_t;
/* Data structure describing a polling request. */
struct pollfd
{
@ -50,9 +50,17 @@ struct pollfd
short int revents; /* Types of events that actually occurred. */
};
/* Poll the file descriptors described by the NFDS structures starting at
FDS. If TIMEOUT is nonzero and not -1, allow TIMEOUT milliseconds for
an event to occur; if TIMEOUT is -1, block until an event occurs.
Returns the number of file descriptors with events, zero if timed out,
or -1 for errors. */
extern int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout);
#endif /* HAVE_POLL_H */
#if defined(HAVE_POLL_H) && !defined(OS_IS_DARWIN)
#define pa_poll(fds,nfds,timeout) poll((fds),(nfds),(timeout))
#else
int pa_poll (struct pollfd *fds, unsigned long nfds, int timeout);
#endif

View file

@ -30,15 +30,10 @@
#include <string.h>
#include <errno.h>
#ifdef HAVE_POLL_H
#include <poll.h>
#else
#include <pulsecore/poll.h>
#endif
#include <pulse/xmalloc.h>
#include <pulse/timeval.h>
#include <pulsecore/poll.h>
#include <pulsecore/core-error.h>
#include <pulsecore/core-rtclock.h>
#include <pulsecore/macro.h>
@ -321,7 +316,7 @@ int pa_rtpoll_run(pa_rtpoll *p, pa_bool_t wait_op) {
r = ppoll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? &ts : NULL, NULL);
}
#else
r = poll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1);
r = pa_poll(p->pollfd, p->n_pollfd_used, (!wait_op || p->quit || p->timer_enabled) ? (int) ((timeout.tv_sec*1000) + (timeout.tv_usec / 1000)) : -1);
#endif
p->timer_elapsed = r == 0;