ddekit:use ucontext to switch threads
Use getcontext/makecontext and setcontext to create/modify and switch thread when using ddekit. Change-Id: I485ad61cb2eb5b8e7b486775f282ff6501912dfd
This commit is contained in:
parent
4dafcd9245
commit
1035348df8
|
@ -5,11 +5,14 @@
|
||||||
#include <ddekit/panic.h>
|
#include <ddekit/panic.h>
|
||||||
#include <ddekit/timer.h>
|
#include <ddekit/timer.h>
|
||||||
|
|
||||||
|
|
||||||
#ifdef DDEBUG_LEVEL_THREAD
|
#ifdef DDEBUG_LEVEL_THREAD
|
||||||
#undef DDEBUG
|
#undef DDEBUG
|
||||||
#define DDEBUG DDEBUG_LEVEL_THREAD
|
#define DDEBUG DDEBUG_LEVEL_THREAD
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
//#define DDEBUG DDEBUG_VERBOSE
|
||||||
|
|
||||||
#include "debug.h"
|
#include "debug.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "thread.h"
|
#include "thread.h"
|
||||||
|
@ -80,7 +83,7 @@ ddekit_thread_create(void (*fun)(void *), void *arg, const char *name)
|
||||||
{
|
{
|
||||||
ddekit_thread_t *th =
|
ddekit_thread_t *th =
|
||||||
(ddekit_thread_t *) ddekit_simple_malloc(sizeof(ddekit_thread_t));
|
(ddekit_thread_t *) ddekit_simple_malloc(sizeof(ddekit_thread_t));
|
||||||
|
memset(th,0,sizeof(ddekit_thread_t));
|
||||||
strncpy(th->name, name, DDEKIT_THREAD_NAMELEN);
|
strncpy(th->name, name, DDEKIT_THREAD_NAMELEN);
|
||||||
th->name[DDEKIT_THREAD_NAMELEN-1] = 0;
|
th->name[DDEKIT_THREAD_NAMELEN-1] = 0;
|
||||||
|
|
||||||
|
@ -94,32 +97,14 @@ ddekit_thread_create(void (*fun)(void *), void *arg, const char *name)
|
||||||
th->next = NULL;
|
th->next = NULL;
|
||||||
th->sleep_sem = ddekit_sem_init(0);
|
th->sleep_sem = ddekit_sem_init(0);
|
||||||
|
|
||||||
|
/* Setup thread context */
|
||||||
/* setup stack */
|
th->ctx.uc_flags |= _UC_IGNSIGM | _UC_IGNFPU;
|
||||||
|
if (getcontext(&th->ctx) != 0) {
|
||||||
void **ptr = (void **)(th->stack + DDEKIT_THREAD_STACKSIZE);
|
panic("ddekit thread create thread getcontext error");
|
||||||
*(--ptr) = th;
|
}
|
||||||
--ptr;
|
th->ctx.uc_stack.ss_sp = th->stack;/* makecontext will determine sp */
|
||||||
--ptr;
|
th->ctx.uc_stack.ss_size = DDEKIT_THREAD_STACKSIZE;
|
||||||
|
makecontext(&th->ctx,_ddekit_thread_start,1 /* argc */,th /* pass thread as argument */);
|
||||||
/* TAKEN FROM P_THREAD (written by david?)*/
|
|
||||||
#ifdef __ACK__
|
|
||||||
th->jb[0].__pc = _ddekit_thread_start;
|
|
||||||
th->jb[0].__sp = ptr;
|
|
||||||
#else /* !__ACK__ */
|
|
||||||
#include <sys/jmp_buf.h>
|
|
||||||
#if defined(JB_PC) && defined(JB_SP)
|
|
||||||
/* um, yikes. */
|
|
||||||
|
|
||||||
*((void (**)(void))(&((char *)th->jb)[JB_PC])) =
|
|
||||||
(void *)_ddekit_thread_start;
|
|
||||||
|
|
||||||
*((void **)(&((char *)th->jb)[JB_SP])) = ptr;
|
|
||||||
#else
|
|
||||||
#error "Unsupported Minix architecture"
|
|
||||||
#endif
|
|
||||||
#endif /* !__ACK__ */
|
|
||||||
|
|
||||||
DDEBUG_MSG_VERBOSE("created thread %s, stack at: %p\n", name,
|
DDEBUG_MSG_VERBOSE("created thread %s, stack at: %p\n", name,
|
||||||
th->stack + DDEKIT_THREAD_STACKSIZE);
|
th->stack + DDEKIT_THREAD_STACKSIZE);
|
||||||
_ddekit_thread_enqueue(th);
|
_ddekit_thread_enqueue(th);
|
||||||
|
@ -159,7 +144,7 @@ ddekit_thread_t *ddekit_thread_myself(void)
|
||||||
ddekit_thread_t *ddekit_thread_setup_myself(const char *name) {
|
ddekit_thread_t *ddekit_thread_setup_myself(const char *name) {
|
||||||
ddekit_thread_t *th =
|
ddekit_thread_t *th =
|
||||||
(ddekit_thread_t *) ddekit_simple_malloc(sizeof(ddekit_thread_t));
|
(ddekit_thread_t *) ddekit_simple_malloc(sizeof(ddekit_thread_t));
|
||||||
|
memset(th,0,sizeof(ddekit_thread_t));
|
||||||
strncpy(th->name, name, DDEKIT_THREAD_NAMELEN);
|
strncpy(th->name, name, DDEKIT_THREAD_NAMELEN);
|
||||||
th->name[DDEKIT_THREAD_NAMELEN-1] = 0;
|
th->name[DDEKIT_THREAD_NAMELEN-1] = 0;
|
||||||
th->stack = NULL;
|
th->stack = NULL;
|
||||||
|
@ -341,14 +326,30 @@ void _ddekit_thread_schedule()
|
||||||
|
|
||||||
/* get our tcb */
|
/* get our tcb */
|
||||||
ddekit_thread_t * th = current;
|
ddekit_thread_t * th = current;
|
||||||
|
volatile int is_callback;
|
||||||
|
|
||||||
#if DDEBUG >= 4
|
#if DDEBUG >= 4
|
||||||
_ddekit_print_backtrace(th);
|
_ddekit_print_backtrace(th);
|
||||||
#endif
|
#endif
|
||||||
|
/* getcontext saves the current context in ctx. When setcontext is called
|
||||||
|
* with that ctx it will return execution at getcontext here. To
|
||||||
|
* discriminate between the initial call to getcontext that simply returns
|
||||||
|
* and the situation where getcontext returns because of a setcontext call
|
||||||
|
* we use the is_callback variable.
|
||||||
|
*
|
||||||
|
* When the program flow passes via the assignment bellow it will enter
|
||||||
|
* the scheduling loop and set is_callback to 1. When the function returns
|
||||||
|
* because of a setcontext call the program skip the scheduling and return
|
||||||
|
* from this method to continue normal execution.
|
||||||
|
*/
|
||||||
|
is_callback =0;
|
||||||
/* save our context */
|
/* save our context */
|
||||||
if (_setjmp(th->jb) == 0) {
|
th->ctx.uc_flags |= _UC_IGNSIGM | _UC_IGNFPU;
|
||||||
|
if (getcontext(&th->ctx) != 0){
|
||||||
|
panic("ddekit thread schedule getcontext error");
|
||||||
|
}
|
||||||
|
if (is_callback == 0) {
|
||||||
|
is_callback = 1;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* find a runnable thread */
|
/* find a runnable thread */
|
||||||
|
@ -365,7 +366,7 @@ void _ddekit_thread_schedule()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (current == NULL) {
|
if (current == NULL) {
|
||||||
ddekit_panic("No runable threads?!");
|
ddekit_panic("No runnable threads?!");
|
||||||
}
|
}
|
||||||
|
|
||||||
DDEBUG_MSG_VERBOSE("switching to id: %d name %s, prio: %d",
|
DDEBUG_MSG_VERBOSE("switching to id: %d name %s, prio: %d",
|
||||||
|
@ -373,8 +374,14 @@ void _ddekit_thread_schedule()
|
||||||
#if DDEBUG >= 4
|
#if DDEBUG >= 4
|
||||||
_ddekit_print_backtrace(current);
|
_ddekit_print_backtrace(current);
|
||||||
#endif
|
#endif
|
||||||
_longjmp(current->jb, 1);
|
//th->ctx.uc_flags |= _UC_IGNSIGM | _UC_IGNFPU;
|
||||||
|
if (setcontext(¤t->ctx) == -1){
|
||||||
|
panic("ddekit threading setcontext error");
|
||||||
|
}
|
||||||
|
panic("unreachable code");
|
||||||
}
|
}
|
||||||
|
DDEBUG_MSG_VERBOSE("continuing thread execution id: %d name %s, prio: %d",
|
||||||
|
current->id, current->name, current->prio);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +417,7 @@ void _ddekit_thread_enqueue(ddekit_thread_t *th)
|
||||||
void _ddekit_thread_set_myprio(int prio)
|
void _ddekit_thread_set_myprio(int prio)
|
||||||
{
|
{
|
||||||
DDEBUG_MSG_VERBOSE("changing thread prio, id: %d name %s, old prio: %d, "
|
DDEBUG_MSG_VERBOSE("changing thread prio, id: %d name %s, old prio: %d, "
|
||||||
"new prio: %d", current->id, current->name, current->prio);
|
"new prio: %d", current->id, current->name, current->prio, prio);
|
||||||
|
|
||||||
current->prio = prio;
|
current->prio = prio;
|
||||||
ddekit_thread_schedule();
|
ddekit_thread_schedule();
|
||||||
|
@ -466,22 +473,12 @@ void _ddekit_thread_wakeup_sleeping()
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
void _ddekit_print_backtrace(ddekit_thread_t *th)
|
void _ddekit_print_backtrace(ddekit_thread_t *th)
|
||||||
{
|
{
|
||||||
|
#if defined(__i386)
|
||||||
unsigned long bp, pc, hbp;
|
unsigned long bp, pc, hbp;
|
||||||
|
|
||||||
ddekit_printf("%s: ", th->name);
|
ddekit_printf("%s: ", th->name);
|
||||||
|
|
||||||
#ifdef __ACK__
|
bp = th->ctx.uc_mcontext.__gregs[_REG_EBP];
|
||||||
bp =th->jb[0].__bp;
|
|
||||||
#else /* !__ACK__ */
|
|
||||||
#include <sys/jmp_buf.h>
|
|
||||||
#if defined(JB_BP)
|
|
||||||
/* um, yikes. */
|
|
||||||
bp = (unsigned long) *((void **)(&((char *)th->jb)[JB_BP]));
|
|
||||||
#else
|
|
||||||
#error "Unsupported Minix architecture"
|
|
||||||
#endif
|
|
||||||
#endif /* !__ACK__ */
|
|
||||||
|
|
||||||
while (bp) {
|
while (bp) {
|
||||||
pc = ((unsigned long *)bp)[1];
|
pc = ((unsigned long *)bp)[1];
|
||||||
hbp = ((unsigned long *)bp)[0];
|
hbp = ((unsigned long *)bp)[0];
|
||||||
|
@ -494,6 +491,8 @@ void _ddekit_print_backtrace(ddekit_thread_t *th)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
bp= hbp;
|
bp= hbp;
|
||||||
}
|
}
|
||||||
|
|
||||||
ddekit_printf("\n");
|
ddekit_printf("\n");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define DDEKIT_SRC_THREAD_H 1
|
#define DDEKIT_SRC_THREAD_H 1
|
||||||
#include <ddekit/thread.h>
|
#include <ddekit/thread.h>
|
||||||
#include <ddekit/semaphore.h>
|
#include <ddekit/semaphore.h>
|
||||||
#include <setjmp.h>
|
#include <ucontext.h>
|
||||||
|
|
||||||
#define DDEKIT_THREAD_NAMELEN 32
|
#define DDEKIT_THREAD_NAMELEN 32
|
||||||
#define DDEKIT_THREAD_PRIOS 3
|
#define DDEKIT_THREAD_PRIOS 3
|
||||||
|
@ -26,7 +26,7 @@ struct ddekit_thread {
|
||||||
void *data;
|
void *data;
|
||||||
unsigned sleep_until;
|
unsigned sleep_until;
|
||||||
char name[DDEKIT_THREAD_NAMELEN];
|
char name[DDEKIT_THREAD_NAMELEN];
|
||||||
jmp_buf jb;
|
ucontext_t ctx;
|
||||||
ddekit_sem_t *sleep_sem;
|
ddekit_sem_t *sleep_sem;
|
||||||
struct ddekit_thread * next;
|
struct ddekit_thread * next;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue