tOpenBSD, thanks to Tim Wiess - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit fe8c925e8ad3fe1fb95b89d26dcb828c6b31f548
 (DIR) parent 6a73f8b6c12c1618fdf02c70236155b68086f8b2
 (HTM) Author: rsc <devnull@localhost>
       Date:   Thu, 21 Jul 2005 18:29:04 +0000
       
       OpenBSD, thanks to Tim Wiess
       
       Diffstat:
         M include/libc.h                      |      10 ++++++++++
         M src/cmd/9term/OpenBSD.c             |       2 ++
         M src/cmd/auxstats/OpenBSD.c          |     216 ++++++++++++++++++++++++++++++-
         M src/lib9/_p9dir.c                   |       3 ++-
         M src/lib9/dirfwstat.c                |       2 +-
         M src/libthread/BSD.c                 |       8 ++++++++
         M src/libthread/OpenBSD-386-asm.s     |     146 ++++++++++++++++++++-----------
         M src/libthread/OpenBSD.c             |      18 ++++++++++++++++++
         M src/libthread/mkfile                |       5 ++---
       
       9 files changed, 354 insertions(+), 56 deletions(-)
       ---
 (DIR) diff --git a/include/libc.h b/include/libc.h
       t@@ -832,6 +832,16 @@ extern        int        post9pservice(int, char*);
        #        endif
        #endif
        
       +#if defined(__OpenBSD__) && !defined(NOPLAN9DEFINES)
       +#define sched_yield() \
       +        do { \
       +                struct timespec ts; \
       +                ts.tv_sec = 0; \
       +                ts.tv_nsec = 10; \
       +                nanosleep(&ts, NULL); \
       +        } while(0)
       +#endif
       +
        /* command line */
        extern char        *argv0;
        extern void __fixargv0(void);
 (DIR) diff --git a/src/cmd/9term/OpenBSD.c b/src/cmd/9term/OpenBSD.c
       t@@ -2,6 +2,8 @@
        #include "bsdpty.c"
        #undef getpts
        
       +#include <util.h>
       +
        int
        getpts(int fd[], char *slave)
        {
 (DIR) diff --git a/src/cmd/auxstats/OpenBSD.c b/src/cmd/auxstats/OpenBSD.c
       t@@ -1,10 +1,223 @@
        #include <u.h>
       +#include <kvm.h>
       +#include <nlist.h>
       +#include <sys/types.h>
       +#include <sys/param.h>
       +#include <sys/socket.h>
       +#include <sys/sysctl.h>
       +#include <sys/time.h>
       +#include <sys/dkstat.h>
       +#include <net/if.h>
       +#include <machine/apmvar.h>
       +#include <sys/ioctl.h>
       +#include <uvm/uvm_param.h>
       +#include <uvm/uvm_extern.h>
       +#include <limits.h>
        #include <libc.h>
        #include <bio.h>
        #include "dat.h"
        
       -void (*statfn[])(int) = 
       +void xapm(int);
       +void xloadavg(int);
       +void xcpu(int);
       +void xswap(int);
       +void xsysctl(int);
       +void xnet(int);
       +void xkvm(int);
       +
       +void (*statfn[])(int) =
        {
       +        xkvm,
       +        xapm,
       +        xloadavg,
       +        xcpu,
       +        xsysctl,
       +        xnet,
                0
        };
        
       +static kvm_t *kvm;
       +
       +static struct nlist nl[] = {
       +        { "_ifnet" },
       +        { "_cp_time" },
       +        { "" },
       +};
       +
       +void
       +xloadavg(int first)
       +{
       +        double l[3];
       +
       +        if(first)
       +                return;
       +
       +        if(getloadavg(l, 3) < 0)
       +                return;
       +        Bprint(&bout, "load =%d 1000\n", (int)(l[0]*1000.0));
       +}
       +
       +void
       +xapm(int first)
       +{
       +        static int fd;
       +        struct apm_power_info ai;
       +
       +        if(first){
       +                fd = open("/dev/apm", OREAD);
       +                return;
       +        }
       +
       +        if(ioctl(fd, APM_IOC_GETPOWER, &ai) < 0)
       +                return;
       +
       +        if(ai.battery_life <= 100)
       +                Bprint(&bout, "battery =%d 100\n", ai.battery_life);
       +}
       +
       +
       +void
       +kvminit(void)
       +{
       +        char buf[_POSIX2_LINE_MAX];
       +
       +        if(kvm)
       +                return;
       +        kvm = kvm_openfiles(nil, nil, nil, O_RDONLY, buf);
       +        if(kvm == nil) {
       +                fprint(2, "kvm open error\n%s", buf);
       +                return;
       +        }
       +        if(kvm_nlist(kvm, nl) < 0 || nl[0].n_type == 0){
       +                kvm = nil;
       +                return;
       +        }
       +}
       +
       +void
       +xkvm(int first)
       +{
       +        if(first)
       +                kvminit();
       +}
       +
       +int
       +kread(ulong addr, char *buf, int size)
       +{
       +        if(kvm_read(kvm, addr, buf, size) != size){
       +                memset(buf, 0, size);
       +                return -1;
       +        }
       +        return size;
       +}
       +
       +void
       +xnet(int first)
       +{
       +        ulong out, in, outb, inb, err;
       +        static ulong ifnetaddr;
       +        ulong addr;
       +        struct ifnet ifnet;
       +        struct ifnet_head ifnethead;
       +        char name[16];
       +
       +        if(first)
       +                return;
       +
       +        if(ifnetaddr == 0){
       +                ifnetaddr = nl[0].n_value;
       +                if(ifnetaddr == 0)
       +                        return;
       +        }
       +
       +        if(kread(ifnetaddr, (char*)&ifnethead, sizeof ifnethead) < 0)
       +                return;
       +
       +        out = in = outb = inb = err = 0;
       +        addr = (ulong)TAILQ_FIRST(&ifnethead);
       +        while(addr){
       +                if(kread(addr, (char*)&ifnet, sizeof ifnet) < 0
       +                || kread((ulong)ifnet.if_xname, name, 16) < 0)
       +                        return;
       +                name[15] = 0;
       +                addr = (ulong)TAILQ_NEXT(&ifnet, if_list);
       +                out += ifnet.if_opackets;
       +                in += ifnet.if_ipackets;
       +                outb += ifnet.if_obytes;
       +                inb += ifnet.if_ibytes;
       +                err += ifnet.if_oerrors+ifnet.if_ierrors;
       +        }
       +        Bprint(&bout, "etherin %lud 1000\n", in);
       +        Bprint(&bout, "etherout %lud 1000\n", out);
       +        Bprint(&bout, "etherinb %lud 1000000\n", inb);
       +        Bprint(&bout, "etheroutb %lud 1000000\n", outb);
       +        Bprint(&bout, "ethererr %lud 1000\n", err);
       +        Bprint(&bout, "ether %lud 1000\n", in+out);
       +        Bprint(&bout, "etherb %lud 1000000\n", inb+outb);
       +}
       +
       +void
       +xcpu(int first)
       +{
       +        static int stathz;
       +        ulong x[20];
       +        struct clockinfo *ci;
       +        int mib[2];
       +        int l;
       +
       +        if(first){
       +                mib[0] = CTL_KERN;
       +                mib[1] = KERN_CLOCKRATE;
       +                l = sizeof(x);
       +                sysctl(mib, 2, (char *)&x, &l, nil, 0);
       +                x[l] = 0;
       +                if (l < sizeof(ci))
       +                        stathz = 128;
       +                else{
       +                        ci = (struct clockinfo*)x;
       +                        stathz = ci->stathz;
       +                }
       +                return;
       +        }
       +
       +        mib[0] = CTL_KERN;
       +        mib[1] = KERN_CPTIME;
       +        l = sizeof(x);
       +        sysctl(mib, 2, (char *)&x, &l, nil, 0);
       +        if (l < 5*sizeof(ulong))
       +                return;
       +        x[l] = 0;
       +
       +        Bprint(&bout, "user %lud %d\n", x[CP_USER]+x[CP_NICE], stathz);
       +        Bprint(&bout, "sys %lud %d\n", x[CP_SYS], stathz);
       +        Bprint(&bout, "cpu %lud %d\n", x[CP_USER]+x[CP_NICE]+x[CP_SYS], stathz);
       +        Bprint(&bout, "idle %lud %d\n", x[CP_IDLE], stathz);
       +}
       +
       +void
       +xsysctl(int first)
       +{
       +        struct uvmexp vm;
       +        static int pgsize;
       +        int mib[2];
       +        size_t l;
       +
       +        l = sizeof(vm);
       +        mib[0] = CTL_VM;
       +        mib[1] = VM_UVMEXP;
       +        sysctl(mib, 2, &vm, &l, nil, 0);
       +        if (l < sizeof(vm))
       +                return;
       +
       +        if (first)
       +                pgsize = vm.pagesize;
       +
       +        Bprint(&bout, "mem =%lud %lud\n", vm.active*pgsize, vm.npages*pgsize);
       +        Bprint(&bout, "context %lud 1000\n", vm.swtch);
       +        Bprint(&bout, "syscall %lud 1000\n", vm.syscalls);
       +        Bprint(&bout, "intr %lud 1000\n", vm.intrs+vm.traps);
       +        Bprint(&bout, "fault %lud 1000\n", vm.faults);
       +
       +        Bprint(&bout, "fork %ud 1000\n", vm.forks);
       +        Bprint(&bout, "swap =%lud %lud\n", vm.swpginuse*pgsize, vm.swpages*pgsize);
       +}
       +\ No newline at end of file
 (DIR) diff --git a/src/lib9/_p9dir.c b/src/lib9/_p9dir.c
       t@@ -7,8 +7,9 @@
        #include <pwd.h>
        #include <grp.h>
        
       -#if defined(__FreeBSD__)
       +#if defined(__FreeBSD__) || defined(__OpenBSD__)
        #include <sys/disklabel.h>
       +#include <sys/ioctl.h>
        static int diskdev[] = {
                151,        /* aacd */
                116,        /* ad */
 (DIR) diff --git a/src/lib9/dirfwstat.c b/src/lib9/dirfwstat.c
       t@@ -4,7 +4,7 @@
        #include <sys/time.h>
        #include <sys/stat.h>
        
       -#if defined(__FreeBSD__) || defined(__APPLE__)
       +#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__OpenBSD__)
        /* do nothing -- futimes exists and is fine */
        
        #elif defined(__SunOS5_9__)
 (DIR) diff --git a/src/libthread/BSD.c b/src/libthread/BSD.c
       t@@ -90,6 +90,14 @@ _spinlock(spinlock_t *lk)
                lock((Lock*)&lk->access_lock);
        }
        
       +void
       +_spinunlock(spinlock_t *lk)
       +{
       +        unlock((Lock*)&lk->access_lock);
       +}
       +
       +
       +
        /*
         * sleep and wakeup
         */
 (DIR) diff --git a/src/libthread/OpenBSD-386-asm.s b/src/libthread/OpenBSD-386-asm.s
       t@@ -1,54 +1,99 @@
       -.globl _tas
       -_tas:
       -        movl $0xCAFEBABE, %eax
       -        movl 4(%esp), %ecx
       -        xchgl %eax, 0(%ecx)
       -        ret
       +#include "FreeBSD-386-asm.s"
        
       -.globl setmcontext
       -setmcontext:
       -        movl 4(%esp), %edx
       -        movl        8(%edx), %fs
       -        movl        12(%edx), %es
       -        movl        16(%edx), %ds
       -        movl        76(%edx), %ss
       -        movl        20(%edx), %edi
       -        movl        24(%edx), %esi
       -        movl        28(%edx), %ebp
       -        movl        %esp, %ecx                 
       -        movl        72(%edx), %esp                 
       -        pushl        60(%edx)        /* eip */         
       -        pushl        44(%edx)        /* ecx */         
       -        pushl        48(%edx)        /* eax */         
       -        movl        36(%edx), %ebx                 
       -        movl        40(%edx), %edx
       -        movl        12(%ecx), %eax                 
       -        popl        %eax                         
       -        popl        %ecx
       -        ret
       +/*
       + * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
       + * All rights reserved.
       + *
       + * Redistribution and use in source and binary forms, with or without
       + * modification, are permitted provided that the following conditions
       + * are met:
       + * 1. Redistributions of source code must retain the above copyright
       + *    notice, this list of conditions and the following disclaimer.
       + * 2. Redistributions in binary form must reproduce the above copyright
       + *    notice, this list of conditions and the following disclaimer in the
       + *    documentation and/or other materials provided with the distribution.
       + *
       + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
       + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
       + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
       + * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
       + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
       + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
       + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
       + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
       + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
       + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
       + * SUCH DAMAGE.
       + */
       +
       +#include <sys/syscall.h>
       +#include <machine/asm.h>
       +
       +ENTRY(rfork_thread)
       +        pushl   %ebp
       +        movl    %esp, %ebp
       +        pushl   %esi
       +
       +        /*
       +        * Push thread info onto the new thread's stack
       +        */
       +        movl    12(%ebp), %esi  # get stack addr
        
       -.globl getmcontext
       -getmcontext:
       -        pushl        %edx
       -        movl        8(%esp), %edx
       -        movl        %fs, 8(%edx)
       -        movl        %es, 12(%edx)
       -        movl        %ds, 16(%edx)
       -        movl        %ss, 76(%edx)
       -        movl        %edi, 20(%edx)
       -        movl        %esi, 24(%edx)
       -        movl        %ebp, 28(%edx)
       -        movl        %ebx, 36(%edx)
       -        movl        $1, 48(%edx)
       -        popl        %eax
       -        movl        %eax, 40(%edx)                 
       -        movl        %ecx, 44(%edx)
       -        movl        (%esp), %eax        /* eip */                 
       -        movl        %eax, 60(%edx)                 
       -        movl        %esp, %eax                 
       -        addl        $4, %eax        /* setmcontext will re-push the eip */         
       -        movl        %eax, 72(%edx)
       -        movl        40(%edx), %edx                 
       -        xorl        %eax, %eax                 
       +        subl    $4, %esi
       +        movl    20(%ebp), %eax  # get start argument
       +        movl    %eax, (%esi)
       +
       +        subl    $4, %esi
       +        movl    16(%ebp), %eax  # get start thread address
       +        movl    %eax, (%esi)
       +
       +        /*
       +        * Prepare and execute the thread creation syscall
       +        */
       +        pushl   8(%ebp)
       +        pushl   $0
       +        movl    $SYS_rfork, %eax
       +        int     $0x80
       +        jb      2f
       +
       +        /*
       +        * Check to see if we are in the parent or child
       +        */
       +        cmpl    $0, %edx
       +        jnz     1f
       +        addl    $8, %esp
       +        popl    %esi
       +        movl    %ebp, %esp
       +        popl    %ebp
                ret
       +        .p2align 2
       +
       +        /*
       +        * If we are in the child (new thread), then
       +        * set-up the call to the internal subroutine.  If it
       +        * returns, then call __exit.
       +        */
       +1:
       +        movl    %esi,%esp
       +        popl    %eax
       +        call    *%eax
       +        addl    $4, %esp
       +
       +        /*
       +        * Exit system call
       +        */
       +        pushl   %eax
       +        pushl   $0
       +        movl    $SYS_exit, %eax
       +        int     $0x80
        
       +        /*
       +        * Branch here if the thread creation fails:
       +        */
       +2:
       +        addl    $8, %esp
       +        popl    %esi
       +        movl    %ebp, %esp
       +        popl    %ebp
       +        PIC_PROLOGUE
       +        jmp     PIC_PLT(_C_LABEL(__cerror))
       +\ No newline at end of file
 (DIR) diff --git a/src/libthread/OpenBSD.c b/src/libthread/OpenBSD.c
       t@@ -2,3 +2,21 @@
        
        #include "BSD.c"
        
       +static spinlock_t mlock = { 0, 0, NULL, 0 };
       +
       +void
       +_thread_malloc_lock(void)
       +{
       +        _spinlock(&mlock);
       +}
       +
       +void
       +_thread_malloc_unlock(void)
       +{
       +        _spinunlock(&mlock);
       +}
       +
       +void
       +_thread_malloc_init(void)
       +{
       +}
 (DIR) diff --git a/src/libthread/mkfile b/src/libthread/mkfile
       t@@ -32,9 +32,8 @@ tspawnloop: tspawnloop.$O
        # with generic .s rule in mkcommon on case-insensitive
        # systems like Mac OS X.
        
       -OpenBSD-power-asm.$O:        OpenBSD-power-asm.S
       -        $CC $CFLAGS $stem.S
       -        
       +OpenBSD-%-asm.$O:        OpenBSD-%-asm.S
       +        $CC $CFLAGS OpenBSD-$stem-asm.S
        
        test:V: tprimes tspawn
                primes 1 10007 >p1.txt