From e3545c55bf706984af5962221f95881d868c5407 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 29 Sep 2014 15:45:44 +1000 Subject: Bug fixes for the linux GOS layer. Also add POSIX semaphore implementation. --- src/gos/gfx_linux.c | 171 +++++++++++++++++++++++++++++++--------------------- src/gos/gfx_linux.h | 31 +++++++--- 2 files changed, 127 insertions(+), 75 deletions(-) (limited to 'src/gos') diff --git a/src/gos/gfx_linux.c b/src/gos/gfx_linux.c index fc716ec9..e6fbe26c 100644 --- a/src/gos/gfx_linux.c +++ b/src/gos/gfx_linux.c @@ -14,8 +14,6 @@ #include #include -#include -#include #include #if USE_SCHED_NOT_PTHREAD_YIELD #include @@ -70,16 +68,16 @@ void gfxSleepMilliseconds(delaytime_t ms) { default: ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000; + ts.tv_nsec = (ms % 1000) * 1000000; nanosleep(&ts, 0); return; } } -void gfxSleepMicroseconds(delaytime_t ms) { +void gfxSleepMicroseconds(delaytime_t us) { struct timespec ts; - switch(ms) { + switch(us) { case TIME_IMMEDIATE: linuxyield(); return; @@ -90,8 +88,8 @@ void gfxSleepMicroseconds(delaytime_t ms) { return; default: - ts.tv_sec = ms / 1000000; - ts.tv_nsec = ms % 1000000; + ts.tv_sec = us / 1000000; + ts.tv_nsec = (us % 1000000) * 1000; nanosleep(&ts, 0); return; } @@ -101,8 +99,7 @@ systemticks_t gfxSystemTicks(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - - return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; + return ts.tv_sec * 1000 + ts.tv_nsec / 1000000; } gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { @@ -133,81 +130,119 @@ threadreturn_t gfxThreadWait(gfxThreadHandle thread) { return retval; } -void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { - pthread_mutex_init(&pSem->mtx, 0); - pthread_cond_init(&pSem->cond, 0); - pthread_mutex_lock(&pSem->mtx); - pSem->cnt = val; - pSem->max = limit; - pthread_mutex_unlock(&pSem->mtx); -} - -void gfxSemDestroy(gfxSem *pSem) { - pthread_mutex_destroy(&pSem->mtx); - pthread_cond_destroy(&pSem->cond); -} - -bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { - pthread_mutex_lock(&pSem->mtx); - - switch (ms) { +#if GFX_USE_POSIX_SEMAPHORES + void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { + pSem->max = limit; + sem_init(&pSem->sem, 0, val); + } + void gfxSemDestroy(gfxSem *pSem) { + sem_destroy(&pSem->sem); + } + bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { + switch (ms) { case TIME_INFINITE: - while (!pSem->cnt) - pthread_cond_wait(&pSem->cond, &pSem->mtx); - break; + return sem_wait(&pSem->sem) ? FALSE : TRUE; case TIME_IMMEDIATE: - if (!pSem->cnt) { - pthread_mutex_unlock(&pSem->mtx); - return FALSE; - } - break; + return sem_trywait(&pSem->sem) ? FALSE : TRUE; default: { - struct timeval now; struct timespec tm; - gettimeofday(&now, 0); - tm.tv_sec = now.tv_sec + ms / 1000; - tm.tv_nsec = (now.tv_usec + ms % 1000) * 1000; - while (!pSem->cnt) { - if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm) == ETIMEDOUT) { - pthread_mutex_unlock(&pSem->mtx); - return FALSE; - } - } + clock_gettime(CLOCK_REALTIME, &tm); + tm.tv_sec += ms / 1000; + tm.tv_nsec += (ms % 1000) * 1000000; + return sem_timedwait(&pSem->sem, &tm) ? FALSE : TRUE; } - break; + } } + void gfxSemSignal(gfxSem *pSem) { + if (gfxSemCounter(pSem) < pSem->max) + sem_post(&pSem->sem); + } + semcount_t gfxSemCounter(gfxSem *pSem) { + int res; - pSem->cnt--; - pthread_mutex_unlock(&pSem->mtx); - - return TRUE; -} - -void gfxSemSignal(gfxSem *pSem) { - pthread_mutex_lock(&pSem->mtx); + res = 0; + sem_getvalue(&pSem->sem, &res); + return res; + } +#else + void gfxSemInit(gfxSem *pSem, semcount_t val, semcount_t limit) { + pthread_mutex_init(&pSem->mtx, 0); + pthread_cond_init(&pSem->cond, 0); + pthread_mutex_lock(&pSem->mtx); + pSem->cnt = val; + pSem->max = limit; + pthread_mutex_unlock(&pSem->mtx); + } + void gfxSemDestroy(gfxSem *pSem) { + pthread_mutex_destroy(&pSem->mtx); + pthread_cond_destroy(&pSem->cond); + } + bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { + pthread_mutex_lock(&pSem->mtx); + + switch (ms) { + case TIME_INFINITE: + while (!pSem->cnt) + pthread_cond_wait(&pSem->cond, &pSem->mtx); + break; + + case TIME_IMMEDIATE: + if (!pSem->cnt) { + pthread_mutex_unlock(&pSem->mtx); + return FALSE; + } + break; + + default: + { + struct timespec tm; + + clock_gettime(CLOCK_REALTIME, &tm); + tm.tv_sec += ms / 1000; + tm.tv_nsec += (ms % 1000) * 1000000; + while (!pSem->cnt) { + // We used to test the return value for ETIMEDOUT. This doesn't + // work in some current pthread libraries which return -1 instead + // and set errno to ETIMEDOUT. So, we will return FALSE on any error + // including a ETIMEDOUT. + if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { + pthread_mutex_unlock(&pSem->mtx); + return FALSE; + } + } + } + break; + } - if (pSem->cnt < pSem->max) { - pSem->cnt++; - pthread_cond_signal(&pSem->cond); + pSem->cnt--; + pthread_mutex_unlock(&pSem->mtx); + return TRUE; } + void gfxSemSignal(gfxSem *pSem) { + pthread_mutex_lock(&pSem->mtx); - pthread_mutex_unlock(&pSem->mtx); -} + if (pSem->cnt < pSem->max) { + pSem->cnt++; + pthread_cond_signal(&pSem->cond); + } -semcount_t gfxSemCounter(gfxSem *pSem) { - semcount_t res; + pthread_mutex_unlock(&pSem->mtx); + } + semcount_t gfxSemCounter(gfxSem *pSem) { + semcount_t res; - // The locking is really only required if obtaining the count is a divisible operation - // which it might be on a 8/16 bit processor with a 32 bit semaphore count. - pthread_mutex_lock(&pSem->mtx); - res = pSem->cnt; - pthread_mutex_unlock(&pSem->mtx); + // The locking is really only required if obtaining the count is a divisible operation + // which it might be on a 8/16 bit processor with a 32 bit semaphore count. + pthread_mutex_lock(&pSem->mtx); + res = pSem->cnt; + pthread_mutex_unlock(&pSem->mtx); - return res; -} + return res; + } +#endif // GFX_USE_POSIX_SEMAPHORES #endif /* GFX_USE_OS_LINUX */ diff --git a/src/gos/gfx_linux.h b/src/gos/gfx_linux.h index bd31184e..39cfbc85 100644 --- a/src/gos/gfx_linux.h +++ b/src/gos/gfx_linux.h @@ -10,11 +10,20 @@ #if GFX_USE_OS_LINUX +// We don't put this in the general sys_options.h as it is Linux specific. +#ifndef GFX_USE_POSIX_SEMAPHORES + #define GFX_USE_POSIX_SEMAPHORES TRUE +#endif + #include #include #include #include +#if GFX_USE_POSIX_SEMAPHORES + #include +#endif + /* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ typedef int8_t bool_t; @@ -42,7 +51,6 @@ typedef pthread_mutex_t gfxMutex; #define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) #define gfxSemWaitI(psem) gfxSemWait(psem, TIME_IMMEDIATE) #define gfxSemSignalI(psem) gfxSemSignal(psem) -#define gfxSemCounterI(pSem) ((pSem)->cnt) #define TIME_IMMEDIATE 0 #define TIME_INFINITE ((delaytime_t)-1) @@ -51,12 +59,21 @@ typedef pthread_mutex_t gfxMutex; #define NORMAL_PRIORITY 0 #define HIGH_PRIORITY -10 -typedef struct gfxSem { - pthread_mutex_t mtx; - pthread_cond_t cond; - semcount_t cnt; - semcount_t max; -} gfxSem; +#if GFX_USE_POSIX_SEMAPHORES + typedef struct gfxSem { + sem_t sem; + semcount_t max; + } gfxSem; + #define gfxSemCounterI(psem) gfxSemCounter(psem) +#else + typedef struct gfxSem { + pthread_mutex_t mtx; + pthread_cond_t cond; + semcount_t cnt; + semcount_t max; + } gfxSem; + #define gfxSemCounterI(psem) ((psem)->cnt) +#endif /*===========================================================================*/ /* Function declarations. */ -- cgit v1.2.3 From 3abbf8e1b2bac9ca02ab22d00fad828e5ff54898 Mon Sep 17 00:00:00 2001 From: inmarket Date: Mon, 29 Sep 2014 15:46:08 +1000 Subject: Bug fixes for the OSX GOS layer --- src/gos/gfx_osx.c | 42 +++++++++++++++++------------------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'src/gos') diff --git a/src/gos/gfx_osx.c b/src/gos/gfx_osx.c index f2e58f77..f21b8a75 100644 --- a/src/gos/gfx_osx.c +++ b/src/gos/gfx_osx.c @@ -21,18 +21,6 @@ static gfxMutex SystemMutex; - -void get_ticks(mach_timespec_t *mts){ - clock_serv_t cclock; - //mach_timespec_t mts; - - host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); - clock_get_time(cclock, mts); - mach_port_deallocate(mach_task_self(), cclock); - - -} - void _gosInit(void) { /* No initialization of the operating system itself is needed */ @@ -66,35 +54,35 @@ void gfxSleepMilliseconds(delaytime_t ms) { case TIME_INFINITE: while(1) sleep(60); return; default: ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000; + ts.tv_nsec = (ms % 1000) * 1000000; nanosleep(&ts, 0); return; } } -void gfxSleepMicroseconds(delaytime_t ms) { +void gfxSleepMicroseconds(delaytime_t us) { struct timespec ts; - switch(ms) { + switch(us) { case TIME_IMMEDIATE: gfxYield(); return; case TIME_INFINITE: while(1) sleep(60); return; default: - ts.tv_sec = ms / 1000000; - ts.tv_nsec = ms % 1000000; + ts.tv_sec = us / 1000000; + ts.tv_nsec = (us % 1000000) * 1000; nanosleep(&ts, 0); return; } } systemticks_t gfxSystemTicks(void) { - //struct timespec ts; - //clock_gettime(CLOCK_MONOTONIC, &ts); - - mach_timespec_t ts; - get_ticks(&ts); + mach_timespec_t ts; + clock_serv_t cclock; + host_get_clock_service(mach_host_self(), SYSTEM_CLOCK, &cclock); + clock_get_time(cclock, &ts); + mach_port_deallocate(mach_task_self(), cclock); - return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; + return ts.tv_sec * 1000UL + ts.tv_nsec / 1000000; } gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { @@ -157,9 +145,13 @@ bool_t gfxSemWait(gfxSem *pSem, delaytime_t ms) { gettimeofday(&now, 0); tm.tv_sec = now.tv_sec + ms / 1000; - tm.tv_nsec = (now.tv_usec + ms % 1000) * 1000; + tm.tv_nsec = now.tv_usec * 1000 + (ms % 1000) * 1000000; while (!pSem->cnt) { - if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm) == ETIMEDOUT) { + // We used to test the return value for ETIMEDOUT. This doesn't + // work in some current pthread libraries which return -1 instead + // and set errno to ETIMEDOUT. So, we will return FALSE on any error + // including a ETIMEDOUT. + if (pthread_cond_timedwait(&pSem->cond, &pSem->mtx, &tm)) { pthread_mutex_unlock(&pSem->mtx); return FALSE; } -- cgit v1.2.3