Skip to content

Commit

Permalink
Define and use a new jmpbuf, because the structure is different.
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Aug 7, 2022
1 parent 6610914 commit 9d87f24
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 167 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche
- [x] System: Support Multiple Threads for Linux and Darwin. [#19](https://github.com/ossrs/state-threads/issues/19), [srs#2188](https://github.com/ossrs/srs/issues/2188).
- [x] RISCV: Support RISCV for RISCV CPU, [#24](https://github.com/ossrs/state-threads/pull/28).
- [x] MIPS: Support Linux/MIPS64 for loongson 3A4000/3B3000, [#21](https://github.com/ossrs/state-threads/pull/21).
- [x] Define and use a new jmpbuf, because the structure is different.
- [ ] IDE: Support CLion for debugging and learning.
- [ ] System: Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12).

Expand Down
3 changes: 1 addition & 2 deletions common.h
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,6 @@ typedef struct _st_cond {
_st_clist_t wait_q; /* Condition variable wait queue */
} _st_cond_t;


typedef struct _st_thread _st_thread_t;

struct _st_thread {
Expand Down Expand Up @@ -198,7 +197,7 @@ struct _st_thread {

_st_cond_t *term; /* Termination condition variable for join */

jmp_buf context; /* Thread's context */
_st_jmp_buf_t context; /* Thread's context */
};


Expand Down
188 changes: 61 additions & 127 deletions md.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,34 @@
#define MAP_FAILED -1
#endif

/* We define the jmpbuf, because the system's is different in different OS */
typedef struct _st_jmp_buf {
/*
* OS CPU SIZE
* Darwin __amd64__/__x86_64__ long[8]
* Linux __i386__ long[6]
* Linux __amd64__/__x86_64__ long[8]
* Linux __aarch64__ long[22]
* Linux __arm__ long[16]
* Linux __mips__/__mips64 long[13]
* Linux __riscv long[14]
* Linux __loongarch64 long[12]
* Cygwin64 __amd64__/__x86_64__ long[8]
*/
long __jmpbuf[22];
} _st_jmp_buf_t[1];

extern int _st_md_cxt_save(_st_jmp_buf_t env);
extern void _st_md_cxt_restore(_st_jmp_buf_t env, int val);

/* 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)
#error The libc setjmp is not supported now
#endif

/*****************************************
* Platform specifics
*/
Expand All @@ -66,11 +94,8 @@
#define MD_ACCEPT_NB_INHERITED
#define MD_HAVE_SOCKLEN_T

#define MD_USE_BUILTIN_SETJMP

#if defined(__amd64__) || defined(__x86_64__)
#define JB_SP 12 /* The jmpbuf is int(4B) array, while MD_GET_SP covert to long(8B) pointer, so the JB_SP should be 12 which is 6*sizeof(long)/sizeof(int) */
#define MD_GET_SP(_t) *((long *)&((_t)->context[JB_SP]))
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[6]))
#else
#error Unknown CPU architecture
#endif
Expand All @@ -82,14 +107,6 @@
MD_GET_SP(_thread) = (long) (_sp); \
ST_END_MACRO

#if defined(MD_USE_BUILTIN_SETJMP)
#define MD_SETJMP(env) _st_md_cxt_save(env)
#define MD_LONGJMP(env, val) _st_md_cxt_restore(env, val)

extern int _st_md_cxt_save(jmp_buf env);
extern void _st_md_cxt_restore(jmp_buf env, int val);
#endif

#define MD_GET_UTIME() \
struct timeval tv; \
(void) gettimeofday(&tv, NULL); \
Expand Down Expand Up @@ -117,112 +134,38 @@
(void) gettimeofday(&tv, NULL); \
return (tv.tv_sec * 1000000LL + tv.tv_usec)

#if 1

/*
* On linux, there are a few styles of jmpbuf format. These vary based
* on architecture/glibc combination.
*
* Most of the glibc based toggles were lifted from:
* mozilla/nsprpub/pr/include/md/_linux.h
*/

/*
* Starting with glibc 2.4, JB_SP definitions are not public anymore.
* They, however, can still be found in glibc source tree in
* architecture-specific "jmpbuf-offsets.h" files.
* Most importantly, the content of jmp_buf is mangled by setjmp to make
* it completely opaque (the mangling can be disabled by setting the
* LD_POINTER_GUARD environment variable before application execution).
* Therefore we will use built-in _st_md_cxt_save/_st_md_cxt_restore
* functions as a setjmp/longjmp replacement wherever they are available
* unless USE_LIBC_SETJMP is defined.
*/

#if defined(__i386__)
#define MD_USE_BUILTIN_SETJMP

#if defined(__GLIBC__) && __GLIBC__ >= 2
#ifndef JB_SP
#define JB_SP 4
#endif
#define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_SP]
#else
/* not an error but certainly cause for caution */
#error "Untested use of old glibc on i386"
#define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[0].__sp
#endif

#elif defined(__amd64__) || defined(__x86_64__)
#define MD_USE_BUILTIN_SETJMP

#ifndef JB_RSP
#define JB_RSP 6
#endif
#define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[JB_RSP]

#elif defined(__aarch64__)
/* https://github.com/ossrs/state-threads/issues/9 */
#define MD_USE_BUILTIN_SETJMP
#define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[13]

#elif defined(__arm__)
/* https://github.com/ossrs/state-threads/issues/1#issuecomment-244648573 */
#define MD_USE_BUILTIN_SETJMP

/* force to use glibc solution, hack the guard jmpbuf from michaeltalyansky */
#ifdef USE_LIBC_SETJMP
#undef MD_USE_BUILTIN_SETJMP
#endif

#if defined(__GLIBC__) && __GLIBC__ >= 2
/* Merge from https://github.com/michaeltalyansky/state-threads/commit/56554a5c425aee8e7a73782eae23d74d83c4120a */
#define MD_GET_SP(_t) (_t)->context[0].__jmpbuf[8]
#else
#error "ARM/Linux pre-glibc2 not supported yet"
#endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */

#elif defined(__mips64)
/* https://github.com/ossrs/state-threads/issues/21 */
#define MD_USE_BUILTIN_SETJMP
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))
#elif defined(__mips__)
/* https://github.com/ossrs/state-threads/issues/21 */
#define MD_USE_BUILTIN_SETJMP
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jb[0]))
#elif defined(__riscv)
/* https://github.com/ossrs/state-threads/pull/28 */
#define MD_USE_BUILTIN_SETJMP
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))

#elif defined(__loongarch64)
/* https://github.com/ossrs/state-threads/issues/24 */
#define MD_USE_BUILTIN_SETJMP
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))

#else
#error "Unknown CPU architecture"
#endif /* Cases with common MD_INIT_CONTEXT and different SP locations */

#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

#endif /* Cases with different MD_INIT_CONTEXT */

#if defined(MD_USE_BUILTIN_SETJMP) && !defined(USE_LIBC_SETJMP)
#define MD_SETJMP(env) _st_md_cxt_save(env)
#define MD_LONGJMP(env, val) _st_md_cxt_restore(env, val)

extern int _st_md_cxt_save(jmp_buf env);
extern void _st_md_cxt_restore(jmp_buf env, int val);
#if defined(__i386__)
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[4]))
#elif defined(__amd64__) || defined(__x86_64__)
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[6]))
#elif defined(__aarch64__)
/* https://github.com/ossrs/state-threads/issues/9 */
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[13]))
#elif defined(__arm__)
/* https://github.com/ossrs/state-threads/issues/1#issuecomment-244648573 */
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[8]))
#elif defined(__mips64)
/* https://github.com/ossrs/state-threads/issues/21 */
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))
#elif defined(__mips__)
/* https://github.com/ossrs/state-threads/issues/21 */
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))
#elif defined(__riscv)
/* https://github.com/ossrs/state-threads/pull/28 */
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))
#elif defined(__loongarch64)
/* https://github.com/ossrs/state-threads/issues/24 */
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[0]))
#else
#define MD_SETJMP(env) setjmp(env)
#define MD_LONGJMP(env, val) longjmp(env, val)
#endif
#error "Unknown CPU architecture"
#endif /* Cases with common MD_INIT_CONTEXT and different SP locations */

#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)

Expand All @@ -234,8 +177,7 @@
#define MD_USE_BUILTIN_SETJMP

#if defined(__amd64__) || defined(__x86_64__)
#define JB_SP 6 // The context is long(32) array, @see https://github.com/ossrs/state-threads/issues/20#issuecomment-887569093
#define MD_GET_SP(_t) *((long *)&((_t)->context[JB_SP]))
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[6]))
#else
#error Unknown CPU architecture
#endif
Expand All @@ -247,14 +189,6 @@
MD_GET_SP(_thread) = (long) (_sp); \
ST_END_MACRO

#if defined(MD_USE_BUILTIN_SETJMP)
#define MD_SETJMP(env) _st_md_cxt_save(env)
#define MD_LONGJMP(env, val) _st_md_cxt_restore(env, val)

extern int _st_md_cxt_save(jmp_buf env);
extern void _st_md_cxt_restore(jmp_buf env, int val);
#endif

#define MD_GET_UTIME() \
struct timeval tv; \
(void) gettimeofday(&tv, NULL); \
Expand Down
20 changes: 10 additions & 10 deletions md_linux.S
Original file line number Diff line number Diff line change
Expand Up @@ -189,16 +189,16 @@
#define JB_X28 9
#define JB_X29 10
#define JB_LR 11
#define JB_SP 13

#define JB_D8 14
#define JB_D9 15
#define JB_D10 16
#define JB_D11 17
#define JB_D12 18
#define JB_D13 19
#define JB_D14 20
#define JB_D15 21
#define JB_SP 13

#define JB_D8 14
#define JB_D9 15
#define JB_D10 16
#define JB_D11 17
#define JB_D12 18
#define JB_D13 19
#define JB_D14 20
#define JB_D15 21

.file "md.S"
.text
Expand Down
31 changes: 7 additions & 24 deletions sched.c
Original file line number Diff line number Diff line change
Expand Up @@ -618,15 +618,6 @@ void st_thread_interrupt(_st_thread_t *thread)
}


/* Merge from https://github.com/michaeltalyansky/state-threads/commit/cce736426c2320ffec7c9820df49ee7a18ae638c */
#if defined(__arm__) && !defined(MD_USE_BUILTIN_SETJMP) && __GLIBC_MINOR__ >= 19
extern unsigned long __pointer_chk_guard;
#define PTR_MANGLE(var) \
(var) = (__typeof (var)) ((unsigned long) (var) ^ __pointer_chk_guard)
#define PTR_DEMANGLE(var) PTR_MANGLE (var)
#endif


_st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinable, int stk_size)
{
_st_thread_t *thread;
Expand Down Expand Up @@ -662,17 +653,9 @@ _st_thread_t *st_thread_create(void *(*start)(void *arg), void *arg, int joinabl
thread->stack = stack;
thread->start = start;
thread->arg = arg;

/* Merge from https://github.com/michaeltalyansky/state-threads/commit/cce736426c2320ffec7c9820df49ee7a18ae638c */
#if defined(__arm__) && !defined(MD_USE_BUILTIN_SETJMP) && __GLIBC_MINOR__ >= 19
volatile void * lsp = PTR_MANGLE(stack->sp);
if (_setjmp ((thread)->context))
_st_thread_main();
(thread)->context[0].__jmpbuf[8] = (long) (lsp);
#else
_ST_INIT_CONTEXT(thread, stack->sp, _st_thread_main);
#endif


_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();
Expand Down Expand Up @@ -720,19 +703,19 @@ int _st_iterate_threads_flag = 0;
void _st_iterate_threads(void)
{
static __thread _st_thread_t *thread = NULL;
static __thread jmp_buf orig_jb, save_jb;
static __thread _st_jmp_buf_t orig_jb, save_jb;
_st_clist_t *q;

if (!_st_iterate_threads_flag) {
if (thread) {
memcpy(thread->context, save_jb, sizeof(jmp_buf));
memcpy(thread->context, save_jb, sizeof(_st_jmp_buf_t));
MD_LONGJMP(orig_jb, 1);
}
return;
}

if (thread) {
memcpy(thread->context, save_jb, sizeof(jmp_buf));
memcpy(thread->context, save_jb, sizeof(_st_jmp_buf_t));
_st_show_thread_stack(thread, NULL);
} else {
if (MD_SETJMP(orig_jb)) {
Expand All @@ -752,7 +735,7 @@ void _st_iterate_threads(void)
thread = _ST_THREAD_THREADQ_PTR(q);
if (thread == _ST_CURRENT_THREAD())
MD_LONGJMP(orig_jb, 1);
memcpy(save_jb, thread->context, sizeof(jmp_buf));
memcpy(save_jb, thread->context, sizeof(_st_jmp_buf_t));
MD_LONGJMP(thread->context, 1);
}
#endif /* DEBUG */
Expand Down
5 changes: 3 additions & 2 deletions tools/jmpbuf/Makefile
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
.PHONY: default clean pre

LDLIBS=
CFLAGS=-g -O0

default: ./jmpbuf pre

./jmpbuf: jmpbuf.c
./jmpbuf: jmpbuf.c $(LDLIBS)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^ $(LDLIBS)

pre: jmpbuf.c
pre: jmpbuf.c $(LDLIBS)
$(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -E -o jmpbuf.E.c $^ $(LDLIBS)

clean:
Expand Down
Loading

0 comments on commit 9d87f24

Please sign in to comment.