From 3eb2f4bb976a42e3a5e2cd3933400d9d3c20c82c Mon Sep 17 00:00:00 2001 From: Joel Bodenmann Date: Tue, 23 Jul 2013 00:47:42 +0200 Subject: [PATCH] POSIX port now became Linux and OSX --- include/gos/linux.h | 96 ++++++++++++++++++++++ include/gos/osx.h | 97 ++++++++++++++++++++++ src/gos/linux.c | 170 +++++++++++++++++++++++++++++++++++++++ src/gos/osx.c | 191 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 554 insertions(+) create mode 100644 include/gos/linux.h create mode 100644 include/gos/osx.h create mode 100644 src/gos/linux.c create mode 100644 src/gos/osx.c diff --git a/include/gos/linux.h b/include/gos/linux.h new file mode 100644 index 00000000..6653c81c --- /dev/null +++ b/include/gos/linux.h @@ -0,0 +1,96 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file include/gos/linux.h + * @brief GOS - Operating System Support header file for POSIX. + */ + +#ifndef _GOS_LINUX_H +#define _GOS_LINUX_H + +#if GFX_USE_OS_LINUX + +#include +#include +#include + +/* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ + +typedef int8_t bool_t; +typedef unsigned long systemticks_t; +typedef void * threadreturn_t; +typedef unsigned long delaytime_t; +typedef pthread_t gfxThreadHandle; +typedef int threadpriority_t; +typedef uint32_t semcount_t; +typedef pthread_mutex_t gfxMutex; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; + +#define gfxExit() exit(0) +#define gfxAlloc(sz) malloc(sz) +#define gfxRealloc(p,osz,nsz) realloc(p, nsz) +#define gfxFree(ptr) free(ptr) +#define gfxMillisecondsToTicks(ms) (ms) +#define gfxYield() pthread_yield() +#define gfxThreadMe() pthread_self() +#define gfxThreadClose(th) {} +#define gfxMutexInit(pmtx) pthread_mutex_init(pmtx, 0) +#define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) +#define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) +#define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) +#define gfxSemSignalI(psem) gfxSemSignal(psem) +#define gfxSemCounterI(pSem) ((pSem)->cnt) + + +#define FALSE 0 +#define TRUE 1 +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE ((delaytime_t)-1) +#define MAX_SEMAPHORE_COUNT ((semcount_t)-1) +#define LOW_PRIORITY 10 +#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; + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void gfxHalt(const char *msg); +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); +systemticks_t gfxSystemTicks(void); +void gfxSystemLock(void); +void gfxSystemUnlock(void); +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); +void gfxSemDestroy(gfxSem *psem); +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); +void gfxSemSignal(gfxSem *psem); +semcount_t gfxSemCounter(gfxSem *pSem); +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +threadreturn_t gfxThreadWait(gfxThreadHandle thread); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_LINUX */ + +#endif /* _GOS_LINUX_H */ diff --git a/include/gos/osx.h b/include/gos/osx.h new file mode 100644 index 00000000..a181c2c6 --- /dev/null +++ b/include/gos/osx.h @@ -0,0 +1,97 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file include/gos/osx.h + * @brief GOS - Operating System Support header file for POSIX. + */ + +#ifndef _GOS_OSX_H +#define _GOS_OSX_H + +#if GFX_USE_OS_OSX + +#include +#include +#include + +/* Already defined int8_t, uint8_t, int16_t, uint16_t, int32_t, uint32_t, size_t */ + +typedef int8_t bool_t; +typedef unsigned long systemticks_t; +typedef void * threadreturn_t; +typedef unsigned long delaytime_t; +typedef pthread_t gfxThreadHandle; +typedef int threadpriority_t; +typedef uint32_t semcount_t; +typedef pthread_mutex_t gfxMutex; + +#define DECLARE_THREAD_FUNCTION(fnName, param) threadreturn_t fnName(void *param) +#define DECLARE_THREAD_STACK(name, sz) uint8_t name[0]; + +#define gfxExit() exit(0) +#define gfxAlloc(sz) malloc(sz) +#define gfxRealloc(p,osz,nsz) realloc(p, nsz) +#define gfxFree(ptr) free(ptr) +#define gfxMillisecondsToTicks(ms) (ms) +#define gfxYield() sched_yield() +#define gfxThreadMe() pthread_self() +#define gfxThreadClose(th) {} +#define gfxMutexInit(pmtx) pthread_mutex_init(pmtx, 0) +#define gfxMutexDestroy(pmtx) pthread_mutex_destroy(pmtx) +#define gfxMutexEnter(pmtx) pthread_mutex_lock(pmtx) +#define gfxMutexExit(pmtx) pthread_mutex_unlock(pmtx) +#define gfxSemSignalI(psem) gfxSemSignal(psem) +#define gfxSemCounterI(pSem) ((pSem)->cnt) + + +#define FALSE 0 +#define TRUE 1 +#define TIME_IMMEDIATE 0 +#define TIME_INFINITE ((delaytime_t)-1) +#define MAX_SEMAPHORE_COUNT ((semcount_t)-1) +#define LOW_PRIORITY 10 +#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; + +/*===========================================================================*/ +/* Function declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + +void gfxHalt(const char *msg); +void gfxSleepMilliseconds(delaytime_t ms); +void gfxSleepMicroseconds(delaytime_t ms); +systemticks_t gfxSystemTicks(void); +void gfxSystemLock(void); +void gfxSystemUnlock(void); +void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit); +void gfxSemDestroy(gfxSem *psem); +bool_t gfxSemWait(gfxSem *psem, delaytime_t ms); +void gfxSemSignal(gfxSem *psem); +semcount_t gfxSemCounter(gfxSem *pSem); +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param); +threadreturn_t gfxThreadWait(gfxThreadHandle thread); + +#ifdef __cplusplus +} +#endif + +#endif /* GFX_USE_OS_OSX */ + +#endif /* _GOS_OSX_H */ + diff --git a/src/gos/linux.c b/src/gos/linux.c new file mode 100644 index 00000000..ef0fea97 --- /dev/null +++ b/src/gos/linux.c @@ -0,0 +1,170 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file src/gos/osx.c + * @brief GOS ChibiOS Operating System support. + */ +#include "gfx.h" + +#if GFX_USE_OS_OSX + +#include +#include +#include +#include + +static gfxMutex SystemMutex; + +void _gosInit(void) { + gfxMutexInit(&SystemMutex); +} + +void gfxSystemLock(void) { + gfxMutexEnter(&SystemMutex); +} + +void gfxSystemUnlock(void) { + gfxMutexExit(&SystemMutex); +} + +void gfxHalt(const char *msg) { + if (msg) + fprintf(stderr, "%s\n", msg); + exit(1); +} + +void gfxSleepMilliseconds(delaytime_t ms) { + struct timespec ts; + + switch(ms) { + case TIME_IMMEDIATE: pthread_yield(); return; + case TIME_INFINITE: while(1) sleep(60); return; + default: + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000; + nanosleep(&ts, 0); + return; + } +} + +void gfxSleepMicroseconds(delaytime_t ms) { + struct timespec ts; + + switch(ms) { + case TIME_IMMEDIATE: pthread_yield(); return; + case TIME_INFINITE: while(1) sleep(60); return; + default: + ts.tv_sec = ms / 1000000; + ts.tv_nsec = ms % 1000000; + nanosleep(&ts, 0); + return; + } +} + +systemticks_t gfxSystemTicks(void) { + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { + gfxThreadHandle th; + + // Implementing priority with pthreads is a rats nest that is also pthreads implementation dependent. + // Only some pthreads schedulers support it, some implementations use the operating system process priority mechanisms. + // Even those that do support it can have different ranges of priority and "normal" priority is an undefined concept. + // Across different UNIX style operating systems things can be very different (let alone OS's such as Windows). + // Even just Linux changes the way priority works with different kernel schedulers and across kernel versions. + // For these reasons we ignore the priority. + + if (pthread_create(&th, 0, fn, param)) + return 0; + return th; +} + +threadreturn_t gfxThreadWait(gfxThreadHandle thread) { + threadreturn_t retval; + + if (pthread_join(thread, &retval)) + return 0; + 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) { + 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 timeval now; + struct timespec tm; + + gettimeofday(&now); + 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; + } + } + } + break; + } + pSem->cnt--; + pthread_mutex_unlock(&pSem->mtx); + return TRUE; +} + +void gfxSemSignal(gfxSem *pSem) { + pthread_mutex_lock(&pSem->mtx); + if (pSem->cnt < pSem->max) { + pSem->cnt++; + pthread_cond_signal(&pSem->cond); + } + 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); + return res; +} + +#endif /* GFX_USE_OS_OSX */ +/** @} */ + diff --git a/src/gos/osx.c b/src/gos/osx.c new file mode 100644 index 00000000..3692fe5e --- /dev/null +++ b/src/gos/osx.c @@ -0,0 +1,191 @@ +/* + * This file is subject to the terms of the GFX License. If a copy of + * the license was not distributed with this file, you can obtain one at: + * + * http://ugfx.org/license.html + */ + +/** + * @file src/gos/osx.c + * @brief GOS ChibiOS Operating System support. + */ +#include "gfx.h" + +#if GFX_USE_OS_OSX + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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) { + gfxMutexInit(&SystemMutex); +} + +void gfxSystemLock(void) { + gfxMutexEnter(&SystemMutex); +} + +void gfxSystemUnlock(void) { + gfxMutexExit(&SystemMutex); +} + +void gfxHalt(const char *msg) { + if (msg) + fprintf(stderr, "%s\n", msg); + exit(1); +} + +void gfxSleepMilliseconds(delaytime_t ms) { + struct timespec ts; + + switch(ms) { + case TIME_IMMEDIATE: gfxYield(); return; + case TIME_INFINITE: while(1) sleep(60); return; + default: + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000; + nanosleep(&ts, 0); + return; + } +} + +void gfxSleepMicroseconds(delaytime_t ms) { + struct timespec ts; + + switch(ms) { + case TIME_IMMEDIATE: gfxYield(); return; + case TIME_INFINITE: while(1) sleep(60); return; + default: + ts.tv_sec = ms / 1000000; + ts.tv_nsec = ms % 1000000; + nanosleep(&ts, 0); + return; + } +} + +systemticks_t gfxSystemTicks(void) { + //struct timespec ts; + //clock_gettime(CLOCK_MONOTONIC, &ts); + + mach_timespec_t ts; + get_ticks(&ts); + + + return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; +} + +gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_t prio, DECLARE_THREAD_FUNCTION((*fn),p), void *param) { + gfxThreadHandle th; + + // Implementing priority with pthreads is a rats nest that is also pthreads implementation dependent. + // Only some pthreads schedulers support it, some implementations use the operating system process priority mechanisms. + // Even those that do support it can have different ranges of priority and "normal" priority is an undefined concept. + // Across different UNIX style operating systems things can be very different (let alone OS's such as Windows). + // Even just Linux changes the way priority works with different kernel schedulers and across kernel versions. + // For these reasons we ignore the priority. + + if (pthread_create(&th, 0, fn, param)) + return 0; + return th; +} + +threadreturn_t gfxThreadWait(gfxThreadHandle thread) { + threadreturn_t retval; + + if (pthread_join(thread, &retval)) + return 0; + 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) { + 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 timeval now; + struct timespec tm; + + gettimeofday(&now, NULL); + 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; + } + } + } + break; + } + pSem->cnt--; + pthread_mutex_unlock(&pSem->mtx); + return TRUE; +} + +void gfxSemSignal(gfxSem *pSem) { + pthread_mutex_lock(&pSem->mtx); + if (pSem->cnt < pSem->max) { + pSem->cnt++; + pthread_cond_signal(&pSem->cond); + } + 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); + return res; +} + +#endif /* GFX_USE_OS_OSX */ +/** @} */ +