diff options
-rw-r--r-- | include/gos/chibios.h | 1 | ||||
-rw-r--r-- | include/gos/win32.h | 4 | ||||
-rw-r--r-- | src/gos/chibios.c | 27 | ||||
-rw-r--r-- | src/gos/linux.c | 111 | ||||
-rw-r--r-- | src/gos/win32.c | 16 |
5 files changed, 103 insertions, 56 deletions
diff --git a/include/gos/chibios.h b/include/gos/chibios.h index e9d3e8d2..5cc92010 100644 --- a/include/gos/chibios.h +++ b/include/gos/chibios.h @@ -97,3 +97,4 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_ #endif /* GFX_USE_OS_CHIBIOS */ #endif /* _GOS_CHIBIOS_H */ + diff --git a/include/gos/win32.h b/include/gos/win32.h index 121bdb5a..de29ea3b 100644 --- a/include/gos/win32.h +++ b/include/gos/win32.h @@ -101,8 +101,6 @@ threadreturn_t gfxThreadWait(gfxThreadHandle thread); } #endif - - #endif /* GFX_USE_OS_WIN32 */ - #endif /* _GOS_WIN32_H */ + diff --git a/src/gos/chibios.c b/src/gos/chibios.c index aca1a16e..3af0047b 100644 --- a/src/gos/chibios.c +++ b/src/gos/chibios.c @@ -49,39 +49,47 @@ void *gfxRealloc(void *ptr, size_t oldsz, size_t newsz) { void gfxSleepMilliseconds(delaytime_t ms) { switch(ms) { - case TIME_IMMEDIATE: chThdYield(); return; - case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; - default: chThdSleepMilliseconds(ms); return; + case TIME_IMMEDIATE: chThdYield(); return; + case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; + default: chThdSleepMilliseconds(ms); return; } } void gfxSleepMicroseconds(delaytime_t ms) { switch(ms) { - case TIME_IMMEDIATE: return; - case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; - default: chThdSleepMicroseconds(ms); return; + case TIME_IMMEDIATE: return; + case TIME_INFINITE: chThdSleep(TIME_INFINITE); return; + default: chThdSleepMicroseconds(ms); return; } } + void gfxSemInit(gfxSem *psem, semcount_t val, semcount_t limit) { - if (val > limit) val = limit; + if (val > limit) + val = limit; + psem->limit = limit; chSemInit(&psem->sem, val); } + void gfxSemDestroy(gfxSem *psem) { chSemReset(&psem->sem, 1); } + bool_t gfxSemWait(gfxSem *psem, delaytime_t ms) { if (ms == TIME_INFINITE) { chSemWait(&psem->sem); return TRUE; } + return chSemWaitTimeout(&psem->sem, MS2ST(ms)) != RDY_TIMEOUT; } void gfxSemSignal(gfxSem *psem) { chSysLock(); + if (gfxSemCounterI(psem) < psem->limit) chSemSignalI(&psem->sem); + chSchRescheduleS(); chSysUnlock(); } @@ -97,9 +105,12 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_ return chThdCreateFromHeap(0, stacksz, prio, fn, param); } - if (!stacksz) return NULL; + if (!stacksz) + return NULL; + return chThdCreateStatic(stackarea, stacksz, prio, fn, param); } #endif /* GFX_USE_OS_CHIBIOS */ /** @} */ + diff --git a/src/gos/linux.c b/src/gos/linux.c index 54cadd6a..97409364 100644 --- a/src/gos/linux.c +++ b/src/gos/linux.c @@ -42,13 +42,20 @@ 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; + 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; } } @@ -56,13 +63,20 @@ 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; + 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; } } @@ -70,6 +84,7 @@ systemticks_t gfxSystemTicks(void) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); + return ts.tv_sec * 1000UL + ts.tv_nsec / 1000UL; } @@ -77,14 +92,15 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_ 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. + // 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; } @@ -93,6 +109,7 @@ threadreturn_t gfxThreadWait(gfxThreadHandle thread) { if (pthread_join(thread, &retval)) return 0; + return retval; } @@ -112,45 +129,52 @@ void gfxSemDestroy(gfxSem *pSem) { 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; + 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; + 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); } @@ -162,6 +186,7 @@ semcount_t gfxSemCounter(gfxSem *pSem) { pthread_mutex_lock(&pSem->mtx); res = pSem->cnt; pthread_mutex_unlock(&pSem->mtx); + return res; } diff --git a/src/gos/win32.c b/src/gos/win32.c index 50be42a5..791b8d04 100644 --- a/src/gos/win32.c +++ b/src/gos/win32.c @@ -18,11 +18,13 @@ static HANDLE SystemMutex; void _gosInit(void) { + } void gfxHalt(const char *msg) { if (msg) fprintf(stderr, "%s\n", msg); + ExitProcess(1); } @@ -32,8 +34,13 @@ void gfxSleepMicroseconds(delaytime_t ms) { LARGE_INTEGER t1, t2, tdiff; switch(ms) { - case TIME_IMMEDIATE: return; - case TIME_INFINITE: while(1) Sleep(1000); return; + case TIME_IMMEDIATE: + return; + + case TIME_INFINITE: + while(1) + Sleep(1000); + return; } if (!initflag) { @@ -81,6 +88,7 @@ semcount_t gfxSemCounter(gfxSem *pSem) { NtQuerySemaphore = (_NtQuerySemaphore)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQuerySemaphore"); NtQuerySemaphore(*pSem, 0, &BasicInfo, sizeof(BasicInfo), NULL); + return BasicInfo.CurrentCount; } @@ -90,8 +98,10 @@ gfxThreadHandle gfxThreadCreate(void *stackarea, size_t stacksz, threadpriority_ if (!(thd = CreateThread(NULL, stacksz, fn, param, CREATE_SUSPENDED, NULL))) return FALSE; + SetThreadPriority(thd, prio); ResumeThread(thd); + return thd; } @@ -101,8 +111,10 @@ threadreturn_t gfxThreadWait(gfxThreadHandle thread) { WaitForSingleObject(thread, INFINITE); GetExitCodeThread(thread, &ret); CloseHandle(thread); + return ret; } #endif /* GFX_USE_OS_WIN32 */ /** @} */ + |