怎么理解state thread库?

主要一下几个问题

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队列。


那么这个队列怎么怎么执行的?在哪个线程空间里执行呢?






  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值