10 #if GOS_NEED_X_THREADS
16 #if !defined(INTERRUPTS_OFF) || !defined(INTERRUPTS_ON)
17 #define INTERRUPTS_OFF()
18 #define INTERRUPTS_ON()
54 gTicks starttm, delay;
63 delay = gDelayForever;
67 if (!delay) delay = 1;
72 while (psem->cnt <= 0) {
107 if (psem->cnt < psem->limit)
116 gTicks starttm, delay;
138 gTicks starttm, delay;
171 typedef struct thread {
172 struct thread * next;
174 #define FLG_THD_ALLOC 0x0001
175 #define FLG_THD_MAIN 0x0002
176 #define FLG_THD_DEAD 0x0004
177 #define FLG_THD_WAIT 0x0008
179 gThreadreturn (*fn)(
void *param);
184 typedef struct threadQ {
189 static threadQ readyQ;
190 static threadQ deadQ;
191 thread * _gfxCurrentThread;
192 static thread mainthread;
194 #undef GFX_THREADS_DONE
196 #if GFX_CPU == GFX_CPU_CORTEX_M0 || GFX_CPU == GFX_CPU_CORTEX_M1
197 #include "gos_x_threads_cortexm01.h"
198 #elif GFX_CPU == GFX_CPU_CORTEX_M3 || GFX_CPU == GFX_CPU_CORTEX_M4 || GFX_CPU == GFX_CPU_CORTEX_M7
199 #include "gos_x_threads_cortexm347.h"
200 #elif GFX_CPU == GFX_CPU_CORTEX_M4_FP || GFX_CPU == GFX_CPU_CORTEX_M7_FP
201 #include "gos_x_threads_cortexm47fp.h"
204 #ifndef GFX_THREADS_DONE
205 #define GFX_THREADS_DONE
217 #if (!defined(setjmp) && !defined(_setjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
218 #define CXT_SAVE setjmp
220 #define CXT_SAVE _setjmp
222 #if (!defined(longjmp) && !defined(_longjmp)) || GFX_COMPILER == GFX_COMPILER_KEIL || GFX_COMPILER == GFX_COMPILER_MINGW32 || GFX_COMPILER == GFX_COMPILER_MINGW64
223 #define CXT_RESTORE longjmp
225 #define CXT_RESTORE _longjmp
230 static jmp_buf maincxt;
253 #if GFX_COMPILER == GFX_COMPILER_MINGW32
255 #define AUTO_DETECT_STACKFRAME GFXOFF
256 #define STACK_DIR_UP GFXOFF
257 #define MASK1 0x00000011
258 #define MASK2 0x00000000
259 #define STACK_BASE 12
260 #define _gfxThreadsInit() mainthread.cxt = maincxt
266 #define AUTO_DETECT_STACKFRAME GFXON
267 #define STACK_DIR_UP stackdirup
268 #define MASK1 jmpmask1
269 #define MASK2 jmpmask2
270 #define STACK_BASE stackbase
273 typedef struct saveloc {
278 static gBool stackdirup;
279 static gU32 jmpmask1;
280 static gU32 jmpmask2;
281 static gMemSize stackbase;
282 static saveloc *pframeinfo;
285 void _gfxGetStackState(
void) {
287 pframeinfo->localptr = (
char *)&c;
288 CXT_SAVE(pframeinfo->cxt);
290 void _gfxGetStackStateInFn(
void) {
295 static void _gfxThreadsInit(
void) {
301 saveloc tmpsaveloc[2];
304 mainthread.cxt = maincxt;
307 pframeinfo = tmpsaveloc;
310 _gfxGetStackStateInFn();
316 stackdirup = pframeinfo[1].localptr > pframeinfo[0].localptr;
317 pout = (
char **)pframeinfo[0].cxt;
318 pin = (
char **)pframeinfo[1].cxt;
319 diff = pframeinfo[0].localptr - pframeinfo[1].localptr;
320 framebase = pframeinfo[0].localptr;
321 jmpmask1 = jmpmask2 = 0;
322 for (i = 0; i <
sizeof(jmp_buf)/
sizeof(
char *); i++, pout++, pin++) {
323 if ((gPtrDiff)(*pout - *pin) == diff) {
327 jmpmask2 |= 1 << (i-32);
330 if (framebase > *pout)
333 if (framebase < *pout)
338 stackbase = stackdirup ? (pframeinfo[0].localptr - framebase) : (framebase - pframeinfo[0].localptr);
344 static void _gfxAdjustCxt(thread *t) {
352 #if AUTO_DETECT_STACKFRAME
354 nf = (
char *)(t) +
sizeof(thread) +
sizeof(jmp_buf) + STACK_BASE;
355 memcpy(t+1, (
char *)&s - STACK_BASE, STACK_BASE+
sizeof(
char *));
357 nf = (
char *)(t) + t->size - (STACK_BASE +
sizeof(
char *));
358 memcpy(nf, &s, STACK_BASE+
sizeof(
char *));
362 nf = (
char *)(t) +
sizeof(thread) +
sizeof(jmp_buf) + STACK_BASE;
363 memcpy(t+1, (
char *)&s - STACK_BASE, STACK_BASE+
sizeof(
char *));
366 nf = (
char *)(t) + t->size - (STACK_BASE +
sizeof(
char *));
367 memcpy(nf, &s, STACK_BASE+
sizeof(
char *));
371 s = (
char **)(t->cxt);
372 diff = nf - (
char *)&s;
375 for (i = MASK1; i ; i >>= 1, s++) {
380 s = (
char **)(t->cxt)+32;
381 for (i = MASK2; i ; i >>= 1, s++) {
387 static void _gfxXSwitch(thread *oldt, thread *newt, gBool doBuildFrame) {
390 if (CXT_SAVE(oldt->cxt))
return;
397 if (CXT_SAVE(newt->cxt)) {
405 gfxThreadExit(_gfxCurrentThread->fn(_gfxCurrentThread->param));
415 CXT_RESTORE(newt->cxt, 1);
418 #define _gfxTaskSwitch(oldt, newt) _gfxXSwitch(oldt, newt, gFalse)
419 #define _gfxStartThread(oldt, newt) _gfxXSwitch(oldt, newt, gTrue)
421 #undef GFX_THREADS_DONE
423 static void Qinit(threadQ * q) {
424 q->head = q->tail = 0;
427 static void Qadd(threadQ * q, thread *t) {
433 q->head = q->tail = t;
436 static thread *Qpop(threadQ * q) {
446 void _gosThreadsInit(
void) {
450 mainthread.size =
sizeof(thread);
451 mainthread.flags = FLG_THD_MAIN;
453 mainthread.param = 0;
457 _gfxCurrentThread = &mainthread;
461 return (
gThread)_gfxCurrentThread;
465 static void cleanUpDeadThreads(
void) {
468 while ((p = Qpop(&deadQ)))
476 cleanUpDeadThreads();
482 Qadd(&readyQ, me = _gfxCurrentThread);
483 _gfxCurrentThread = Qpop(&readyQ);
484 _gfxTaskSwitch(me, _gfxCurrentThread);
488 void gfxThreadExit(gThreadreturn ret) {
492 me = _gfxCurrentThread;
493 me->param = (
void *)ret;
494 me->flags |= FLG_THD_DEAD;
498 if ((me->flags & (FLG_THD_ALLOC|FLG_THD_WAIT)) == FLG_THD_ALLOC)
502 if (!(_gfxCurrentThread = Qpop(&readyQ)))
506 _gfxTaskSwitch(me, _gfxCurrentThread);
517 if (stacksz <
sizeof(thread)+64) {
518 stacksz =
sizeof(thread)+64;
523 t = (thread *)stackarea;
529 t->flags = FLG_THD_ALLOC;
536 me = _gfxCurrentThread;
538 _gfxCurrentThread = t;
540 _gfxStartThread(me, t);
550 if (t == _gfxCurrentThread)
554 t->flags |= FLG_THD_WAIT;
557 while(!(t->flags & FLG_THD_DEAD))
561 t->flags &= ~FLG_THD_WAIT;
564 if (t->flags & FLG_THD_ALLOC)
568 return (gThreadreturn)t->param;
gThreadreturn gfxThreadWait(gThread thread)
Wait for a thread to finish.
void gfxSemSignal(gSem *psem)
Signal a semaphore.
void * gThread
A thread handle.
gTicks gfxSystemTicks(void)
Get the current operating system tick time.
void gfxYield(void)
Yield the current thread.
#define GFX_THREAD_FUNCTION(fnName, param)
Declare a thread function.
void gfxMutexExit(gMutex *pmutex)
Exit the critical code region protected by the mutex.
gTicks gfxMillisecondsToTicks(gDelay ms)
Convert a given number of millseconds to a number of operating system ticks.
gBool gfxSemWait(gSem *psem, gDelay ms)
Wait on a semaphore.
void gfxExit(void)
Exit the GFX application.
void gfxSystemUnlock(void)
Unlock the operating system previous locked by gfxSystemLock()
void gfxSleepMicroseconds(gDelay us)
Put the current thread to sleep for the specified period in microseconds.
void gfxMutexEnter(gMutex *pmutex)
Enter the critical code region protected by the mutex.
gThread gfxThreadMe(void)
Get the current thread handle.
void * gfxAlloc(gMemSize sz)
Allocate memory.
void gfxSystemLock(void)
Lock the operating system to protect a sequence of code.
void gfxMutexInit(gMutex *pmutex)
Initialise a mutex to protect a region of code from other threads.
gThread gfxThreadCreate(void *stackarea, gMemSize stacksz, gThreadpriority prio, GFX_THREAD_FUNCTION((*fn), p), void *param)
Start a new thread.
gBool gfxSemWaitI(gSem *psem)
Test if a wait on a semaphore can be satisfied immediately.
void gfxSemInit(gSem *psem, gSemcount val, gSemcount limit)
Initialise a Counted Semaphore.
void gfxFree(void *ptr)
Free memory.
void gfxSemSignalI(gSem *psem)
Signal a semaphore.
void gfxSleepMilliseconds(gDelay ms)
Put the current thread to sleep for the specified period in milliseconds.