📄 sched.c
字号:
*/static _st_thread_t **heap_insert(_st_thread_t *thread) { int target = thread->heap_index; int s = target; _st_thread_t **p = &_ST_SLEEPQ; int bits = 0; int bit; int index = 1; while (s) { s >>= 1; bits++; } for (bit = bits - 2; bit >= 0; bit--) { if (thread->due < (*p)->due) { _st_thread_t *t = *p; thread->left = t->left; thread->right = t->right; *p = thread; thread->heap_index = index; thread = t; } index <<= 1; if (target & (1 << bit)) { p = &((*p)->right); index |= 1; } else { p = &((*p)->left); } } thread->heap_index = index; *p = thread; thread->left = thread->right = NULL; return p;}/* * Delete "thread" from the timeout heap. */static void heap_delete(_st_thread_t *thread) { _st_thread_t *t, **p; int bits = 0; int s, bit; /* First find and unlink the last heap element */ p = &_ST_SLEEPQ; s = _ST_SLEEPQ_SIZE; while (s) { s >>= 1; bits++; } for (bit = bits - 2; bit >= 0; bit--) { if (_ST_SLEEPQ_SIZE & (1 << bit)) { p = &((*p)->right); } else { p = &((*p)->left); } } t = *p; *p = NULL; --_ST_SLEEPQ_SIZE; if (t != thread) { /* * Insert the unlinked last element in place of the element we are deleting */ t->heap_index = thread->heap_index; p = heap_insert(t); t = *p; t->left = thread->left; t->right = thread->right; /* * Reestablish the heap invariant. */ for (;;) { _st_thread_t *y; /* The younger child */ int index_tmp; if (t->left == NULL) break; else if (t->right == NULL) y = t->left; else if (t->left->due < t->right->due) y = t->left; else y = t->right; if (t->due > y->due) { _st_thread_t *tl = y->left; _st_thread_t *tr = y->right; *p = y; if (y == t->left) { y->left = t; y->right = t->right; p = &y->left; } else { y->left = t->left; y->right = t; p = &y->right; } t->left = tl; t->right = tr; index_tmp = t->heap_index; t->heap_index = y->heap_index; y->heap_index = index_tmp; } else { break; } } } thread->left = thread->right = NULL;}void _st_add_sleep_q(_st_thread_t *thread, st_utime_t timeout){ thread->due = _ST_LAST_CLOCK + timeout; thread->flags |= _ST_FL_ON_SLEEPQ; thread->heap_index = ++_ST_SLEEPQ_SIZE; heap_insert(thread);}void _st_del_sleep_q(_st_thread_t *thread){ heap_delete(thread); thread->flags &= ~_ST_FL_ON_SLEEPQ;}void _st_vp_check_clock(void){ _st_thread_t *thread; st_utime_t elapsed, now; now = st_utime(); elapsed = now - _ST_LAST_CLOCK; _ST_LAST_CLOCK = now; if (_st_curr_time && now - _st_last_tset > 999000) { _st_curr_time = time(NULL); _st_last_tset = now; } while (_ST_SLEEPQ != NULL) { thread = _ST_SLEEPQ; ST_ASSERT(thread->flags & _ST_FL_ON_SLEEPQ); if (thread->due > now) break; _ST_DEL_SLEEPQ(thread); /* If thread is waiting on condition variable, set the time out flag */ if (thread->state == _ST_ST_COND_WAIT) thread->flags |= _ST_FL_TIMEDOUT; /* Make thread runnable */ ST_ASSERT(!(thread->flags & _ST_FL_IDLE_THREAD)); thread->state = _ST_ST_RUNNABLE; _ST_ADD_RUNQ(thread); }}void st_thread_interrupt(_st_thread_t *thread){ /* If thread is already dead */ if (thread->state == _ST_ST_ZOMBIE) return; thread->flags |= _ST_FL_INTERRUPT; if (thread->state == _ST_ST_RUNNING || thread->state == _ST_ST_RUNNABLE) return; if (thread->flags & _ST_FL_ON_SLEEPQ) _ST_DEL_SLEEPQ(thread); /* Make thread runnable */ thread->state = _ST_ST_RUNNABLE; _ST_ADD_RUNQ(thread);}_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;#ifdef __ia64__ char *bsp;#endif /* 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 */#if defined (MD_STACK_GROWS_DOWN) sp = stack->stk_top;#ifdef __ia64__ /* * The stack segment is split in the middle. The upper half is used * as backing store for the register stack which grows upward. * The lower half is used for the traditional memory stack which * grows downward. Both stacks start in the middle and grow outward * from each other. */ sp -= (stk_size >> 1); bsp = sp; /* Make register stack 64-byte aligned */ if ((unsigned long)bsp & 0x3f) bsp = bsp + (0x40 - ((unsigned long)bsp & 0x3f)); stack->bsp = bsp + _ST_STACK_PAD_SIZE;#endif 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;#elif defined (MD_STACK_GROWS_UP) sp = stack->stk_bottom; thread = (_st_thread_t *) sp; sp = sp + sizeof(_st_thread_t); ptds = (void **) sp; sp = sp + (ST_KEYS_MAX * sizeof(void *)); /* Make stack 64-byte aligned */ if ((unsigned long)sp & 0x3f) sp = sp + (0x40 - ((unsigned long)sp & 0x3f)); stack->sp = sp + _ST_STACK_PAD_SIZE;#else#error Unknown OS#endif 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;#ifndef __ia64__ _ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main);#else _ST_INIT_CONTEXT(thread, stack->sp, stack->bsp, _st_thread_main);#endif /* 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);#ifdef DEBUG _ST_ADD_THREADQ(thread);#endif return thread;}_st_thread_t *st_thread_self(void){ return _ST_CURRENT_THREAD();}#ifdef DEBUG/* ARGSUSED */void _st_show_thread_stack(_st_thread_t *thread, const char *messg){}/* To be set from debugger */int _st_iterate_threads_flag = 0;void _st_iterate_threads(void){ static _st_thread_t *thread = NULL; static jmp_buf orig_jb, save_jb; _st_clist_t *q; if (!_st_iterate_threads_flag) { if (thread) { memcpy(thread->context, save_jb, sizeof(jmp_buf)); MD_LONGJMP(orig_jb, 1); } return; } if (thread) { memcpy(thread->context, save_jb, sizeof(jmp_buf)); _st_show_thread_stack(thread, NULL); } else { if (MD_SETJMP(orig_jb)) { _st_iterate_threads_flag = 0; thread = NULL; _st_show_thread_stack(thread, "Iteration completed"); return; } thread = _ST_CURRENT_THREAD(); _st_show_thread_stack(thread, "Iteration started"); } q = thread->tlink.next; if (q == &_ST_THREADQ) q = q->next; ST_ASSERT(q != &_ST_THREADQ); thread = _ST_THREAD_THREADQ_PTR(q); if (thread == _ST_CURRENT_THREAD()) MD_LONGJMP(orig_jb, 1); memcpy(save_jb, thread->context, sizeof(jmp_buf)); MD_LONGJMP(thread->context, 1);}#endif /* DEBUG */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -