[osx] Added missing timer/clock functions, support Bonjour mDNS on OSX

Added configure checks needed to detect missing functions on OSX
Added compat clock functions using clock_get_time on OSX
Added compat timer functions using clock_gettime and setitimer on OSX
Added byteswap functions on OSX
This commit is contained in:
Scott Shambarger
2017-01-14 00:56:43 -05:00
parent b54d94fda6
commit bb68d59a6e
8 changed files with 1111 additions and 22 deletions

View File

@@ -920,6 +920,183 @@ timespec_cmp(struct timespec time1, struct timespec time2)
return 0;
}
#if defined(HAVE_MACH_CLOCK) || defined(HAVE_MACH_TIMER)
#include <mach/mach_time.h> /* mach_absolute_time */
#include <mach/mach.h> /* host_get_clock_service */
#include <mach/clock.h> /* clock_get_time */
/* mach monotonic clock port */
extern mach_port_t clock_port;
#ifndef HAVE_CLOCK_GETTIME
int
clock_gettime(clockid_t clock_id, struct timespec *tp) {
static int clock_init = 0;
static clock_serv_t clock;
mach_timespec_t mts;
int ret;
if (! clock_init) {
clock_init = 1;
if (host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &clock))
abort(); /* unlikely */
}
if(! tp)
return -1;
switch (clock_id) {
case CLOCK_REALTIME:
/* query mach for calendar time */
ret = clock_get_time(clock, &mts);
if (! ret) {
tp->tv_sec = mts.tv_sec;
tp->tv_nsec = mts.tv_nsec;
}
break;
case CLOCK_MONOTONIC:
/* query mach for monotinic time */
ret = clock_get_time(clock_port, &mts);
if (! ret) {
tp->tv_sec = mts.tv_sec;
tp->tv_nsec = mts.tv_nsec;
}
break;
default:
ret = -1;
break;
}
return ret;
}
int
clock_getres(clockid_t clock_id, struct timespec *res) {
if (! res)
return -1;
/* hardcode ms resolution */
res->tv_sec = 0;
res->tv_nsec = 1000;
return 0;
}
#endif /* HAVE_CLOCK_GETTIME */
#ifndef HAVE_TIMER_SETTIME
#include <sys/time.h> /* ITIMER_REAL */
static uint64_t timer_interval;
static struct timespec timer_expire;
int
timer_create(clockid_t clock_id, void *sevp, timer_t *timer_id) {
if (clock_id != CLOCK_MONOTONIC)
return -1;
if (sevp)
return -1;
/* setitimer only supports one timer */
*timer_id = 0;
timer_expire.tv_sec = 0;
timer_expire.tv_nsec = 0;
return 0;
}
int
timer_delete(timer_t timer_id) {
struct itimerval timerval;
if (timer_id != 0)
return -1;
memset(&timerval, 0, sizeof(struct itimerval));
timer_expire.tv_sec = 0;
timer_expire.tv_nsec = 0;
return setitimer(ITIMER_REAL, &timerval, NULL);
}
int
timer_settime(timer_t timer_id, int flags, const struct itimerspec *tp,
struct itimerspec *old) {
struct itimerval tv;
if (timer_id != 0 || ! tp || old)
return -1;
if (tp->it_value.tv_sec || tp->it_value.tv_nsec) {
/* calc expire */
if (clock_gettime(CLOCK_MONOTONIC, &timer_expire))
return -1;
timer_expire.tv_sec += tp->it_value.tv_sec;
timer_expire.tv_nsec += tp->it_value.tv_nsec;
if (timer_expire.tv_nsec >= 1e9) {
timer_expire.tv_sec++;
timer_expire.tv_nsec -= 1e9;
}
/* record the interval */
timer_interval = tp->it_interval.tv_sec * 1e9;
timer_interval += tp->it_interval.tv_nsec;
}
else {
timer_expire.tv_sec = 0;
timer_expire.tv_nsec = 0;
}
TIMESPEC_TO_TIMEVAL(&(tv.it_value), &(tp->it_value));
TIMESPEC_TO_TIMEVAL(&(tv.it_interval), &(tp->it_interval));
return setitimer(ITIMER_REAL, &tv, NULL);
}
int
timer_getoverrun(timer_t timer_id) {
struct timespec now;
int64_t diff;
if (timer_id != 0)
return -1;
if (timer_expire.tv_sec == 0 && timer_expire.tv_nsec == 0)
return 0;
if (timer_interval == 0)
return 0;
/* calc how much time has elapsed since expiration */
if (clock_gettime(CLOCK_MONOTONIC, &now))
return -1;
diff = (now.tv_sec - timer_expire.tv_sec) * 1e9;
diff += now.tv_nsec - now.tv_nsec;
if (diff < 0)
return 0;
return (int)(diff / timer_interval);
}
#endif /* HAVE_TIMER_SETTIME */
#endif /* HAVE_MACH_CLOCK */
void
fork_mutex_init(pthread_mutex_t *mutex)
{