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 24, 2022
1 parent 6df526e commit c15dc0d
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 159 deletions.
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,8 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche
- [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] AppleM1: Support Apple Silicon M1(aarch64), [#30](https://github.com/ossrs/state-threads/issues/30).
- [ ] IDE: Support CLion for debugging and learning.
- [x] IDE: Support CLion for debugging and learning.
- [x] Define and use a new jmpbuf, because the structure is different.
- [ ] System: Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12).

## GDB Tools
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
192 changes: 63 additions & 129 deletions md.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,35 @@
#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]
* Darwin __aarch64__ long[22]
* 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,14 +95,10 @@
#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]))
#elif defined(__aarch64__)
/* MUST be SP*2 because context is int array */
#define MD_GET_SP(_t) *((long *)&((_t)->context[13 * 2]))
#define MD_GET_SP(_t) *((long *)&((_t)->context[0].__jmpbuf[13]))
#else
#error Unknown CPU architecture
#endif
Expand All @@ -85,14 +110,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 @@ -120,112 +137,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 @@ -237,8 +180,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 @@ -250,14 +192,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
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
3 changes: 2 additions & 1 deletion tools/jmpbuf/Makefile
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
.PHONY: default clean

LDLIBS=
CFLAGS=-g -O0

OS_NAME = $(shell uname -s)
Expand All @@ -13,7 +14,7 @@ endif

default: ./jmpbuf ./jmpbuf.E.c

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

./jmpbuf.E.c: jmpbuf.c
Expand Down
27 changes: 25 additions & 2 deletions tools/jmpbuf/jmpbuf.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,36 @@
#include <stdio.h>
#include <setjmp.h>

/* 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]
* Darwin __aarch64__ long[22]
* 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];

int main(int argc, char** argv)
{
jmp_buf ctx = {0};
int r0 = setjmp(ctx);

int nn_jb = sizeof(ctx);
printf("r0=%d, sizeof(jmp_buf)=%d (unsigned long long [%d])\n", r0, nn_jb, nn_jb/8);
printf("jmp_buf: r0=%d, sizeof(jmp_buf)=%d (unsigned long long [%d])\n", r0, nn_jb, nn_jb/8);

_st_jmp_buf_t ctx2 = {0};
int r1 = sizeof(_st_jmp_buf_t);
int r2 = sizeof(ctx2);
printf("_st_jmp_buf_t: sizeof(_st_jmp_buf_t)=%d/%d (unsigned long long [%d])\n", r1, r2, r2/8);

return 0;
}

0 comments on commit c15dc0d

Please sign in to comment.