Fixes to the Raw32 threading.

Optimisation of the RAM it uses for stack frame autodetection.
ugfx_release_2.6
inmarket 2013-12-21 13:25:01 +10:00
parent 983342b001
commit 0c854f099f
1 changed files with 55 additions and 62 deletions

View File

@ -403,24 +403,32 @@ void gfxSleepMicroseconds(delaytime_t ms) {
/** /**
* There are some compilers we know how they store the jmpbuf. For those * There are some compilers we know how they store the jmpbuf. For those
* we can use the constant MASK1 and MASK2. For others we have to "auto-detect". * we can use the constant macro definitions. For others we have to "auto-detect".
* Auto-detection is hairy and there is no guarantee it will work on all architectures. * Auto-detection is hairy and there is no guarantee it will work on all architectures.
* For those it doesn't - read the compiler manuals and the library source code to * For those it doesn't - read the compiler manuals and the library source code to
* work out the correct MASK values. * work out the correct macro values.
* Using the debugger to work out the values for your compiler and putting them here * You can use the debugger to work out the values for your compiler and put them here.
* also saves a nice block of RAM. * Defining these macros as constant values makes the system behaviour guaranteed but also
* makes your code compiler and cpu architecture dependant.
*/ */
#if 0 #if 0
#define STACK_DIR_UP FALSE // usually false as most stacks grow down // Define your compiler constant values here.
#define MASK1 somevalue1 // These example values are for mingw32 compiler (x86).
#define MASK2 somevalue2 // optional #define AUTO_DETECT_MASK FALSE
#define STACK_BASE someindex #define STACK_DIR_UP FALSE
#define MASK1 0x00000011
#define MASK2 0x00000000
#define STACK_BASE 9
#else #else
#define AUTO_DETECT_MASK TRUE #define AUTO_DETECT_MASK TRUE
#define STACK_DIR_UP stackdirup #define STACK_DIR_UP stackdirup // TRUE if the stack grow up instead of down
#define MASK1 jmpmask1 #define MASK1 jmpmask1 // The 1st mask of jmp_buf elements that need relocation
#define MASK2 jmpmask2 #define MASK2 jmpmask2 // The 2nd mask of jmp_buf elements that need relocation
#define STACK_BASE stackbase #define STACK_BASE stackbase // The base of the stack frame relative to the local variables
static bool_t stackdirup;
static uint32_t jmpmask1;
static uint32_t jmpmask2;
static size_t stackbase;
#endif #endif
#include <setjmp.h> /* jmp_buf, setjmp(), longjmp() */ #include <setjmp.h> /* jmp_buf, setjmp(), longjmp() */
@ -473,7 +481,7 @@ static void Qinit(threadQ * q) {
static void Qadd(threadQ * q, thread *t) { static void Qadd(threadQ * q, thread *t) {
t->next = 0; t->next = 0;
if (q->tail) { if (q->head) {
q->tail->next = t; q->tail->next = t;
q->tail = t; q->tail = t;
} else } else
@ -491,47 +499,27 @@ static thread *Qpop(threadQ * q) {
} }
#if AUTO_DETECT_MASK #if AUTO_DETECT_MASK
static char * lowptr; // A pointer to somewhere low in the stack frame // The structure for the saved stack frame information
static char * highptr; // A pointer to somewhere high in the stack frame
// The saved information on a stack frame
typedef struct saveloc { typedef struct saveloc {
char * localptr; char * localptr;
jmp_buf cxt; jmp_buf cxt;
} saveloc; } saveloc;
static saveloc infn; // The saved stack frame info inside a function // A pointer to our auto-detection buffer.
static saveloc outfn; // The saved stack frame info outside a function static saveloc *pframeinfo;
static saveloc *saveptr; // Which saved stack frame variable we are currently using
// Where we save all the information
static bool_t stackdirup; // TRUE if the stack grow up instead of down
static uint32_t jmpmask1; // The 1st mask of jmp_buf elements that need relocation
static uint32_t jmpmask2; // The 2nd mask of jmp_buf elements that need relocation
static size_t stackbase; // The base of the stack frame relative to the local variables
/* These functions are not static to prevent the compiler removing them as functions */ /* These functions are not static to prevent the compiler removing them as functions */
void get_highptr(void) {
char c;
highptr = &c;
}
void test_stack(void) {
char c;
saveptr->localptr = (char *)&c;
_setjmp(saveptr->cxt);
get_highptr();
}
void get_stack_state(void) { void get_stack_state(void) {
char c; char c;
lowptr = &c; pframeinfo->localptr = (char *)&c;
test_stack(); _setjmp(pframeinfo->cxt);
} }
void get_stack_state_in_fn(void) { void get_stack_state_in_fn(void) {
pframeinfo++;
get_stack_state(); get_stack_state();
pframeinfo--;
} }
#endif #endif
@ -545,28 +533,32 @@ static void _gosThreadsInit(void) {
current->param = 0; current->param = 0;
#if AUTO_DETECT_MASK #if AUTO_DETECT_MASK
// Get details of the stack frame from within a function
saveptr = &infn;
get_stack_state_in_fn();
// Get details of the stack frame outside the function
saveptr = &outfn;
get_stack_state();
/* stack direction */
stackdirup = highptr > lowptr; // Can we also test infn.localptr > outfn.localptr?
/* study the jump buffer */
{ {
uint32_t i; uint32_t i;
char ** pout; char ** pout;
char ** pin; char ** pin;
size_t diff = outfn.localptr - infn.localptr; size_t diff;
char * min_frame = outfn.localptr; char * framebase;
// Allocate a buffer to store our test data
pframeinfo = (saveloc *)gfxAlloc(sizeof(saveloc)*2);
// Get details of the stack frame from within a function
get_stack_state_in_fn();
// Get details of the stack frame outside the function
get_stack_state();
/* stack direction */
stackdirup = pframeinfo[1].localptr > pframeinfo[0].localptr;
/* study the jump buffer */
diff = pframeinfo[0].localptr - pframeinfo[1].localptr;
framebase = pframeinfo[0].localptr;
/* following line views jump buffer as array of long int */ /* following line views jump buffer as array of long int */
pout = (char **)outfn.cxt; pout = (char **)pframeinfo[0].cxt;
pin = (char **)infn.cxt; pin = (char **)pframeinfo[1].cxt;
jmpmask1 = jmpmask2 = 0; jmpmask1 = jmpmask2 = 0;
if (diff) { if (diff) {
@ -579,12 +571,12 @@ static void _gosThreadsInit(void) {
jmpmask2 |= 1 << (i-32); jmpmask2 |= 1 << (i-32);
if (stackdirup) { if (stackdirup) {
if (min_frame > *pout) { if (framebase > *pout) {
min_frame = *pout; framebase = *pout;
} }
} else { } else {
if (min_frame < *pout) { if (framebase < *pout) {
min_frame = *pout; framebase = *pout;
} }
} }
} }
@ -592,10 +584,11 @@ static void _gosThreadsInit(void) {
} }
if (stackdirup) { if (stackdirup) {
stackbase = outfn.localptr - min_frame; stackbase = pframeinfo[0].localptr - framebase;
} else { } else {
stackbase = min_frame - outfn.localptr; stackbase = framebase - pframeinfo[0].localptr;
} }
gfxFree(pframeinfo);
} }
#endif #endif
} }