Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Define and use a new jmpbuf, because the structure is different. #29

Merged
merged 1 commit into from
Sep 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ make cygwin64-debug

## Branch SRS

The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patched the following patches:
The branch [srs](https://github.com/ossrs/state-threads/tree/srs) was patched and refined:

- [x] ARM: Patch [st.arm.patch](https://github.com/ossrs/srs/blob/2.0release/trunk/3rdparty/patches/1.st.arm.patch), for ARM.
- [x] OSX: Patch [st.osx.kqueue.patch](https://github.com/ossrs/srs/blob/2.0release/trunk/3rdparty/patches/3.st.osx.kqueue.patch), for osx.
Expand All @@ -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;
}