diff --git a/README.md b/README.md index 31be27a..93b982c 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/common.h b/common.h index 7733814..ab3a0c1 100644 --- a/common.h +++ b/common.h @@ -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 { @@ -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 */ }; diff --git a/md.h b/md.h index 4a3f82e..d3158db 100644 --- a/md.h +++ b/md.h @@ -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 */ @@ -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 @@ -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); \ @@ -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) @@ -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 @@ -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); \ diff --git a/sched.c b/sched.c index 4d37e48..0ef56ca 100644 --- a/sched.c +++ b/sched.c @@ -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; @@ -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(); @@ -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)) { @@ -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 */ diff --git a/tools/jmpbuf/Makefile b/tools/jmpbuf/Makefile index a0e3d58..11271b0 100644 --- a/tools/jmpbuf/Makefile +++ b/tools/jmpbuf/Makefile @@ -1,5 +1,6 @@ .PHONY: default clean +LDLIBS= CFLAGS=-g -O0 OS_NAME = $(shell uname -s) @@ -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 diff --git a/tools/jmpbuf/jmpbuf.c b/tools/jmpbuf/jmpbuf.c index d26d89f..ebde2f5 100644 --- a/tools/jmpbuf/jmpbuf.c +++ b/tools/jmpbuf/jmpbuf.c @@ -4,13 +4,36 @@ #include #include +/* 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; }