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>
pull/4152/head
Winlin 5 months ago committed by GitHub
parent 0d76081430
commit ff6a608099
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -46,6 +46,7 @@ VERSION = 1.9
########################## ##########################
CC = cc CC = cc
CXX = g++
AR = ar AR = ar
LD = ld LD = ld
RANLIB = ranlib RANLIB = ranlib
@ -207,7 +208,8 @@ OBJS = $(TARGETDIR)/sched.o \
$(TARGETDIR)/sync.o \ $(TARGETDIR)/sync.o \
$(TARGETDIR)/key.o \ $(TARGETDIR)/key.o \
$(TARGETDIR)/io.o \ $(TARGETDIR)/io.o \
$(TARGETDIR)/event.o $(TARGETDIR)/event.o \
$(TARGETDIR)/common.o
OBJS += $(EXTRA_OBJS) OBJS += $(EXTRA_OBJS)
HEADER = $(TARGETDIR)/st.h HEADER = $(TARGETDIR)/st.h
SLIBRARY = $(TARGETDIR)/libst.a SLIBRARY = $(TARGETDIR)/libst.a
@ -270,21 +272,16 @@ $(HEADER): public.h
rm -f $@ rm -f $@
cp public.h $@ cp public.h $@
$(TARGETDIR)/md_linux.o: md_linux.S $(TARGETDIR)/%.o: %.S
$(CC) $(CFLAGS) -c $< -o $@
$(TARGETDIR)/md_linux2.o: md_linux2.S
$(CC) $(CFLAGS) -c $< -o $@
$(TARGETDIR)/md_darwin.o: md_darwin.S
$(CC) $(CFLAGS) -c $< -o $@
$(TARGETDIR)/md_cygwin64.o: md_cygwin64.S
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
$(TARGETDIR)/%.o: %.c common.h md.h $(TARGETDIR)/%.o: %.c common.h md.h
$(CC) $(CFLAGS) -c $< -o $@ $(CC) $(CFLAGS) -c $< -o $@
# Note that we use C++98 standard for the C++ files.
$(TARGETDIR)/%.o: %.cc common.h md.h
$(CXX) $(CFLAGS) -c $< -o $@ -std=c++98
clean: clean:
rm -rf *_OPT *_DBG obj st.pc rm -rf *_OPT *_DBG obj st.pc

@ -0,0 +1,23 @@
/* SPDX-License-Identifier: MIT */
/* Copyright (c) 2021-2022 The SRS Authors */
#include "common.h"
void _st_switch_context(_st_thread_t *thread)
{
ST_SWITCH_OUT_CB(thread);
if (!_st_md_cxt_save(thread->context)) {
_st_vp_schedule();
}
ST_DEBUG_ITERATE_THREADS();
ST_SWITCH_IN_CB(thread);
}
void _st_restore_context(_st_thread_t *thread)
{
_st_this_thread = thread;
_st_md_cxt_restore(thread->context, 1);
}

@ -69,13 +69,8 @@
#include "public.h" #include "public.h"
#include "md.h" #include "md.h"
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */ #ifdef __cplusplus
#ifndef MD_VALGRIND extern "C" {
#ifndef NVALGRIND
#define NVALGRIND
#endif
#else
#undef NVALGRIND
#endif #endif
@ -88,58 +83,37 @@ typedef struct _st_clist {
struct _st_clist *prev; struct _st_clist *prev;
} _st_clist_t; } _st_clist_t;
/* Insert element "_e" into the list, before "_l" */ /* Initialize a circular list */
#define ST_INSERT_BEFORE(_e,_l) \ static inline void st_clist_init(_st_clist_t *l)
ST_BEGIN_MACRO \ {
(_e)->next = (_l); \ l->next = l;
(_e)->prev = (_l)->prev; \ l->prev = l;
(_l)->prev->next = (_e); \ }
(_l)->prev = (_e); \
ST_END_MACRO
/* Insert element "_e" into the list, after "_l" */
#define ST_INSERT_AFTER(_e,_l) \
ST_BEGIN_MACRO \
(_e)->next = (_l)->next; \
(_e)->prev = (_l); \
(_l)->next->prev = (_e); \
(_l)->next = (_e); \
ST_END_MACRO
/* Return the element following element "_e" */
#define ST_NEXT_LINK(_e) ((_e)->next)
/* Append an element "_e" to the end of the list "_l" */
#define ST_APPEND_LINK(_e,_l) ST_INSERT_BEFORE(_e,_l)
/* Insert an element "_e" at the head of the list "_l" */
#define ST_INSERT_LINK(_e,_l) ST_INSERT_AFTER(_e,_l)
/* Return the head/tail of the list */
#define ST_LIST_HEAD(_l) (_l)->next
#define ST_LIST_TAIL(_l) (_l)->prev
/* Remove the element "_e" from it's circular list */ /* Remove the element "_e" from it's circular list */
#define ST_REMOVE_LINK(_e) \ static inline void st_clist_remove(_st_clist_t *e)
ST_BEGIN_MACRO \ {
(_e)->prev->next = (_e)->next; \ e->prev->next = e->next;
(_e)->next->prev = (_e)->prev; \ e->next->prev = e->prev;
ST_END_MACRO }
/* Return non-zero if the given circular list "_l" is empty, */
/* zero if the circular list is not empty */
#define ST_CLIST_IS_EMPTY(_l) \
((_l)->next == (_l))
/* Initialize a circular list */ /* Insert element "_e" into the list, before "_l" */
#define ST_INIT_CLIST(_l) \ static inline void st_clist_insert_before(_st_clist_t *e, _st_clist_t *l)
ST_BEGIN_MACRO \ {
(_l)->next = (_l); \ e->next = l;
(_l)->prev = (_l); \ e->prev = l->prev;
ST_END_MACRO l->prev->next = e;
l->prev = e;
}
#define ST_INIT_STATIC_CLIST(_l) \ /* Insert element "_e" into the list, after "_l" */
{(_l), (_l)} static inline void st_clist_insert_after(_st_clist_t *e, _st_clist_t *l)
{
e->next = l->next;
e->prev = l;
l->next->prev = e;
l->next = e;
}
/***************************************** /*****************************************
@ -158,7 +132,7 @@ typedef struct _st_stack {
char *stk_top; /* Highest address of stack's usable portion */ char *stk_top; /* Highest address of stack's usable portion */
void *sp; /* Stack pointer from C's point of view */ void *sp; /* Stack pointer from C's point of view */
/* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */ /* merge from https://github.com/toffaletti/state-threads/commit/7f57fc9acc05e657bca1223f1e5b9b1a45ed929b */
#ifndef NVALGRIND #ifdef MD_VALGRIND
/* id returned by VALGRIND_STACK_REGISTER */ /* id returned by VALGRIND_STACK_REGISTER */
/* http://valgrind.org/docs/manual/manual-core-adv.html */ /* http://valgrind.org/docs/manual/manual-core-adv.html */
unsigned long valgrind_stack_id; unsigned long valgrind_stack_id;
@ -270,48 +244,6 @@ extern __thread _st_vp_t _st_this_vp;
extern __thread _st_thread_t *_st_this_thread; extern __thread _st_thread_t *_st_this_thread;
extern __thread _st_eventsys_t *_st_eventsys; extern __thread _st_eventsys_t *_st_eventsys;
#define _ST_CURRENT_THREAD() (_st_this_thread)
#define _ST_SET_CURRENT_THREAD(_thread) (_st_this_thread = (_thread))
#define _ST_LAST_CLOCK (_st_this_vp.last_clock)
#define _ST_RUNQ (_st_this_vp.run_q)
#define _ST_IOQ (_st_this_vp.io_q)
#define _ST_ZOMBIEQ (_st_this_vp.zombie_q)
#ifdef DEBUG
#define _ST_THREADQ (_st_this_vp.thread_q)
#endif
#define _ST_PAGE_SIZE (_st_this_vp.pagesize)
#define _ST_SLEEPQ (_st_this_vp.sleep_q)
#define _ST_SLEEPQ_SIZE (_st_this_vp.sleepq_size)
#define _ST_VP_IDLE() (*_st_eventsys->dispatch)()
/*****************************************
* vp queues operations
*/
#define _ST_ADD_IOQ(_pq) ST_APPEND_LINK(&_pq.links, &_ST_IOQ)
#define _ST_DEL_IOQ(_pq) ST_REMOVE_LINK(&_pq.links)
#define _ST_ADD_RUNQ(_thr) ST_APPEND_LINK(&(_thr)->links, &_ST_RUNQ)
#define _ST_INSERT_RUNQ(_thr) ST_INSERT_LINK(&(_thr)->links, &_ST_RUNQ)
#define _ST_DEL_RUNQ(_thr) ST_REMOVE_LINK(&(_thr)->links)
#define _ST_ADD_SLEEPQ(_thr, _timeout) _st_add_sleep_q(_thr, _timeout)
#define _ST_DEL_SLEEPQ(_thr) _st_del_sleep_q(_thr)
#define _ST_ADD_ZOMBIEQ(_thr) ST_APPEND_LINK(&(_thr)->links, &_ST_ZOMBIEQ)
#define _ST_DEL_ZOMBIEQ(_thr) ST_REMOVE_LINK(&(_thr)->links)
#ifdef DEBUG
#define _ST_ADD_THREADQ(_thr) ST_APPEND_LINK(&(_thr)->tlink, &_ST_THREADQ)
#define _ST_DEL_THREADQ(_thr) ST_REMOVE_LINK(&(_thr)->tlink)
#endif
/***************************************** /*****************************************
* Thread states and flags * Thread states and flags
@ -411,39 +343,18 @@ extern __thread _st_eventsys_t *_st_eventsys;
* Switch away from the current thread context by saving its state and * Switch away from the current thread context by saving its state and
* calling the thread scheduler * calling the thread scheduler
*/ */
#define _ST_SWITCH_CONTEXT(_thread) \ void _st_switch_context(_st_thread_t *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
/* /*
* Restore a thread context that was saved by _ST_SWITCH_CONTEXT or * Restore a thread context that was saved by _st_switch_context or
* initialized by _ST_INIT_CONTEXT * initialized by _ST_INIT_CONTEXT
*/ */
#define _ST_RESTORE_CONTEXT(_thread) \ void _st_restore_context(_st_thread_t *thread);
ST_BEGIN_MACRO \
_ST_SET_CURRENT_THREAD(_thread); \
MD_LONGJMP((_thread)->context, 1); \
ST_END_MACRO
/*
* Initialize the thread context preparing it to execute _main
*/
#ifdef MD_INIT_CONTEXT
#define _ST_INIT_CONTEXT MD_INIT_CONTEXT
#else
#error Unknown OS
#endif
/* /*
* Number of bytes reserved under the stack "bottom" * Number of bytes reserved under the stack "bottom"
*/ */
#define _ST_STACK_PAD_SIZE MD_STACK_PAD_SIZE #define _ST_STACK_PAD_SIZE 128
/***************************************** /*****************************************
@ -471,5 +382,9 @@ ssize_t st_write(_st_netfd_t *fd, const void *buf, size_t nbyte, st_utime_t time
int st_poll(struct pollfd *pds, int npds, st_utime_t timeout); int st_poll(struct pollfd *pds, int npds, st_utime_t timeout);
_st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size); _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size);
#ifdef __cplusplus
} /* extern "C" */
#endif
#endif /* !__ST_COMMON_H__ */ #endif /* !__ST_COMMON_H__ */

@ -22,7 +22,7 @@ appropriate for ST than introducing a separate array.
Thus, the new ST timeout heap works by organizing the existing Thus, the new ST timeout heap works by organizing the existing
_st_thread_t objects in a balanced binary tree, just as they were _st_thread_t objects in a balanced binary tree, just as they were
previously organized into a doubly-linked, sorted list. The global previously organized into a doubly-linked, sorted list. The global
_ST_SLEEPQ variable, formerly a linked list head, is now simply a _st_this_vp.sleep_q variable, formerly a linked list head, is now simply a
pointer to the root of this tree, and the root node of the tree is the pointer to the root of this tree, and the root node of the tree is the
thread with the earliest timeout. Each thread object has two child thread with the earliest timeout. Each thread object has two child
pointers, "left" and "right", pointing to threads with later timeouts. pointers, "left" and "right", pointing to threads with later timeouts.

@ -233,7 +233,7 @@ ST_HIDDEN void _st_select_find_bad_fd(void)
_ST_SELECT_MAX_OSFD = -1; _ST_SELECT_MAX_OSFD = -1;
for (q = _ST_IOQ.next; q != &_ST_IOQ; q = q->next) { for (q = _st_this_vp.io_q.next; q != &_st_this_vp.io_q; q = q->next) {
pq = _ST_POLLQUEUE_PTR(q); pq = _ST_POLLQUEUE_PTR(q);
notify = 0; notify = 0;
epds = pq->pds + pq->npds; epds = pq->pds + pq->npds;
@ -254,7 +254,7 @@ ST_HIDDEN void _st_select_find_bad_fd(void)
} }
if (notify) { if (notify) {
ST_REMOVE_LINK(&pq->links); st_clist_remove(&pq->links);
pq->on_ioq = 0; pq->on_ioq = 0;
/* /*
* Decrement the count of descriptors for each descriptor/event * Decrement the count of descriptors for each descriptor/event
@ -281,9 +281,9 @@ ST_HIDDEN void _st_select_find_bad_fd(void)
} }
if (pq->thread->flags & _ST_FL_ON_SLEEPQ) if (pq->thread->flags & _ST_FL_ON_SLEEPQ)
_ST_DEL_SLEEPQ(pq->thread); _st_del_sleep_q(pq->thread);
pq->thread->state = _ST_ST_RUNNABLE; pq->thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(pq->thread); st_clist_insert_before(&pq->thread->links, &_st_this_vp.run_q);
} else { } else {
if (_ST_SELECT_MAX_OSFD < pq_max_osfd) if (_ST_SELECT_MAX_OSFD < pq_max_osfd)
_ST_SELECT_MAX_OSFD = pq_max_osfd; _ST_SELECT_MAX_OSFD = pq_max_osfd;
@ -315,11 +315,11 @@ ST_HIDDEN void _st_select_dispatch(void)
wp = &w; wp = &w;
ep = &e; ep = &e;
if (_ST_SLEEPQ == NULL) { if (_st_this_vp.sleep_q == NULL) {
tvp = NULL; tvp = NULL;
} else { } else {
min_timeout = (_ST_SLEEPQ->due <= _ST_LAST_CLOCK) ? 0 : min_timeout = (_st_this_vp.sleep_q->due <= _st_this_vp.last_clock) ? 0 :
(_ST_SLEEPQ->due - _ST_LAST_CLOCK); (_st_this_vp.sleep_q->due - _st_this_vp.last_clock);
timeout.tv_sec = (int) (min_timeout / 1000000); timeout.tv_sec = (int) (min_timeout / 1000000);
timeout.tv_usec = (int) (min_timeout % 1000000); timeout.tv_usec = (int) (min_timeout % 1000000);
tvp = &timeout; tvp = &timeout;
@ -331,7 +331,7 @@ ST_HIDDEN void _st_select_dispatch(void)
/* Notify threads that are associated with the selected descriptors */ /* Notify threads that are associated with the selected descriptors */
if (nfd > 0) { if (nfd > 0) {
_ST_SELECT_MAX_OSFD = -1; _ST_SELECT_MAX_OSFD = -1;
for (q = _ST_IOQ.next; q != &_ST_IOQ; q = q->next) { for (q = _st_this_vp.io_q.next; q != &_st_this_vp.io_q; q = q->next) {
pq = _ST_POLLQUEUE_PTR(q); pq = _ST_POLLQUEUE_PTR(q);
notify = 0; notify = 0;
epds = pq->pds + pq->npds; epds = pq->pds + pq->npds;
@ -359,7 +359,7 @@ ST_HIDDEN void _st_select_dispatch(void)
} }
} }
if (notify) { if (notify) {
ST_REMOVE_LINK(&pq->links); st_clist_remove(&pq->links);
pq->on_ioq = 0; pq->on_ioq = 0;
/* /*
* Decrement the count of descriptors for each descriptor/event * Decrement the count of descriptors for each descriptor/event
@ -386,9 +386,9 @@ ST_HIDDEN void _st_select_dispatch(void)
} }
if (pq->thread->flags & _ST_FL_ON_SLEEPQ) if (pq->thread->flags & _ST_FL_ON_SLEEPQ)
_ST_DEL_SLEEPQ(pq->thread); _st_del_sleep_q(pq->thread);
pq->thread->state = _ST_ST_RUNNABLE; pq->thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(pq->thread); st_clist_insert_before(&pq->thread->links, &_st_this_vp.run_q);
} else { } else {
if (_ST_SELECT_MAX_OSFD < pq_max_osfd) if (_ST_SELECT_MAX_OSFD < pq_max_osfd)
_ST_SELECT_MAX_OSFD = pq_max_osfd; _ST_SELECT_MAX_OSFD = pq_max_osfd;
@ -697,10 +697,10 @@ ST_HIDDEN void _st_kq_dispatch(void)
int nfd, i, osfd, notify, filter; int nfd, i, osfd, notify, filter;
short events, revents; short events, revents;
if (_ST_SLEEPQ == NULL) { if (_st_this_vp.sleep_q == NULL) {
tsp = NULL; tsp = NULL;
} else { } else {
min_timeout = (_ST_SLEEPQ->due <= _ST_LAST_CLOCK) ? 0 : (_ST_SLEEPQ->due - _ST_LAST_CLOCK); min_timeout = (_st_this_vp.sleep_q->due <= _st_this_vp.last_clock) ? 0 : (_st_this_vp.sleep_q->due - _st_this_vp.last_clock);
timeout.tv_sec = (time_t) (min_timeout / 1000000); timeout.tv_sec = (time_t) (min_timeout / 1000000);
timeout.tv_nsec = (long) ((min_timeout % 1000000) * 1000); timeout.tv_nsec = (long) ((min_timeout % 1000000) * 1000);
tsp = &timeout; tsp = &timeout;
@ -735,7 +735,7 @@ ST_HIDDEN void _st_kq_dispatch(void)
_st_kq_data->dellist_cnt = 0; _st_kq_data->dellist_cnt = 0;
for (q = _ST_IOQ.next; q != &_ST_IOQ; q = q->next) { for (q = _st_this_vp.io_q.next; q != &_st_this_vp.io_q; q = q->next) {
pq = _ST_POLLQUEUE_PTR(q); pq = _ST_POLLQUEUE_PTR(q);
notify = 0; notify = 0;
epds = pq->pds + pq->npds; epds = pq->pds + pq->npds;
@ -756,7 +756,7 @@ ST_HIDDEN void _st_kq_dispatch(void)
} }
} }
if (notify) { if (notify) {
ST_REMOVE_LINK(&pq->links); st_clist_remove(&pq->links);
pq->on_ioq = 0; pq->on_ioq = 0;
for (pds = pq->pds; pds < epds; pds++) { for (pds = pq->pds; pds < epds; pds++) {
osfd = pds->fd; osfd = pds->fd;
@ -782,9 +782,9 @@ ST_HIDDEN void _st_kq_dispatch(void)
} }
if (pq->thread->flags & _ST_FL_ON_SLEEPQ) if (pq->thread->flags & _ST_FL_ON_SLEEPQ)
_ST_DEL_SLEEPQ(pq->thread); _st_del_sleep_q(pq->thread);
pq->thread->state = _ST_ST_RUNNABLE; pq->thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(pq->thread); st_clist_insert_before(&pq->thread->links, &_st_this_vp.run_q);
} }
} }
@ -811,7 +811,7 @@ ST_HIDDEN void _st_kq_dispatch(void)
_st_kq_data->pid = getpid(); _st_kq_data->pid = getpid();
/* Re-register all descriptors on ioq with new kqueue */ /* Re-register all descriptors on ioq with new kqueue */
memset(_st_kq_data->fd_data, 0, _st_kq_data->fd_data_size * sizeof(_kq_fd_data_t)); memset(_st_kq_data->fd_data, 0, _st_kq_data->fd_data_size * sizeof(_kq_fd_data_t));
for (q = _ST_IOQ.next; q != &_ST_IOQ; q = q->next) { for (q = _st_this_vp.io_q.next; q != &_st_this_vp.io_q; q = q->next) {
pq = _ST_POLLQUEUE_PTR(q); pq = _ST_POLLQUEUE_PTR(q);
_st_kq_pollset_add(pq->pds, pq->npds); _st_kq_pollset_add(pq->pds, pq->npds);
} }
@ -1064,10 +1064,10 @@ ST_HIDDEN void _st_epoll_dispatch(void)
++_st_stat_epoll; ++_st_stat_epoll;
#endif #endif
if (_ST_SLEEPQ == NULL) { if (_st_this_vp.sleep_q == NULL) {
timeout = -1; timeout = -1;
} else { } else {
min_timeout = (_ST_SLEEPQ->due <= _ST_LAST_CLOCK) ? 0 : (_ST_SLEEPQ->due - _ST_LAST_CLOCK); min_timeout = (_st_this_vp.sleep_q->due <= _st_this_vp.last_clock) ? 0 : (_st_this_vp.sleep_q->due - _st_this_vp.last_clock);
timeout = (int) (min_timeout / 1000); timeout = (int) (min_timeout / 1000);
// At least wait 1ms when <1ms, to avoid epoll_wait spin loop. // At least wait 1ms when <1ms, to avoid epoll_wait spin loop.
@ -1105,7 +1105,7 @@ ST_HIDDEN void _st_epoll_dispatch(void)
} }
} }
for (q = _ST_IOQ.next; q != &_ST_IOQ; q = q->next) { for (q = _st_this_vp.io_q.next; q != &_st_this_vp.io_q; q = q->next) {
pq = _ST_POLLQUEUE_PTR(q); pq = _ST_POLLQUEUE_PTR(q);
notify = 0; notify = 0;
epds = pq->pds + pq->npds; epds = pq->pds + pq->npds;
@ -1135,7 +1135,7 @@ ST_HIDDEN void _st_epoll_dispatch(void)
} }
} }
if (notify) { if (notify) {
ST_REMOVE_LINK(&pq->links); st_clist_remove(&pq->links);
pq->on_ioq = 0; pq->on_ioq = 0;
/* /*
* Here we will only delete/modify descriptors that * Here we will only delete/modify descriptors that
@ -1144,9 +1144,9 @@ ST_HIDDEN void _st_epoll_dispatch(void)
_st_epoll_pollset_del(pq->pds, pq->npds); _st_epoll_pollset_del(pq->pds, pq->npds);
if (pq->thread->flags & _ST_FL_ON_SLEEPQ) if (pq->thread->flags & _ST_FL_ON_SLEEPQ)
_ST_DEL_SLEEPQ(pq->thread); _st_del_sleep_q(pq->thread);
pq->thread->state = _ST_ST_RUNNABLE; pq->thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(pq->thread); st_clist_insert_before(&pq->thread->links, &_st_this_vp.run_q);
} }
} }

@ -78,7 +78,7 @@ int st_key_getlimit(void)
int st_thread_setspecific(int key, void *value) int st_thread_setspecific(int key, void *value)
{ {
_st_thread_t *me = _ST_CURRENT_THREAD(); _st_thread_t *me = _st_this_thread;
return st_thread_setspecific2(me, key, value); return st_thread_setspecific2(me, key, value);
} }
@ -107,7 +107,7 @@ void *st_thread_getspecific(int key)
if (key < 0 || key >= key_max) if (key < 0 || key >= key_max)
return NULL; return NULL;
return ((_ST_CURRENT_THREAD())->private_data[key]); return _st_this_thread->private_data[key];
} }

@ -74,13 +74,11 @@ typedef struct _st_jmp_buf {
long __jmpbuf[22]; long __jmpbuf[22];
} _st_jmp_buf_t[1]; } _st_jmp_buf_t[1];
/* Defined in *.S file and implemented by ASM. */
extern int _st_md_cxt_save(_st_jmp_buf_t env); extern int _st_md_cxt_save(_st_jmp_buf_t env);
extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val); extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
/* Always use builtin setjmp/longjmp, use asm code. */ /* Always use builtin setjmp/longjmp, use asm code. */
#define MD_USE_BUILTIN_SETJMP
#define MD_SETJMP(env) _st_md_cxt_save(env)
#define MD_LONGJMP(env, val) _st_md_cxt_restore(env, val)
#if defined(USE_LIBC_SETJMP) #if defined(USE_LIBC_SETJMP)
#error The libc setjmp is not supported now #error The libc setjmp is not supported now
#endif #endif
@ -103,13 +101,6 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
#error Unknown CPU architecture #error Unknown CPU architecture
#endif #endif
#define MD_INIT_CONTEXT(_thread, _sp, _main) \
ST_BEGIN_MACRO \
if (MD_SETJMP((_thread)->context)) \
_main(); \
MD_GET_SP(_thread) = (long) (_sp); \
ST_END_MACRO
#define MD_GET_UTIME() \ #define MD_GET_UTIME() \
struct timeval tv; \ struct timeval tv; \
(void) gettimeofday(&tv, NULL); \ (void) gettimeofday(&tv, NULL); \
@ -161,14 +152,7 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0])) #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))
#else #else
#error "Unknown CPU architecture" #error "Unknown CPU architecture"
#endif /* Cases with common MD_INIT_CONTEXT and different SP locations */ #endif
#define MD_INIT_CONTEXT(_thread, _sp, _main) \
ST_BEGIN_MACRO \
if (MD_SETJMP((_thread)->context)) \
_main(); \
MD_GET_SP(_thread) = (long) (_sp); \
ST_END_MACRO
#elif defined (CYGWIN64) #elif defined (CYGWIN64)
@ -177,21 +161,12 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
#define MD_ACCEPT_NB_INHERITED #define MD_ACCEPT_NB_INHERITED
#define MD_HAVE_SOCKLEN_T #define MD_HAVE_SOCKLEN_T
#define MD_USE_BUILTIN_SETJMP
#if defined(__amd64__) || defined(__x86_64__) #if defined(__amd64__) || defined(__x86_64__)
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[6])) #define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[6]))
#else #else
#error Unknown CPU architecture #error Unknown CPU architecture
#endif #endif
#define MD_INIT_CONTEXT(_thread, _sp, _main) \
ST_BEGIN_MACRO \
if (MD_SETJMP((_thread)->context)) \
_main(); \
MD_GET_SP(_thread) = (long) (_sp); \
ST_END_MACRO
#define MD_GET_UTIME() \ #define MD_GET_UTIME() \
struct timeval tv; \ struct timeval tv; \
(void) gettimeofday(&tv, NULL); \ (void) gettimeofday(&tv, NULL); \
@ -201,10 +176,6 @@ extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);
#error Unknown OS #error Unknown OS
#endif /* OS */ #endif /* OS */
#ifndef MD_STACK_PAD_SIZE
#define MD_STACK_PAD_SIZE 128
#endif
#if !defined(MD_HAVE_SOCKLEN_T) && !defined(socklen_t) #if !defined(MD_HAVE_SOCKLEN_T) && !defined(socklen_t)
#define socklen_t int #define socklen_t int
#endif #endif

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

@ -50,7 +50,7 @@
/* How much space to leave between the stacks, at each end */ /* How much space to leave between the stacks, at each end */
#define REDZONE _ST_PAGE_SIZE #define REDZONE _st_this_vp.pagesize
__thread _st_clist_t _st_free_stacks; __thread _st_clist_t _st_free_stacks;
__thread int _st_num_free_stacks = 0; __thread int _st_num_free_stacks = 0;
@ -71,7 +71,7 @@ _st_stack_t *_st_stack_new(int stack_size)
ts = _ST_THREAD_STACK_PTR(qp); ts = _ST_THREAD_STACK_PTR(qp);
if (ts->stk_size >= stack_size) { if (ts->stk_size >= stack_size) {
/* Found a stack that is big enough */ /* Found a stack that is big enough */
ST_REMOVE_LINK(&ts->links); st_clist_remove(&ts->links);
_st_num_free_stacks--; _st_num_free_stacks--;
ts->links.next = NULL; ts->links.next = NULL;
ts->links.prev = NULL; ts->links.prev = NULL;
@ -80,7 +80,7 @@ _st_stack_t *_st_stack_new(int stack_size)
} }
#endif #endif
extra = _st_randomize_stacks ? _ST_PAGE_SIZE : 0; extra = _st_randomize_stacks ? _st_this_vp.pagesize : 0;
/* If not cache stack, we will free all stack in the list, which contains the stack to be freed. /* If not cache stack, we will free all stack in the list, which contains the stack to be freed.
* Note that we should never directly free it at _st_stack_free, because it is still be used, * Note that we should never directly free it at _st_stack_free, because it is still be used,
* and will cause crash. */ * and will cause crash. */
@ -90,7 +90,7 @@ _st_stack_t *_st_stack_new(int stack_size)
/* Before qp is freed, move to next one, because the qp will be freed when free the ts. */ /* Before qp is freed, move to next one, because the qp will be freed when free the ts. */
qp = qp->next; qp = qp->next;
ST_REMOVE_LINK(&ts->links); st_clist_remove(&ts->links);
_st_num_free_stacks--; _st_num_free_stacks--;
#if defined(DEBUG) && !defined(MD_NO_PROTECT) #if defined(DEBUG) && !defined(MD_NO_PROTECT)
@ -142,7 +142,7 @@ void _st_stack_free(_st_stack_t *ts)
return; return;
/* Put the stack on the free list */ /* Put the stack on the free list */
ST_APPEND_LINK(&ts->links, _st_free_stacks.prev); st_clist_insert_before(&ts->links, _st_free_stacks.prev);
_st_num_free_stacks++; _st_num_free_stacks++;
} }

@ -87,7 +87,7 @@ int st_set_utime_function(st_utime_t (*func)(void))
st_utime_t st_utime_last_clock(void) st_utime_t st_utime_last_clock(void)
{ {
return _ST_LAST_CLOCK; return _st_this_vp.last_clock;
} }
@ -116,7 +116,7 @@ time_t st_time(void)
int st_usleep(st_utime_t usecs) int st_usleep(st_utime_t usecs)
{ {
_st_thread_t *me = _ST_CURRENT_THREAD(); _st_thread_t *me = _st_this_thread;
if (me->flags & _ST_FL_INTERRUPT) { if (me->flags & _ST_FL_INTERRUPT) {
me->flags &= ~_ST_FL_INTERRUPT; me->flags &= ~_ST_FL_INTERRUPT;
@ -126,11 +126,11 @@ int st_usleep(st_utime_t usecs)
if (usecs != ST_UTIME_NO_TIMEOUT) { if (usecs != ST_UTIME_NO_TIMEOUT) {
me->state = _ST_ST_SLEEPING; me->state = _ST_ST_SLEEPING;
_ST_ADD_SLEEPQ(me, usecs); _st_add_sleep_q(me, usecs);
} else } else
me->state = _ST_ST_SUSPENDED; me->state = _ST_ST_SUSPENDED;
_ST_SWITCH_CONTEXT(me); _st_switch_context(me);
if (me->flags & _ST_FL_INTERRUPT) { if (me->flags & _ST_FL_INTERRUPT) {
me->flags &= ~_ST_FL_INTERRUPT; me->flags &= ~_ST_FL_INTERRUPT;
@ -158,7 +158,7 @@ _st_cond_t *st_cond_new(void)
cvar = (_st_cond_t *) calloc(1, sizeof(_st_cond_t)); cvar = (_st_cond_t *) calloc(1, sizeof(_st_cond_t));
if (cvar) { if (cvar) {
ST_INIT_CLIST(&cvar->wait_q); st_clist_init(&cvar->wait_q);
} }
return cvar; return cvar;
@ -180,7 +180,7 @@ int st_cond_destroy(_st_cond_t *cvar)
int st_cond_timedwait(_st_cond_t *cvar, st_utime_t timeout) int st_cond_timedwait(_st_cond_t *cvar, st_utime_t timeout)
{ {
_st_thread_t *me = _ST_CURRENT_THREAD(); _st_thread_t *me = _st_this_thread;
int rv; int rv;
if (me->flags & _ST_FL_INTERRUPT) { if (me->flags & _ST_FL_INTERRUPT) {
@ -191,14 +191,14 @@ int st_cond_timedwait(_st_cond_t *cvar, st_utime_t timeout)
/* Put caller thread on the condition variable's wait queue */ /* Put caller thread on the condition variable's wait queue */
me->state = _ST_ST_COND_WAIT; me->state = _ST_ST_COND_WAIT;
ST_APPEND_LINK(&me->wait_links, &cvar->wait_q); st_clist_insert_before(&me->wait_links, &cvar->wait_q);
if (timeout != ST_UTIME_NO_TIMEOUT) if (timeout != ST_UTIME_NO_TIMEOUT)
_ST_ADD_SLEEPQ(me, timeout); _st_add_sleep_q(me, timeout);
_ST_SWITCH_CONTEXT(me); _st_switch_context(me);
ST_REMOVE_LINK(&me->wait_links); st_clist_remove(&me->wait_links);
rv = 0; rv = 0;
if (me->flags & _ST_FL_TIMEDOUT) { if (me->flags & _ST_FL_TIMEDOUT) {
@ -231,11 +231,11 @@ static int _st_cond_signal(_st_cond_t *cvar, int broadcast)
thread = _ST_THREAD_WAITQ_PTR(q); thread = _ST_THREAD_WAITQ_PTR(q);
if (thread->state == _ST_ST_COND_WAIT) { if (thread->state == _ST_ST_COND_WAIT) {
if (thread->flags & _ST_FL_ON_SLEEPQ) if (thread->flags & _ST_FL_ON_SLEEPQ)
_ST_DEL_SLEEPQ(thread); _st_del_sleep_q(thread);
/* Make thread runnable */ /* Make thread runnable */
thread->state = _ST_ST_RUNNABLE; thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(thread); st_clist_insert_before(&thread->links, &_st_this_vp.run_q);
if (!broadcast) if (!broadcast)
break; break;
} }
@ -267,7 +267,7 @@ _st_mutex_t *st_mutex_new(void)
lock = (_st_mutex_t *) calloc(1, sizeof(_st_mutex_t)); lock = (_st_mutex_t *) calloc(1, sizeof(_st_mutex_t));
if (lock) { if (lock) {
ST_INIT_CLIST(&lock->wait_q); st_clist_init(&lock->wait_q);
lock->owner = NULL; lock->owner = NULL;
} }
@ -290,7 +290,7 @@ int st_mutex_destroy(_st_mutex_t *lock)
int st_mutex_lock(_st_mutex_t *lock) int st_mutex_lock(_st_mutex_t *lock)
{ {
_st_thread_t *me = _ST_CURRENT_THREAD(); _st_thread_t *me = _st_this_thread;
if (me->flags & _ST_FL_INTERRUPT) { if (me->flags & _ST_FL_INTERRUPT) {
me->flags &= ~_ST_FL_INTERRUPT; me->flags &= ~_ST_FL_INTERRUPT;
@ -311,11 +311,11 @@ int st_mutex_lock(_st_mutex_t *lock)
/* Put caller thread on the mutex's wait queue */ /* Put caller thread on the mutex's wait queue */
me->state = _ST_ST_LOCK_WAIT; me->state = _ST_ST_LOCK_WAIT;
ST_APPEND_LINK(&me->wait_links, &lock->wait_q); st_clist_insert_before(&me->wait_links, &lock->wait_q);
_ST_SWITCH_CONTEXT(me); _st_switch_context(me);
ST_REMOVE_LINK(&me->wait_links); st_clist_remove(&me->wait_links);
if ((me->flags & _ST_FL_INTERRUPT) && lock->owner != me) { if ((me->flags & _ST_FL_INTERRUPT) && lock->owner != me) {
me->flags &= ~_ST_FL_INTERRUPT; me->flags &= ~_ST_FL_INTERRUPT;
@ -332,7 +332,7 @@ int st_mutex_unlock(_st_mutex_t *lock)
_st_thread_t *thread; _st_thread_t *thread;
_st_clist_t *q; _st_clist_t *q;
if (lock->owner != _ST_CURRENT_THREAD()) { if (lock->owner != _st_this_thread) {
errno = EPERM; errno = EPERM;
return -1; return -1;
} }
@ -343,7 +343,7 @@ int st_mutex_unlock(_st_mutex_t *lock)
lock->owner = thread; lock->owner = thread;
/* Make thread runnable */ /* Make thread runnable */
thread->state = _ST_ST_RUNNABLE; thread->state = _ST_ST_RUNNABLE;
_ST_ADD_RUNQ(thread); st_clist_insert_before(&thread->links, &_st_this_vp.run_q);
return 0; return 0;
} }
} }
@ -363,7 +363,7 @@ int st_mutex_trylock(_st_mutex_t *lock)
} }
/* Got the mutex */ /* Got the mutex */
lock->owner = _ST_CURRENT_THREAD(); lock->owner = _st_this_thread;
return 0; return 0;
} }

6
trunk/configure vendored

@ -128,7 +128,7 @@ fi
# Start to generate the Makefile. # Start to generate the Makefile.
cat << END >> ${SRS_OBJS}/Makefile cat << END >> ${SRS_OBJS}/Makefile
GCC = ${SRS_TOOL_CC} CC = ${SRS_TOOL_CC}
CXX = ${SRS_TOOL_CXX} CXX = ${SRS_TOOL_CXX}
AR = ${SRS_TOOL_AR} AR = ${SRS_TOOL_AR}
LINK = ${SRS_TOOL_CXX} LINK = ${SRS_TOOL_CXX}
@ -514,7 +514,7 @@ cat << END > ${SRS_MAKEFILE}
.PHONY: clean_srs clean_modules clean_openssl clean_srtp2 clean_opus clean_ffmpeg clean_st .PHONY: clean_srs clean_modules clean_openssl clean_srtp2 clean_opus clean_ffmpeg clean_st
.PHONY: st ffmpeg .PHONY: st ffmpeg
GCC = ${SRS_TOOL_CC} CC = ${SRS_TOOL_CC}
CXX = ${SRS_TOOL_CXX} CXX = ${SRS_TOOL_CXX}
AR = ${SRS_TOOL_AR} AR = ${SRS_TOOL_AR}
LINK = ${SRS_TOOL_LD} LINK = ${SRS_TOOL_LD}
@ -606,7 +606,7 @@ clean_st:
st: st:
@rm -f ${SRS_OBJS}/srs srs_utest @rm -f ${SRS_OBJS}/srs srs_utest
@\$(MAKE)\$(JOBS) -C ${SRS_OBJS}/${SRS_PLATFORM}/st-srs clean @\$(MAKE)\$(JOBS) -C ${SRS_OBJS}/${SRS_PLATFORM}/st-srs clean
@env EXTRA_CFLAGS="${_ST_EXTRA_CFLAGS}" \$(MAKE)\$(JOBS) -C ${SRS_OBJS}/${SRS_PLATFORM}/st-srs ${_ST_MAKE_ARGS} CC=\$(GCC) AR=\$(AR) LD=\$(LINK) RANDLIB=\$(RANDLIB) @env EXTRA_CFLAGS="${_ST_EXTRA_CFLAGS}" \$(MAKE)\$(JOBS) -C ${SRS_OBJS}/${SRS_PLATFORM}/st-srs ${_ST_MAKE_ARGS} CC=\$(CC) CXX=\$(CXX) AR=\$(AR) LD=\$(LINK) RANDLIB=\$(RANDLIB)
@echo "Please rebuild srs by: make" @echo "Please rebuild srs by: make"
ffmpeg: ffmpeg:

@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v7-changes"></a> <a name="v7-changes"></a>
## SRS 7.0 Changelog ## SRS 7.0 Changelog
* v7.0, 2024-08-21, Merge [#4149](https://github.com/ossrs/srs/pull/4149): ST: Replace macros with explicit code for better understanding. v7.0.7 (#4149)
* v7.0, 2024-08-21, Merge [#4150](https://github.com/ossrs/srs/pull/4150): API: Support new HTTP API for VALGRIND. v7.0.6 (#4150) * v7.0, 2024-08-21, Merge [#4150](https://github.com/ossrs/srs/pull/4150): API: Support new HTTP API for VALGRIND. v7.0.6 (#4150)
* v7.0, 2024-08-15, Merge [#4144](https://github.com/ossrs/srs/pull/4144): HTTP-FLV: Crash when multiple viewers. v7.0.5 (#4144) * v7.0, 2024-08-15, Merge [#4144](https://github.com/ossrs/srs/pull/4144): HTTP-FLV: Crash when multiple viewers. v7.0.5 (#4144)
* v7.0, 2024-08-15, Merge [#4142](https://github.com/ossrs/srs/pull/4142): Config: Add more utest for env config. v7.0.4 (#4142) * v7.0, 2024-08-15, Merge [#4142](https://github.com/ossrs/srs/pull/4142): Config: Add more utest for env config. v7.0.4 (#4142)

@ -3,3 +3,10 @@ udp-client
cost cost
cost.log cost.log
thread-join thread-join
st-cond
hello-st
hello-world
huge-threads
exceptions
hello
pthreads

@ -0,0 +1,26 @@
/*
g++ st-cond.cpp ../../objs/st/libst.a -g -O0 -o st-cond && ./st-cond
*/
#include <stdio.h>
#include "../../objs/st/st.h"
st_cond_t lock;
void* foo(void*) {
st_cond_wait(lock);
printf("Hello World, ST!\n");
return NULL;
}
int main() {
st_init();
lock = st_cond_new();
st_thread_create(foo, NULL, 0, 0);
st_sleep(1);
st_cond_signal(lock);
st_sleep(1);
st_cond_destroy(lock);
return 0;
}

@ -9,6 +9,6 @@
#define VERSION_MAJOR 7 #define VERSION_MAJOR 7
#define VERSION_MINOR 0 #define VERSION_MINOR 0
#define VERSION_REVISION 6 #define VERSION_REVISION 7
#endif #endif
Loading…
Cancel
Save