diff --git a/src/demo/coroutine/process_pipe.c b/src/demo/coroutine/process_pipe.c index 41c9e0d2a..e6068f5d6 100644 --- a/src/demo/coroutine/process_pipe.c +++ b/src/demo/coroutine/process_pipe.c @@ -27,7 +27,7 @@ static tb_void_t tb_demo_coroutine_proc(tb_cpointer_t priv) { // init process tb_process_attr_t attr = {0}; - attr.outpipe = file[1]; + attr.out.pipe = file[1]; attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE; tb_process_ref_t process = tb_process_init(argv[1], (tb_char_t const**)(argv + 1), &attr); if (process) diff --git a/src/demo/coroutine/stackless/process_pipe.c b/src/demo/coroutine/stackless/process_pipe.c index e4df6bac2..98578d4b2 100644 --- a/src/demo/coroutine/stackless/process_pipe.c +++ b/src/demo/coroutine/stackless/process_pipe.c @@ -55,7 +55,7 @@ static tb_void_t tb_demo_lo_coroutine_func(tb_lo_coroutine_ref_t coroutine, tb_c if (tb_pipe_file_init_pair(process->file, 0)) { // init process - process->attr.outpipe = process->file[1]; + process->attr.out.pipe = process->file[1]; process->attr.outtype = TB_PROCESS_REDIRECT_TYPE_PIPE; process->proc = tb_process_init(process->argv[1], (tb_char_t const**)(process->argv + 1), &process->attr); if (process->proc) diff --git a/src/tbox/platform/arch/x64/context.S b/src/tbox/platform/arch/x64/context.S index 88cd853ad..e18bd5a66 100644 --- a/src/tbox/platform/arch/x64/context.S +++ b/src/tbox/platform/arch/x64/context.S @@ -35,6 +35,165 @@ * implementation */ +/** + * translated from x64/context.asm by Alvin + * + * - support mingw/cygwin on windows + */ +#ifdef _WIN32 + +function(tb_context_make) + + // save the stack top to rax + movq %rcx, %rax + addq %rdx, %rax + + // reserve space for first argument(from) and retval(from) item of context-function + subq $32, %rax + + // 16-align of the stack top address + andq $-16, %rax + + // reserve space for context-data on context-stack + subq $112, %rax + + // context.rbx = func + movq %r8, 80(%rax) + + // save bottom address of context stack as 'limit' + movq %rcx, 16(%rax) + + // save address of context stack limit as 'dealloction stack' + movq %rcx, 8(%rax) + + // save top address of context stack as 'base' + addq %rdx, %rcx + movq %rcx, 24(%rax) + + // init fiber-storage to zero + xorq %rcx, %rcx + movq %rcx, (%rax) + + // init context.retval(saved) = a writeable space (unused) + // it will write context (unused) and priv (unused) when jump to a new context function entry first + leaq 128(%rax), %rcx + movq %rcx, 96(%rax) + + // context.rip = the address of label __entry + leaq __entry(%rip), %rcx + movq %rcx, 104(%rax) + + // context.end = the address of label __end + leaq __end(%rip), %rcx + movq %rcx, 88(%rax) + + // return pointer to context-data + ret + +__entry: + // patch return address (__end) on stack + push %rbp + + // jump to the context function entry(rip) + jmp *%rbx + +__end: + xorq %rcx, %rcx + call _exit + hlt + +endfunc + + +function(tb_context_jump) + + // save the hidden argument: retval (from-context) + pushq %rcx + + // save registers and construct the current context + pushq %rbp + pushq %rbx + pushq %rsi + pushq %rdi + pushq %r15 + pushq %r14 + pushq %r13 + pushq %r12 + + // load TIB + movq %gs:(0x30), %r10 + + // save current stack base + movq 0x08(%r10), %rax + pushq %rax + + // save current stack limit + movq 0x10(%r10), %rax + pushq %rax + + // save current deallocation stack + movq 0x1478(%r10), %rax + pushq %rax + + // save fiber local storage + movq 0x18(%r10), %rax + pushq %rax + + // save the old context(esp) to r9 + movq %rsp, %r9 + + // switch to the new context(esp) and stack + movq %rdx, %rsp + + // load TIB + movq %gs:(0x30), %r10 + + // restore fiber local storage + popq %rax + movq %rax, 0x18(%r10) + + // restore deallocation stack + popq %rax + movq %rax, 0x1478(%r10) + + // restore stack limit + popq %rax + mov %rax, 0x10(%r10) + + // restore stack base + popq %rax + movq %rax, 0x08(%r10) + + // restore registers of the new context + popq %r12 + popq %r13 + popq %r14 + popq %r15 + popq %rdi + popq %rsi + popq %rbx + popq %rbp + + // restore retval (saved) to rax + popq %rax + + // restore the return or function address(r10) + popq %r10 + + // return from-context(retval: [rcx](context: r9, priv: r8)) from jump + // it will write context (unused) and priv (unused) when jump to a new context function entry first + movq %r9, (%rax) + movq %r8, 8(%rax) + + movq %rax, %rcx + + // jump to the return or function address(rip) + jmp *%r10 + +endfunc + +#else + /* make context (refer to boost.context) * * ------------------------------------------------------------------------------------------ @@ -165,3 +324,4 @@ function(tb_context_jump) endfunc +#endif diff --git a/src/tbox/platform/arch/x86/context.S b/src/tbox/platform/arch/x86/context.S index faba6b7f6..595bc2dbe 100644 --- a/src/tbox/platform/arch/x86/context.S +++ b/src/tbox/platform/arch/x86/context.S @@ -41,7 +41,196 @@ * implementation */ -#if defined(TB_CONFIG_OS_MACOSX) || defined(TB_CONFIG_OS_IOS) +/** + * translated from x86/context.asm by Alvin + * + * - support mingw/cygwin.. on windows + */ +#if defined(_WIN32) + +function(tb_context_make) + + // save the stack top to eax + movl 4(%esp), %eax + addl 8(%esp), %eax + movl %eax, %ecx + + // reserve space for first argument(from) and seh item of context-function + leal -20(%eax), %eax + + // 16-align of the stack top address + andl $-16, %eax + + // reserve space for context-data on context-stack + leal -40(%eax), %eax + + // save top address of context stack as 'base' + movl %ecx, 12(%eax) + + // save bottom address of context-stack as 'limit' + movl 4(%esp), %ecx + movl %ecx, 8(%eax) + + // save bottom address of context-stack as 'dealloction stack' + movl %ecx, 4(%eax) + + // set fiber-storage as zero + xorl %ecx, %ecx + movl %ecx, (%eax) + + // context.ebx = func + movl 12(%esp), %ecx + movl %ecx, 28(%eax) + + // context.eip = __entry + movl $__entry, %ecx + movl %ecx, 36(%eax) + + // context.ebp = the address of label __end + movl $__end, %ecx + movl %ecx, 32(%eax) + + // load the current seh chain from TIB + //assume fs:nothing + movl %fs:(0x0), %ecx + //assume fs:error + +__walkchain: + + // if (sehitem.prev == 0xffffffff) (last?) goto __found + movl (%ecx), %edx + incl %edx + jz __found + + // sehitem = sehitem.prev + decl %edx + xchgl %ecx, %edx + jmp __walkchain + +__found: + + // context.seh.handler = sehitem.handler + movl 4(%ecx), %ecx + movl %ecx, 60(%eax) + + // context.seh.prev = 0xffffffff + movl $0xffffffff, %ecx + movl %ecx, 56(%eax) + + // context.seh = the address of context.seh.prev + leal 56(%eax), %ecx + movl %ecx, 16(%eax) + + // return pointer to context-data + ret + +__entry: + + // pass old-context(context: eax, priv: edx) arguments to the context function + movl %eax, (%esp) + movl %edx, 4(%esp) + + // patch return address: __end + pushl %ebp + + // jump to the context function entry(eip) + jmp *%ebx + +__end: + + // exit(0) + xorl %eax, %eax + movl %eax, (%esp) + call __exit + hlt + +endfunc + + +function(tb_context_jump) + + // save registers and construct the current context + pushl %ebp + pushl %ebx + pushl %esi + pushl %edi + + // load TIB to edx + //assume fs:nothing + movl %fs:(0x18), %edx + //assume fs:error + + // load and save current seh exception list + movl (%edx), %eax + pushl %eax + + // load and save current stack base + movl 0x04(%edx), %eax + pushl %eax + + // load and save current stack limit + movl 0x08(%edx), %eax + pushl %eax + + // load and save current deallocation stack + movl 0xe0c(%edx), %eax + pushl %eax + + // load and save fiber local storage + movl 0x10(%edx), %eax + pushl %eax + + // save the old context(esp) to eax + movl %esp, %eax + + // switch to the new context(esp) and stack + movl 40(%esp), %ecx + movl %ecx, %esp + + // load TIB to edx + //assume fs:nothing + movl %fs:(0x18), %edx + //assume fs:error + + // restore fiber local storage (context.fiber) + popl %ecx + movl %ecx, 0x10(%edx) + + // restore current deallocation stack (context.dealloc) + popl %ecx + movl %ecx, 0xe0c(%edx) + + // restore current stack limit (context.limit) + popl %ecx + movl %ecx, 0x08(%edx) + + // restore current stack base (context.base) + popl %ecx + movl %ecx, 0x04(%edx) + + // restore current seh exception list (context.seh) + popl %ecx + movl %ecx, (%edx) + + // restore registers of the new context + popl %edi + popl %esi + popl %ebx + popl %ebp + + // restore the return or function address(ecx) + popl %ecx + + // return from-context(context: eax, priv: edx) from jump + // edx = [eax + 44] = [esp_jump + 44] = jump.argument(priv) + movl 44(%eax), %edx + + // jump to the return or function address(eip) + jmp *%ecx + +endfunc + +#elif defined(TB_CONFIG_OS_MACOSX) || defined(TB_CONFIG_OS_IOS) /* make context * diff --git a/src/tbox/prefix/x86/prefix.S b/src/tbox/prefix/x86/prefix.S index 4a45578bc..78453f57a 100644 --- a/src/tbox/prefix/x86/prefix.S +++ b/src/tbox/prefix/x86/prefix.S @@ -39,6 +39,14 @@ .type name, %function; \ .hidden name; \ name: + +#elif defined(_WIN64) +# define function(name) \ + .text ;\ + .align TB_CPU_BITBYTE; \ + .global name ;\ +name: + #else # define function(name) \ .text ;\