From 33abc6966568ac73f13f52390ae5055fe7be0399 Mon Sep 17 00:00:00 2001 From: winlin Date: Fri, 1 Oct 2021 22:37:06 +0800 Subject: [PATCH] MIPS: Support Linux/MIPS for OpenWRT, #21 --- README.md | 4 +- md.h | 15 +++---- md_linux.S | 80 +++++++++++++++++++++++++++++++++++ tools/helloworld/.gitignore | 1 + tools/helloworld/Makefile | 11 +++++ tools/helloworld/helloworld.c | 20 +++++++++ tools/porting/porting.c | 27 ++++++++++-- tools/verify/Makefile | 4 +- tools/verify/verify.c | 11 +++-- 9 files changed, 154 insertions(+), 19 deletions(-) create mode 100644 tools/helloworld/.gitignore create mode 100644 tools/helloworld/Makefile create mode 100644 tools/helloworld/helloworld.c diff --git a/README.md b/README.md index 1fef6d2..e04a6c9 100644 --- a/README.md +++ b/README.md @@ -87,8 +87,8 @@ The branch [srs](https://github.com/ossrs/state-threads/tree/srs) will be patche - [x] System: Support utest by gtest and coverage by gcov/gocvr. - [x] System: Only support for Linux and Darwin. [#19](https://github.com/ossrs/state-threads/issues/19), [srs#2188](https://github.com/ossrs/srs/issues/2188). - [x] System: Improve the performance of timer. [9fe8cfe5b](https://github.com/ossrs/state-threads/commit/9fe8cfe5b1c9741a2e671a46215184f267fba400), [7879c2b](https://github.com/ossrs/state-threads/commit/7879c2b), [387cddb](https://github.com/ossrs/state-threads/commit/387cddb) -- [ ] Windows: Support Windows 64bits. [#20](https://github.com/ossrs/state-threads/issues/20). -- [ ] MIPS: Support Linux/MIPS for OpenWRT, [#21](https://github.com/ossrs/state-threads/issues/21). +- [x] Windows: Support Windows 64bits. [#20](https://github.com/ossrs/state-threads/issues/20). +- [x] MIPS: Support Linux/MIPS for OpenWRT, [#21](https://github.com/ossrs/state-threads/issues/21). - [ ] 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). - [ ] System: Support sendmmsg for UDP, [#12](https://github.com/ossrs/state-threads/issues/12). diff --git a/md.h b/md.h index eff694d..0376120 100644 --- a/md.h +++ b/md.h @@ -117,15 +117,7 @@ (void) gettimeofday(&tv, NULL); \ return (tv.tv_sec * 1000000LL + tv.tv_usec) - #if defined(__mips__) - #define MD_INIT_CONTEXT(_thread, _sp, _main) \ - ST_BEGIN_MACRO \ - MD_SETJMP((_thread)->context); \ - _thread->context[0].__jmpbuf[0].__pc = (__ptr_t) _main; \ - _thread->context[0].__jmpbuf[0].__sp = _sp; \ - ST_END_MACRO - - #else /* Not mips */ + #if 1 /* * On linux, there are a few styles of jmpbuf format. These vary based @@ -190,6 +182,11 @@ #error "ARM/Linux pre-glibc2 not supported yet" #endif /* defined(__GLIBC__) && __GLIBC__ >= 2 */ + #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])) + #else #error "Unknown CPU architecture" #endif /* Cases with common MD_INIT_CONTEXT and different SP locations */ diff --git a/md_linux.S b/md_linux.S index 2dece86..333b2e3 100644 --- a/md_linux.S +++ b/md_linux.S @@ -348,6 +348,86 @@ /****************************************************************/ + + + + + + + + + +#elif defined(__mips__) + + /****************************************************************/ + + /* + * Internal __jmp_buf layout + */ + #define JB_SP 0 /* Stack pointer */ + #define JB_RA 11 /* Return address */ + #define JB_GP 1 /* Global pointer */ + #define JB_S0 3 /* S0-S7, Saved temporaries */ + #define JB_S1 4 /* S0-S7, Saved temporaries */ + #define JB_S2 5 /* S0-S7, Saved temporaries */ + #define JB_S3 6 /* S0-S7, Saved temporaries */ + #define JB_S4 7 /* S0-S7, Saved temporaries */ + #define JB_S5 8 /* S0-S7, Saved temporaries */ + #define JB_S6 9 /* S0-S7, Saved temporaries */ + #define JB_S7 10 /* S0-S7, Saved temporaries */ + #define JB_FP 2 /* FP/S8 Frame pointer */ + + .file "md_linux.S" + .text + + /* _st_md_cxt_save(__jmp_buf env) */ /* The env is $a0, https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions */ + .globl _st_md_cxt_save + .type _st_md_cxt_save, %function + .align 2 + _st_md_cxt_save: + sw $sp, 0($a0) /* Save sp to env[0], *(long*)($a0+0) =sp */ + sw $ra, 4($a0) /* Save ra to env[1], *(long*)($a0+4)=ra, the return address, https://chortle.ccsu.edu/AssemblyTutorial/Chapter-26/ass26_4.html */ + sw $gp, 8($a0) /* Save gp to env[2], *(long*)($a0+8) =gp */ + sw $s0, 12($a0) /* Save s0 to env[3], *(long*)($a0+12)=s0 */ + sw $s1, 16($a0) /* Save s1 to env[4], *(long*)($a0+16)=s1 */ + sw $s2, 20($a0) /* Save s2 to env[5], *(long*)($a0+20)=s2 */ + sw $s3, 24($a0) /* Save s3 to env[6], *(long*)($a0+24)=s3 */ + sw $s4, 28($a0) /* Save s4 to env[7], *(long*)($a0+28)=s4 */ + sw $s5, 32($a0) /* Save s5 to env[8], *(long*)($a0+32)=s5 */ + sw $s6, 36($a0) /* Save s6 to env[9], *(long*)($a0+36)=s6 */ + sw $s7, 40($a0) /* Save s7 to env[10], *(long*)($a0+40)=s7 */ + sw $fp, 44($a0) /* Save fp to env[11], *(long*)($a0+44) =fp */ + li $v0, 0 /* Set return value to 0 */ + jr $ra /* Return */ + + .size _st_md_cxt_save, .-_st_md_cxt_save + + /****************************************************************/ + + /* _st_md_cxt_restore(__jmp_buf env, int val) */ + .globl _st_md_cxt_restore + .type _st_md_cxt_restore, %function + .align 2 + _st_md_cxt_restore: + lw $sp, 0($a0) /* Load sp from env[0], sp=*(long*)($a0+0) */ + lw $ra, 4($a0) /* Load sp from env[1], ra=*(long*)($a0+4), the saved return address */ + lw $gp, 8($a0) /* Load sp from env[2], gp=*(long*)($a0+8) */ + lw $s0, 12($a0) /* Load sp from env[3], s0=*(long*)($a0+12) */ + lw $s1, 16($a0) /* Load sp from env[4], s1=*(long*)($a0+16) */ + lw $s2, 20($a0) /* Load sp from env[5], s2=*(long*)($a0+20) */ + lw $s3, 24($a0) /* Load sp from env[6], s3=*(long*)($a0+24) */ + lw $s4, 28($a0) /* Load sp from env[7], s4=*(long*)($a0+28) */ + lw $s5, 32($a0) /* Load sp from env[8], s5=*(long*)($a0+32) */ + lw $s6, 36($a0) /* Load sp from env[9], s6=*(long*)($a0+36) */ + lw $s7, 40($a0) /* Load sp from env[10], s7=*(long*)($a0+40) */ + lw $fp, 44($a0) /* Load sp from env[2], fp=*(long*)($a0+44) */ + li $v0, 1 /* Set return value to 1 */ + jr $ra /* Return to the saved return address */ + + .size _st_md_cxt_restore, .-_st_md_cxt_restore + + /****************************************************************/ + #endif #endif diff --git a/tools/helloworld/.gitignore b/tools/helloworld/.gitignore new file mode 100644 index 0000000..31e0fce --- /dev/null +++ b/tools/helloworld/.gitignore @@ -0,0 +1 @@ +helloworld diff --git a/tools/helloworld/Makefile b/tools/helloworld/Makefile new file mode 100644 index 0000000..2ec9a2d --- /dev/null +++ b/tools/helloworld/Makefile @@ -0,0 +1,11 @@ +.PHONY: clean + +LDLIBS=../../obj/libst.a +CFLAGS=-g -O0 -I../../obj + +./helloworld: helloworld.c $(LDLIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o helloworld helloworld.c $(LDLIBS) + +clean: + rm -f helloworld + diff --git a/tools/helloworld/helloworld.c b/tools/helloworld/helloworld.c new file mode 100644 index 0000000..d29fb5d --- /dev/null +++ b/tools/helloworld/helloworld.c @@ -0,0 +1,20 @@ +/* SPDX-License-Identifier: MIT */ +/* Copyright (c) 2021 Winlin */ + +#include + +#include + +int main(int argc, char** argv) +{ + st_set_eventsys(ST_EVENTSYS_ALT); + st_init(); + + for (int i = 0; i < 10000; i++) { + printf("#%03d, Hello, state-threads world!\n", i); + st_sleep(1); + } + + return 0; +} + diff --git a/tools/porting/porting.c b/tools/porting/porting.c index d07db2f..7dfdfa6 100644 --- a/tools/porting/porting.c +++ b/tools/porting/porting.c @@ -4,6 +4,8 @@ #include #include +int foo_return_zero(); +int foo_return_one(); extern void print_buf(unsigned char* p, int nn_jb); extern void print_jmpbuf(); @@ -37,17 +39,33 @@ int main(int argc, char** argv) printf("sizeof(__ptr_t)=%d\n", sizeof(__ptr_t)); #endif + printf("\nReturn value:\n"); + int r0 = foo_return_zero(); + int r1 = foo_return_one(); + printf("foo_return_zero=%d, foo_return_one=%d\n", r0, r1); + printf("\nCalling conventions:\n"); print_jmpbuf(); return 0; } +int foo_return_zero() +{ + return 0; +} + +int foo_return_one() +{ + return 1; +} + #ifdef __linux__ #ifdef __mips__ void print_jmpbuf() { // https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions + register void* ra asm("ra"); register void* gp asm("gp"); register void* sp asm("sp"); register void* fp asm("fp"); @@ -60,8 +78,6 @@ void print_jmpbuf() register void* s5 asm("s5"); register void* s6 asm("s6"); register void* s7 asm("s7"); - printf("gp=%p, fp=%p, sp=%p, s0=%p, s1=%p, s2=%p, s3=%p, s4=%p, s5=%p, s6=%p, s7=%p\n", - gp, fp, sp, s0, s1, s2, s3, s4, s5, s6, s7); /* typedef unsigned long long __jmp_buf[13]; @@ -72,7 +88,12 @@ void print_jmpbuf() } jmp_buf[1]; */ jmp_buf ctx = {0}; - setjmp(ctx); + if (!setjmp(ctx)) { + longjmp(ctx, 1); + } + + printf("ra=%p, sp=%p, s0=%p, s1=%p, s2=%p, s3=%p, s4=%p, s5=%p, s6=%p, s7=%p, fp=%p, gp=%p\n", + ra, sp, s0, s1, s2, s3, s4, s5, s6, s7, fp, gp); int nn_jb = sizeof(ctx[0].__jb); printf("sizeof(jmp_buf)=%d (unsigned long long [%d])\n", nn_jb, nn_jb/8); diff --git a/tools/verify/Makefile b/tools/verify/Makefile index 5b1671b..7c0107c 100644 --- a/tools/verify/Makefile +++ b/tools/verify/Makefile @@ -3,8 +3,8 @@ LDLIBS=../../obj/libst.a CFLAGS=-g -O0 -./verify: verify.c - $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o $@ $^ $(LDLIBS) +./verify: verify.c $(LDLIBS) + $(CC) $(CPPFLAGS) $(CFLAGS) $(LDFLAGS) -Wall -o verify verify.c $(LDLIBS) clean: rm -f verify diff --git a/tools/verify/verify.c b/tools/verify/verify.c index d04dbd2..19242f7 100644 --- a/tools/verify/verify.c +++ b/tools/verify/verify.c @@ -21,6 +21,7 @@ int main(int argc, char** argv) void verify_jmpbuf() { // https://en.wikipedia.org/wiki/MIPS_architecture#Calling_conventions + register void* ra asm("ra"); register void* gp asm("gp"); register void* sp asm("sp"); register void* fp asm("fp"); @@ -33,11 +34,15 @@ void verify_jmpbuf() register void* s5 asm("s5"); register void* s6 asm("s6"); register void* s7 asm("s7"); - printf("gp=%p, fp=%p, sp=%p, s0=%p, s1=%p, s2=%p, s3=%p, s4=%p, s5=%p, s6=%p, s7=%p\n", - gp, fp, sp, s0, s1, s2, s3, s4, s5, s6, s7); jmp_buf ctx = {0}; - _st_md_cxt_save(ctx); + int r0 = _st_md_cxt_save(ctx); + if (!r0) { + _st_md_cxt_restore(ctx, 1); // Restore/Jump to previous line, set r0 to 1. + } + + printf("sp=%p, ra=%p, gp=%p, s0=%p, s1=%p, s2=%p, s3=%p, s4=%p, s5=%p, s6=%p, s7=%p, fp=%p\n", + sp, ra, gp, s0, s1, s2, s3, s4, s5, s6, s7, fp); int nn_jb = sizeof(ctx[0].__jb); unsigned char* p = (unsigned char*)ctx[0].__jb;