URI: 
       tlibthread: Lion context routines - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR commit 04e0a9bb81356b6713e634b4d950c524f0abf15c
   DIR parent f1825251e73ffd1c750ab14950bd1e5374991ae5
  HTML Author: Russ Cox <rsc@swtch.com>
       Date:   Thu, 13 Oct 2011 23:57:54 -0400
       
       libthread: Lion context routines
       
       Diffstat:
         A src/libthread/Darwin-x86_64-asm.s   |      44 +++++++++++++++++++++++++++++++
         A src/libthread/Darwin-x86_64-swapco… |      32 +++++++++++++++++++++++++++++++
         M src/libthread/sysofiles.sh          |       3 +++
         M src/libthread/thread.c              |       4 +++-
         M src/libthread/threadimpl.h          |       6 ++++--
         A src/libthread/x86_64-ucontext.h     |      43 ++++++++++++++++++++++++++++++
       
       6 files changed, 129 insertions(+), 3 deletions(-)
       ---
   DIR diff --git a/src/libthread/Darwin-x86_64-asm.s b/src/libthread/Darwin-x86_64-asm.s
       t@@ -0,0 +1,44 @@
       +.text
       +.align 8
       +
       +.globl        _libthread_getmcontext
       +_libthread_getmcontext:
       +        movq        $1, 0*8(%rdi)  // rax
       +        movq        %rbx, 1*8(%rdi)
       +        movq        %rcx, 2*8(%rdi)
       +        movq        %rdx, 3*8(%rdi)
       +        movq        %rsi, 4*8(%rdi)
       +        movq        %rdi, 5*8(%rdi)
       +        movq        %rbp, 6*8(%rdi)
       +        movq        %rsp, 7*8(%rdi)
       +        movq        %r8, 8*8(%rdi)
       +        movq        %r9, 9*8(%rdi)
       +        movq        %r10, 10*8(%rdi)
       +        movq        %r11, 11*8(%rdi)
       +        movq        %r12, 12*8(%rdi)
       +        movq        %r13, 13*8(%rdi)
       +        movq        %r14, 14*8(%rdi)
       +        movq        %r15, 15*8(%rdi)
       +        movq        $0, %rax
       +        ret
       +
       +.globl        _libthread_setmcontext
       +_libthread_setmcontext:
       +        movq        0*8(%rdi), %rax
       +        movq        1*8(%rdi), %rbx
       +        movq        2*8(%rdi), %rcx
       +        movq        3*8(%rdi), %rdx
       +        movq        4*8(%rdi), %rsi
       +        // %rdi later
       +        movq        6*8(%rdi), %rbp
       +        movq        7*8(%rdi), %rsp
       +        movq        8*8(%rdi), %r8
       +        movq        9*8(%rdi), %r9
       +        movq        10*8(%rdi), %r10
       +        movq        11*8(%rdi), %r11
       +        movq        12*8(%rdi), %r12
       +        movq        13*8(%rdi), %r13
       +        movq        14*8(%rdi), %r14
       +        movq        15*8(%rdi), %r15
       +        movq        5*8(%rdi), %rdi
       +        ret
   DIR diff --git a/src/libthread/Darwin-x86_64-swapcontext.c b/src/libthread/Darwin-x86_64-swapcontext.c
       t@@ -0,0 +1,32 @@
       +#include "threadimpl.h"
       +
       +void
       +makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
       +{
       +        uintptr *sp;
       +        va_list arg;
       +
       +//fprint(2, "makecontext %d\n", argc);
       +        if(argc != 2)
       +                sysfatal("libthread: makecontext misused");
       +        va_start(arg, argc);
       +        uc->mc.di = va_arg(arg, uint);
       +        uc->mc.si = va_arg(arg, uint);
       +//fprint(2, "%ux %ux\n", uc->mc.di, uc->mc.si);
       +        va_end(arg);
       +
       +        sp = (uintptr*)((char*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size);
       +        *--sp = 0;  // fn's return address
       +        *--sp = (uintptr)fn;  // return address of setcontext
       +        uc->mc.sp = (uintptr)sp;
       +}
       +
       +int
       +swapcontext(ucontext_t *oucp, ucontext_t *ucp)
       +{
       +        if(getcontext(oucp) == 0)
       +                setcontext(ucp);
       +        return 0;
       +}
       +
       +
   DIR diff --git a/src/libthread/sysofiles.sh b/src/libthread/sysofiles.sh
       t@@ -34,5 +34,8 @@ arm-Linux)
                # ARM doesn't supply them either.
                echo Linux-arm-context.o Linux-arm-swapcontext.o
                ;;
       +x86_64-Darwin)
       +        echo Darwin-x86_64-asm.o Darwin-x86_64-swapcontext.o
       +        ;;
        esac
        
   DIR diff --git a/src/libthread/thread.c b/src/libthread/thread.c
       t@@ -86,6 +86,7 @@ threadstart(uint y, uint x)
                _Thread *t;
                ulong z;
        
       +//print("threadstart\n");
                z = (ulong)x << 16;        /* hide undefined 32-bit shift from 32-bit compilers */
                z <<= 16;
                z |= y;
       t@@ -317,7 +318,7 @@ procscheduler(Proc *p)
        
                setproc(p);
                _threaddebug("scheduler enter");
       -/*        print("s %p\n", p); */
       +//print("s %p\n", p);
                lock(&p->lock);
                for(;;){
                        if((t = p->pinthread) != nil){
       t@@ -354,6 +355,7 @@ procscheduler(Proc *p)
                        p->thread = t;
                        p->nswitch++;
                        _threaddebug("run %d (%s)", t->id, t->name);
       +//print("run %p %p %p %p\n", t, *(uintptr*)(t->context.uc.mc.sp), t->context.uc.mc.di, t->context.uc.mc.si);
                        contextswitch(&p->schedcontext, &t->context);
        /*print("back in scheduler\n"); */
                        p->thread = nil;
   DIR diff --git a/src/libthread/threadimpl.h b/src/libthread/threadimpl.h
       t@@ -24,7 +24,7 @@ extern        int                swapcontext(ucontext_t*, ucontext_t*);
        extern        void                makecontext(ucontext_t*, void(*)(), int, ...);
        #endif
        
       -#if defined(__APPLE__) && !defined(__x86_64__)
       +#if defined(__APPLE__)
                /*
                 * OS X before 10.5 (Leopard) does not provide
                 * swapcontext nor makecontext, so we have to use our own.
       t@@ -40,6 +40,8 @@ extern        void                makecontext(ucontext_t*, void(*)(), int, ...);
        #        define makecontext libthread_makecontext
        #        if defined(__i386__)
        #                include "386-ucontext.h"
       +#        elif defined(__x86_64__)
       +#                include "x86_64-ucontext.h"
        #        elif defined(__power__)
        #                include "power-ucontext.h"
        #        else
       t@@ -108,7 +110,7 @@ struct Context
                 * end of the ucontext_t.  Sigh.  We put some extra
                 * scratch space here for them.
                 */
       -        uchar        buf[512];
       +        uchar        buf[1024];
        #endif
        };
        
   DIR diff --git a/src/libthread/x86_64-ucontext.h b/src/libthread/x86_64-ucontext.h
       t@@ -0,0 +1,43 @@
       +#define        setcontext(u)        libthread_setmcontext(&(u)->mc)
       +#define        getcontext(u)        libthread_getmcontext(&(u)->mc)
       +typedef struct mcontext mcontext_t;
       +typedef struct ucontext ucontext_t;
       +
       +struct mcontext
       +{
       +        uintptr        ax;
       +        uintptr        bx;
       +        uintptr cx;
       +        uintptr dx;
       +        uintptr si;
       +        uintptr di;
       +        uintptr        bp;
       +        uintptr sp;
       +        uintptr r8;
       +        uintptr r9;
       +        uintptr r10;
       +        uintptr r11;
       +        uintptr r12;
       +        uintptr r13;
       +        uintptr r14;
       +        uintptr r15;
       +/*
       +// XXX: currently do not save vector registers or floating-point state
       +*/
       +};
       +
       +struct ucontext
       +{
       +        struct {
       +                void *ss_sp;
       +                uint ss_size;
       +        } uc_stack;
       +        sigset_t uc_sigmask;
       +        mcontext_t mc;
       +};
       +
       +void makecontext(ucontext_t*, void(*)(void), int, ...);
       +int swapcontext(ucontext_t*, ucontext_t*);
       +int libthread_getmcontext(mcontext_t*);
       +void libthread_setmcontext(mcontext_t*);
       +