主要一下几个问题
1)到底st_thread库运行的线程是谁创建的?
2)st_create_thread,创建的线程是个什么东西?
3)线程怎么切换?
4)和reactor是个什么关系?
首先还原一些关键的代码。
#define _ST_SWITCH_CONTEXT(_thread) \
ST_BEGIN_MACRO \
ST_SWITCH_OUT_CB(_thread); \
if (!MD_SETJMP((_thread)->context)) { \
_st_vp_schedule(); \
} \
ST_DEBUG_ITERATE_THREADS(); \
ST_SWITCH_IN_CB(_thread); \
ST_END_MACRO
这一堆宏,基本相当于下面的代码
int md_setjmp(jmp_buf buf)
{
return _setjmp(env);
}
void _st_switch_context(_st_thread_t *_thread)
{
if (0 == md_setjmp((_thread)->context)))
{
_st_vp_schedule();
}
}
_st_vp_schedule()的实现为:
void _st_vp_schedule(void)
{
_st_thread_t *thread;
if (_ST_RUNQ.next != &_ST_RUNQ) {
/* Pull thread off of the run queue */
thread = _ST_THREAD_PTR(_ST_RUNQ.next);
_ST_DEL_RUNQ(thread);
} else {
/* If there are no threads to run, switch to the idle thread */
thread = _st_this_vp.idle_thread;
}
ST_ASSERT(thread->state == _ST_ST_RUNNABLE);
/* Resume the thread */
thread->state = _ST_ST_RUNNING;
_ST_RESTORE_CONTEXT(thread);
}
#define _ST_RESTORE_CONTEXT(_thread) \
ST_BEGIN_MACRO \
_ST_SET_CURRENT_THREAD(_thread); \
MD_LONGJMP((_thread)->context, 1); \
ST_END_MACRO
这个宏比较简单,就是调用longjump函数。
可以看出,跳转的关键是context变量。在我们创建线程的时候
_st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg,
int joinable, int stk_size)
{
_st_thread_t *thread;
_st_stack_t *stack;
void **ptds;
char *sp;
/* Adjust stack size */
if (stk_size == 0)
stk_size = ST_DEFAULT_STACK_SIZE;
stk_size = ((stk_size + _ST_PAGE_SIZE - 1) / _ST_PAGE_SIZE) * _ST_PAGE_SIZE;
stack = _st_stack_new(stk_size);
if (!stack)
return NULL;
/* Allocate thread object and per-thread data off the stack */
sp = stack->stk_top;
sp = sp - (ST_KEYS_MAX * sizeof(void *));
ptds = (void **)sp;
sp = sp - sizeof(_st_thread_t);
thread = (_st_thread_t *)sp;
/* Make stack 64-byte aligned */
if ((unsigned long)sp & 0x3f)
sp = sp - ((unsigned long)sp & 0x3f);
stack->sp = sp - _ST_STACK_PAD_SIZE;
memset(thread, 0, sizeof(_st_thread_t));
memset(ptds, 0, ST_KEYS_MAX * sizeof(void *));
/* Initialize thread */
thread->private_data = ptds;
thread->stack = stack;
thread->start = start;
thread->arg = arg;
_ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main);
/* If thread is joinable, allocate a termination condition variable */
if (joinable) {
thread->term = st_cond_new();
if (thread->term == NULL) {
_st_stack_free(thread->stack);
return NULL;
}
}
/* Make thread runnable */
thread->state = _ST_ST_RUNNABLE;
_st_active_count++;
_ST_ADD_RUNQ(thread);
return thread;
}
上面是初始化的函数,我去掉了一些无用的红比如ia64位的,和堆栈向上增长的情况。一般情况下,堆栈应该是向上增长的。让我们仔细分析这段代码
经过仔细的阅读,基本读不懂这段代码。基本确定的流程就是,这个thread,在创建成功后,进入到了RUNQ队列。
那么这个队列怎么怎么执行的?在哪个线程空间里执行呢?