1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

ST: Replace macros with explicit code for better understanding. v7.0.7 (#4149)

Improvements for ST(State Threads):

1. ST: Use g++ for CXX compiler.
2. ST: Remove macros for clist.
3. ST: Remove macros for global thread and vp.
4. ST: Remove macros for vp queue operations.
5. ST: Remove macros for context switch.
6. ST: Remove macros for setjmp/longjmp.
7. ST: Remove macro for stack pad.
8. ST: Refine macro for valgrind.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
This commit is contained in:
Winlin 2024-08-22 11:28:25 +08:00 committed by GitHub
parent 0d76081430
commit ff6a608099
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
15 changed files with 228 additions and 285 deletions

View file

@ -50,7 +50,7 @@
#include "common.h"
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
#ifndef NVALGRIND
#ifdef MD_VALGRIND
#include <valgrind/valgrind.h>
#endif
@ -89,7 +89,7 @@ int st_poll(struct pollfd *pds, int npds, st_utime_t timeout)
struct pollfd *pd;
struct pollfd *epd = pds + npds;
_st_pollq_t pq;
_st_thread_t *me = _ST_CURRENT_THREAD();
_st_thread_t *me = _st_this_thread;
int n;
if (me->flags & _ST_FL_INTERRUPT) {
@ -105,17 +105,17 @@ int st_poll(struct pollfd *pds, int npds, st_utime_t timeout)
pq.npds = npds;
pq.thread = me;
pq.on_ioq = 1;
_ST_ADD_IOQ(pq);
st_clist_insert_before(&pq.links, &_st_this_vp.io_q);
if (timeout != ST_UTIME_NO_TIMEOUT)
_ST_ADD_SLEEPQ(me, timeout);
_st_add_sleep_q(me, timeout);
me->state = _ST_ST_IO_WAIT;
_ST_SWITCH_CONTEXT(me);
_st_switch_context(me);
n = 0;
if (pq.on_ioq) {
/* If we timed out, the pollq might still be on the ioq. Remove it */
_ST_DEL_IOQ(pq);
st_clist_remove(&pq.links);
(*_st_eventsys->pollset_del)(pds, npds);
} else {
/* Count the number of ready descriptors */
@ -139,14 +139,14 @@ void _st_vp_schedule(void)
{
_st_thread_t *thread;
if (_ST_RUNQ.next != &_ST_RUNQ) {
if (_st_this_vp.run_q.next != &_st_this_vp.run_q) {
#if defined(DEBUG) && defined(DEBUG_STATS)
++_st_stat_thread_run;
#endif
/* Pull thread off of the run queue */
thread = _ST_THREAD_PTR(_ST_RUNQ.next);
_ST_DEL_RUNQ(thread);
thread = _ST_THREAD_PTR(_st_this_vp.run_q.next);
st_clist_remove(&thread->links);
} else {
#if defined(DEBUG) && defined(DEBUG_STATS)
++_st_stat_thread_idle;
@ -159,7 +159,7 @@ void _st_vp_schedule(void)
/* Resume the thread */
thread->state = _ST_ST_RUNNING;
_ST_RESTORE_CONTEXT(thread);
_st_restore_context(thread);
}
@ -182,16 +182,16 @@ int st_init(void)
return -1;
// Initialize the thread-local variables.
ST_INIT_CLIST(&_st_free_stacks);
st_clist_init(&_st_free_stacks);
// Initialize ST.
memset(&_st_this_vp, 0, sizeof(_st_vp_t));
ST_INIT_CLIST(&_ST_RUNQ);
ST_INIT_CLIST(&_ST_IOQ);
ST_INIT_CLIST(&_ST_ZOMBIEQ);
st_clist_init(&_st_this_vp.run_q);
st_clist_init(&_st_this_vp.io_q);
st_clist_init(&_st_this_vp.zombie_q);
#ifdef DEBUG
ST_INIT_CLIST(&_ST_THREADQ);
st_clist_init(&_st_this_vp.thread_q);
#endif
if ((*_st_eventsys->init)() < 0)
@ -208,7 +208,7 @@ int st_init(void)
return -1;
_st_this_vp.idle_thread->flags = _ST_FL_IDLE_THREAD;
_st_active_count--;
_ST_DEL_RUNQ(_st_this_vp.idle_thread);
st_clist_remove(&_st_this_vp.idle_thread->links);
/*
* Initialize primordial thread
@ -219,10 +219,10 @@ int st_init(void)
thread->private_data = (void **) (thread + 1);
thread->state = _ST_ST_RUNNING;
thread->flags = _ST_FL_PRIMORDIAL;
_ST_SET_CURRENT_THREAD(thread);
_st_this_thread = thread;
_st_active_count++;
#ifdef DEBUG
_ST_ADD_THREADQ(thread);
st_clist_insert_before(&thread->tlink, &_st_this_vp.thread_q);
#endif
return 0;
@ -261,17 +261,17 @@ st_switch_cb_t st_set_switch_out_cb(st_switch_cb_t cb)
/* ARGSUSED */
void *_st_idle_thread_start(void *arg)
{
_st_thread_t *me = _ST_CURRENT_THREAD();
_st_thread_t *me = _st_this_thread;
while (_st_active_count > 0) {
/* Idle vp till I/O is ready or the smallest timeout expired */
_ST_VP_IDLE();
(*_st_eventsys->dispatch)();
/* Check sleep queue for expired threads */
_st_vp_check_clock();
me->state = _ST_ST_RUNNABLE;
_ST_SWITCH_CONTEXT(me);
_st_switch_context(me);
}
/* No more threads */
@ -284,7 +284,7 @@ void *_st_idle_thread_start(void *arg)
void st_thread_exit(void *retval)
{
_st_thread_t *thread = _ST_CURRENT_THREAD();
_st_thread_t *thread = _st_this_thread;
thread->retval = retval;
_st_thread_cleanup(thread);
@ -292,13 +292,13 @@ void st_thread_exit(void *retval)
if (thread->term) {
/* Put thread on the zombie queue */
thread->state = _ST_ST_ZOMBIE;
_ST_ADD_ZOMBIEQ(thread);
st_clist_insert_before(&thread->links, &_st_this_vp.zombie_q);
/* Notify on our termination condition variable */
st_cond_signal(thread->term);
/* Switch context and come back later */
_ST_SWITCH_CONTEXT(thread);
_st_switch_context(thread);
/* Continue the cleanup */
st_cond_destroy(thread->term);
@ -306,11 +306,11 @@ void st_thread_exit(void *retval)
}
#ifdef DEBUG
_ST_DEL_THREADQ(thread);
st_clist_remove(&thread->tlink);
#endif
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
#ifndef NVALGRIND
#ifdef MD_VALGRIND
if (!(thread->flags & _ST_FL_PRIMORDIAL)) {
VALGRIND_STACK_DEREGISTER(thread->stack->valgrind_stack_id);
}
@ -320,7 +320,7 @@ void st_thread_exit(void *retval)
_st_stack_free(thread->stack);
/* Find another thread to run */
_ST_SWITCH_CONTEXT(thread);
_st_switch_context(thread);
/* Not going to land here */
}
@ -334,7 +334,7 @@ int st_thread_join(_st_thread_t *thread, void **retvalp)
errno = EINVAL;
return -1;
}
if (_ST_CURRENT_THREAD() == thread) {
if (_st_this_thread == thread) {
errno = EDEADLK;
return -1;
}
@ -358,8 +358,8 @@ int st_thread_join(_st_thread_t *thread, void **retvalp)
* When it gets scheduled later, it will do the clean up.
*/
thread->state = _ST_ST_RUNNABLE;
_ST_DEL_ZOMBIEQ(thread);
_ST_ADD_RUNQ(thread);
st_clist_remove(&thread->links);
st_clist_insert_before(&thread->links, &_st_this_vp.run_q);
return 0;
}
@ -367,7 +367,7 @@ int st_thread_join(_st_thread_t *thread, void **retvalp)
void _st_thread_main(void)
{
_st_thread_t *thread = _ST_CURRENT_THREAD();
_st_thread_t *thread = _st_this_thread;
/*
* Cap the stack by zeroing out the saved return address register
@ -392,7 +392,7 @@ void _st_thread_main(void)
static _st_thread_t **heap_insert(_st_thread_t *thread) {
int target = thread->heap_index;
int s = target;
_st_thread_t **p = &_ST_SLEEPQ;
_st_thread_t **p = &_st_this_vp.sleep_q;
int bits = 0;
int bit;
int index = 1;
@ -434,14 +434,14 @@ static void heap_delete(_st_thread_t *thread) {
int s, bit;
/* First find and unlink the last heap element */
p = &_ST_SLEEPQ;
s = _ST_SLEEPQ_SIZE;
p = &_st_this_vp.sleep_q;
s = _st_this_vp.sleepq_size;
while (s) {
s >>= 1;
bits++;
}
for (bit = bits - 2; bit >= 0; bit--) {
if (_ST_SLEEPQ_SIZE & (1 << bit)) {
if (_st_this_vp.sleepq_size & (1 << bit)) {
p = &((*p)->right);
} else {
p = &((*p)->left);
@ -449,7 +449,7 @@ static void heap_delete(_st_thread_t *thread) {
}
t = *p;
*p = NULL;
--_ST_SLEEPQ_SIZE;
--_st_this_vp.sleepq_size;
if (t != thread) {
/*
* Insert the unlinked last element in place of the element we are deleting
@ -503,9 +503,9 @@ static void heap_delete(_st_thread_t *thread) {
void _st_add_sleep_q(_st_thread_t *thread, st_utime_t timeout)
{
thread->due = _ST_LAST_CLOCK + timeout;
thread->due = _st_this_vp.last_clock + timeout;
thread->flags |= _ST_FL_ON_SLEEPQ;
thread->heap_index = ++_ST_SLEEPQ_SIZE;
thread->heap_index = ++_st_this_vp.sleepq_size;
heap_insert(thread);
}
@ -527,9 +527,9 @@ void _st_vp_check_clock(void)
now = st_utime();
#if defined(DEBUG) && defined(DEBUG_STATS)
elapsed = now < _ST_LAST_CLOCK? 0 : now - _ST_LAST_CLOCK; // Might step back.
elapsed = now < _st_this_vp.last_clock? 0 : now - _st_this_vp.last_clock; // Might step back.
#endif
_ST_LAST_CLOCK = now;
_st_this_vp.last_clock = now;
#if defined(DEBUG) && defined(DEBUG_STATS)
if (elapsed <= 10000) {
@ -558,12 +558,12 @@ void _st_vp_check_clock(void)
_st_last_tset = now;
}
while (_ST_SLEEPQ != NULL) {
thread = _ST_SLEEPQ;
while (_st_this_vp.sleep_q != NULL) {
thread = _st_this_vp.sleep_q;
ST_ASSERT(thread->flags & _ST_FL_ON_SLEEPQ);
if (thread->due > now)
break;
_ST_DEL_SLEEPQ(thread);
_st_del_sleep_q(thread);
/* If thread is waiting on condition variable, set the time out flag */
if (thread->state == _ST_ST_COND_WAIT)
@ -573,14 +573,14 @@ void _st_vp_check_clock(void)
ST_ASSERT(!(thread->flags & _ST_FL_IDLE_THREAD));
thread->state = _ST_ST_RUNNABLE;
// Insert at the head of RunQ, to execute timer first.
_ST_INSERT_RUNQ(thread);
st_clist_insert_after(&thread->links, &_st_this_vp.run_q);
}
}
void st_thread_yield()
{
_st_thread_t *me = _ST_CURRENT_THREAD();
_st_thread_t *me = _st_this_thread;
#if defined(DEBUG) && defined(DEBUG_STATS)
++_st_stat_thread_yield;
@ -590,7 +590,7 @@ void st_thread_yield()
_st_vp_check_clock();
// If not thread in RunQ to yield to, ignore and continue to run.
if (_ST_RUNQ.next == &_ST_RUNQ) {
if (_st_this_vp.run_q.next == &_st_this_vp.run_q) {
return;
}
@ -600,10 +600,10 @@ void st_thread_yield()
// Append thread to the tail of RunQ, we will back after all threads executed.
me->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(me);
st_clist_insert_before(&me->links, &_st_this_vp.run_q);
// Yield to other threads in the RunQ.
_ST_SWITCH_CONTEXT(me);
_st_switch_context(me);
}
@ -619,11 +619,11 @@ void st_thread_interrupt(_st_thread_t *thread)
return;
if (thread->flags & _ST_FL_ON_SLEEPQ)
_ST_DEL_SLEEPQ(thread);
_st_del_sleep_q(thread);
/* Make thread runnable */
thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(thread);
st_clist_insert_before(&thread->links, &_st_this_vp.run_q);
}
@ -637,7 +637,7 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
/* 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;
stk_size = ((stk_size + _st_this_vp.pagesize - 1) / _st_this_vp.pagesize) * _st_this_vp.pagesize;
stack = _st_stack_new(stk_size);
if (!stack)
return NULL;
@ -663,7 +663,10 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
thread->start = start;
thread->arg = arg;
_ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main);
/* Note that we must directly call rather than call any functions. */
if (_st_md_cxt_save(thread->context))
_st_thread_main();
MD_GET_SP(thread) = (long)(stack->sp);
/* If thread is joinable, allocate a termination condition variable */
if (joinable) {
@ -677,13 +680,13 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
/* Make thread runnable */
thread->state = _ST_ST_RUNNABLE;
_st_active_count++;
_ST_ADD_RUNQ(thread);
st_clist_insert_before(&thread->links, &_st_this_vp.run_q);
#ifdef DEBUG
_ST_ADD_THREADQ(thread);
st_clist_insert_before(&thread->tlink, &_st_this_vp.thread_q);
#endif
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
#ifndef NVALGRIND
#ifdef MD_VALGRIND
if (!(thread->flags & _ST_FL_PRIMORDIAL)) {
thread->stack->valgrind_stack_id = VALGRIND_STACK_REGISTER(thread->stack->stk_top, thread->stack->stk_bottom);
}
@ -695,7 +698,7 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
_st_thread_t *st_thread_self(void)
{
return _ST_CURRENT_THREAD();
return _st_this_thread;
}
#ifdef DEBUG
@ -717,7 +720,7 @@ void _st_iterate_threads(void)
if (!_st_iterate_threads_flag) {
if (thread) {
memcpy(thread->context, save_jb, sizeof(_st_jmp_buf_t));
MD_LONGJMP(orig_jb, 1);
_st_md_cxt_restore(orig_jb, 1);
}
return;
}
@ -726,25 +729,25 @@ void _st_iterate_threads(void)
memcpy(thread->context, save_jb, sizeof(_st_jmp_buf_t));
_st_show_thread_stack(thread, NULL);
} else {
if (MD_SETJMP(orig_jb)) {
if (_st_md_cxt_save(orig_jb)) {
_st_iterate_threads_flag = 0;
thread = NULL;
_st_show_thread_stack(thread, "Iteration completed");
return;
}
thread = _ST_CURRENT_THREAD();
thread = _st_this_thread;
_st_show_thread_stack(thread, "Iteration started");
}
q = thread->tlink.next;
if (q == &_ST_THREADQ)
if (q == &_st_this_vp.thread_q)
q = q->next;
ST_ASSERT(q != &_ST_THREADQ);
ST_ASSERT(q != &_st_this_vp.thread_q);
thread = _ST_THREAD_THREADQ_PTR(q);
if (thread == _ST_CURRENT_THREAD())
MD_LONGJMP(orig_jb, 1);
if (thread == _st_this_thread)
_st_md_cxt_restore(orig_jb, 1);
memcpy(save_jb, thread->context, sizeof(_st_jmp_buf_t));
MD_LONGJMP(thread->context, 1);
_st_md_cxt_restore(thread->context, 1);
}
#endif /* DEBUG */