recent changes

This commit is contained in:
Russ Cox 2011-01-03 15:08:59 -05:00
parent 42f058999e
commit b75fdf3424
9 changed files with 462 additions and 15 deletions

View File

@ -48,9 +48,6 @@ testdelay1: testdelay1.o $(LIB)
clean: clean:
rm -f *.o primes tcpproxy testdelay testdelay1 httpload $(LIB) rm -f *.o primes tcpproxy testdelay testdelay1 httpload $(LIB)
tgz:
tar czvf libtask.tgz COPYRIGHT README *.[chS] Makefile makesun
install: $(LIB) install: $(LIB)
cp $(LIB) /usr/local/lib cp $(LIB) /usr/local/lib
cp task.h /usr/local/include cp task.h /usr/local/include

57
Makefile.sun Normal file
View File

@ -0,0 +1,57 @@
LIB=libtask.a
OFILES=\
channel.o\
context.o\
fd.o\
net.o\
print.o\
qlock.o\
rendez.o\
task.o\
all: $(LIB) primes tcpproxy testdelay
$(OFILES): taskimpl.h task.h 386-ucontext.h power-ucontext.h
AS=as
CC=cc
CFLAGS=-c -I. -g
%.o: %.S
$(AS) $*.S
%.o: %.c
$(CC) $(CFLAGS) $*.c
$(LIB): $(OFILES)
ar rvc $(LIB) $(OFILES)
primes: primes.o $(LIB)
$(CC) -o primes primes.o $(LIB)
tcpproxy: tcpproxy.o $(LIB)
$(CC) -o tcpproxy tcpproxy.o $(LIB)
httpload: httpload.o $(LIB)
$(CC) -o httpload httpload.o $(LIB)
stdlogger: stdlogger.o $(LIB)
$(CC) -o stdlogger stdlogger.o $(LIB)
testdelay: testdelay.o $(LIB)
$(CC) -o testdelay testdelay.o $(LIB)
clock: clock.o $(LIB)
$(CC) -o clock clock.o $(LIB)
clean:
rm *.o tcpproxy primes $(LIB)
tgz:
tar czvf libtask.tgz COPYRIGHT README *.[chS] Makefile
install: $(LIB)
cp $(LIB) /usr/local/lib
cp task.h /usr/local/include

6
README
View File

@ -1,6 +1,6 @@
Libtask is a simple coroutine library. It runs on Linux (ARM and x86), Libtask is a simple coroutine library. It runs on Linux (ARM, MIPS, and x86),
FreeBSD (x86), OS X (PowerPC and x86), and SunOS Solaris (Sparc), and is FreeBSD (x86), OS X (PowerPC x86, and x86-64), and SunOS Solaris (Sparc),
easy to port to other systems. and is easy to port to other systems.
Libtask gives the programmer the illusion of threads, but Libtask gives the programmer the illusion of threads, but
the operating system sees only a single kernel thread. the operating system sees only a single kernel thread.

137
amd64-ucontext.h Normal file
View File

@ -0,0 +1,137 @@
#define setcontext(u) setmcontext(&(u)->uc_mcontext)
#define getcontext(u) getmcontext(&(u)->uc_mcontext)
typedef struct mcontext mcontext_t;
typedef struct ucontext ucontext_t;
extern int swapcontext(ucontext_t*, const ucontext_t*);
extern void makecontext(ucontext_t*, void(*)(), int, ...);
extern int getmcontext(mcontext_t*);
extern void setmcontext(const mcontext_t*);
/*-
* Copyright (c) 1999 Marcel Moolenaar
* 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
* in this position and unchanged.
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
*
* $FreeBSD: src/sys/sys/ucontext.h,v 1.4 1999/10/11 20:33:17 luoqi Exp $
*/
/* #include <machine/ucontext.h> */
/*-
* Copyright (c) 1999 Marcel Moolenaar
* 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
* in this position and unchanged.
* 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.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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.
*
* $FreeBSD: src/sys/i386/include/ucontext.h,v 1.4 1999/10/11 20:33:09 luoqi Exp $
*/
struct mcontext {
/*
* The first 20 fields must match the definition of
* sigcontext. So that we can support sigcontext
* and ucontext_t at the same time.
*/
long mc_onstack; /* XXX - sigcontext compat. */
long mc_rdi; /* machine state (struct trapframe) */
long mc_rsi;
long mc_rdx;
long mc_rcx;
long mc_r8;
long mc_r9;
long mc_rax;
long mc_rbx;
long mc_rbp;
long mc_r10;
long mc_r11;
long mc_r12;
long mc_r13;
long mc_r14;
long mc_r15;
long mc_trapno;
long mc_addr;
long mc_flags;
long mc_err;
long mc_rip;
long mc_cs;
long mc_rflags;
long mc_rsp;
long mc_ss;
long mc_len; /* sizeof(mcontext_t) */
#define _MC_FPFMT_NODEV 0x10000 /* device not present or configured */
#define _MC_FPFMT_XMM 0x10002
long mc_fpformat;
#define _MC_FPOWNED_NONE 0x20000 /* FP state not used */
#define _MC_FPOWNED_FPU 0x20001 /* FP state came from FPU */
#define _MC_FPOWNED_PCB 0x20002 /* FP state came from PCB */
long mc_ownedfp;
/*
* See <machine/fpu.h> for the internals of mc_fpstate[].
*/
long mc_fpstate[64];
long mc_spare[8];
};
struct ucontext {
/*
* Keep the order of the first two fields. Also,
* keep them the first two fields in the structure.
* This way we can have a union with struct
* sigcontext and ucontext_t. This allows us to
* support them both at the same time.
* note: the union is not defined, though.
*/
sigset_t uc_sigmask;
mcontext_t uc_mcontext;
struct __ucontext *uc_link;
stack_t uc_stack;
int __spare__[8];
};

128
asm.S
View File

@ -12,17 +12,21 @@
#define GET getmcontext #define GET getmcontext
#endif #endif
#if defined(__APPLE__) && defined(__i386__) #if defined(__APPLE__)
#if defined(__i386__)
#define NEEDX86CONTEXT 1 #define NEEDX86CONTEXT 1
#define SET _setmcontext #define SET _setmcontext
#define GET _getmcontext #define GET _getmcontext
#endif #elif defined(__x86_64__)
#define NEEDAMD64CONTEXT 1
#if defined(__APPLE__) && !defined(__i386__) #define SET _setmcontext
#define GET _getmcontext
#else
#define NEEDPOWERCONTEXT 1 #define NEEDPOWERCONTEXT 1
#define SET __setmcontext #define SET __setmcontext
#define GET __getmcontext #define GET __getmcontext
#endif #endif
#endif
#if defined(__linux__) && defined(__arm__) #if defined(__linux__) && defined(__arm__)
#define NEEDARMCONTEXT 1 #define NEEDARMCONTEXT 1
@ -30,6 +34,12 @@
#define GET getmcontext #define GET getmcontext
#endif #endif
#if defined(__linux__) && defined(__mips__)
#define NEEDMIPSCONTEXT 1
#define SET setmcontext
#define GET getmcontext
#endif
#ifdef NEEDX86CONTEXT #ifdef NEEDX86CONTEXT
.globl SET .globl SET
SET: SET:
@ -77,6 +87,56 @@ GET:
ret ret
#endif #endif
#ifdef NEEDAMD64CONTEXT
.globl SET
SET:
movq 16(%rdi), %rsi
movq 24(%rdi), %rdx
movq 32(%rdi), %rcx
movq 40(%rdi), %r8
movq 48(%rdi), %r9
movq 56(%rdi), %rax
movq 64(%rdi), %rbx
movq 72(%rdi), %rbp
movq 80(%rdi), %r10
movq 88(%rdi), %r11
movq 96(%rdi), %r12
movq 104(%rdi), %r13
movq 112(%rdi), %r14
movq 120(%rdi), %r15
movq 184(%rdi), %rsp
pushq 160(%rdi) /* new %eip */
movq 8(%rdi), %rdi
ret
.globl GET
GET:
movq %rdi, 8(%rdi)
movq %rsi, 16(%rdi)
movq %rdx, 24(%rdi)
movq %rcx, 32(%rdi)
movq %r8, 40(%rdi)
movq %r9, 48(%rdi)
movq $1, 56(%rdi) /* %rax */
movq %rbx, 64(%rdi)
movq %rbp, 72(%rdi)
movq %r10, 80(%rdi)
movq %r11, 88(%rdi)
movq %r12, 96(%rdi)
movq %r13, 104(%rdi)
movq %r14, 112(%rdi)
movq %r15, 120(%rdi)
movq (%rsp), %rcx /* %rip */
movq %rcx, 160(%rdi)
leaq 8(%rsp), %rcx /* %rsp */
movq %rcx, 184(%rdi)
movq 32(%rdi), %rcx /* restore %rcx */
movq $0, %rax
ret
#endif
#ifdef NEEDPOWERCONTEXT #ifdef NEEDPOWERCONTEXT
/* get FPR and VR use flags with sc 0x7FF3 */ /* get FPR and VR use flags with sc 0x7FF3 */
/* get vsave with mfspr reg, 256 */ /* get vsave with mfspr reg, 256 */
@ -204,3 +264,63 @@ SET:
ldr r0, [r0] ldr r0, [r0]
mov pc, lr mov pc, lr
#endif #endif
#ifdef NEEDMIPSCONTEXT
.globl GET
GET:
sw $4, 24($4)
sw $5, 28($4)
sw $6, 32($4)
sw $7, 36($4)
sw $16, 72($4)
sw $17, 76($4)
sw $18, 80($4)
sw $19, 84($4)
sw $20, 88($4)
sw $21, 92($4)
sw $22, 96($4)
sw $23, 100($4)
sw $28, 120($4) /* gp */
sw $29, 124($4) /* sp */
sw $30, 128($4) /* fp */
sw $31, 132($4) /* ra */
xor $2, $2, $2
j $31
nop
.globl SET
SET:
lw $16, 72($4)
lw $17, 76($4)
lw $18, 80($4)
lw $19, 84($4)
lw $20, 88($4)
lw $21, 92($4)
lw $22, 96($4)
lw $23, 100($4)
lw $28, 120($4) /* gp */
lw $29, 124($4) /* sp */
lw $30, 128($4) /* fp */
/*
* If we set $31 directly and j $31,
* we would loose the outer return address.
* Use a temporary register, then.
*/
lw $8, 132($4) /* ra */
/* bug: not setting the pc causes a bus error */
lw $25, 132($4) /* pc */
lw $5, 28($4)
lw $6, 32($4)
lw $7, 36($4)
lw $4, 24($4)
j $8
nop
#endif

View File

@ -2,15 +2,18 @@
#include "taskimpl.h" #include "taskimpl.h"
#if defined(__APPLE__) && defined(__i386__) #if defined(__APPLE__)
#if defined(__i386__)
#define NEEDX86MAKECONTEXT #define NEEDX86MAKECONTEXT
#define NEEDSWAPCONTEXT #define NEEDSWAPCONTEXT
#endif #elif defined(__x86_64__)
#define NEEDAMD64MAKECONTEXT
#if defined(__APPLE__) && !defined(__i386__) #define NEEDSWAPCONTEXT
#else
#define NEEDPOWERMAKECONTEXT #define NEEDPOWERMAKECONTEXT
#define NEEDSWAPCONTEXT #define NEEDSWAPCONTEXT
#endif #endif
#endif
#if defined(__FreeBSD__) && defined(__i386__) && __FreeBSD__ < 5 #if defined(__FreeBSD__) && defined(__i386__) && __FreeBSD__ < 5
#define NEEDX86MAKECONTEXT #define NEEDX86MAKECONTEXT
@ -27,6 +30,11 @@
#define NEEDARMMAKECONTEXT #define NEEDARMMAKECONTEXT
#endif #endif
#if defined(__linux__) && defined(__mips__)
#define NEEDSWAPCONTEXT
#define NEEDMIPSMAKECONTEXT
#endif
#ifdef NEEDPOWERMAKECONTEXT #ifdef NEEDPOWERMAKECONTEXT
void void
makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...) makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
@ -61,6 +69,29 @@ makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
} }
#endif #endif
#ifdef NEEDAMD64MAKECONTEXT
void
makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
{
long *sp;
va_list va;
memset(&ucp->uc_mcontext, 0, sizeof ucp->uc_mcontext);
if(argc != 2)
*(int*)0 = 0;
va_start(va, argc);
ucp->uc_mcontext.mc_rdi = va_arg(va, int);
ucp->uc_mcontext.mc_rsi = va_arg(va, int);
va_end(va);
sp = (long*)ucp->uc_stack.ss_sp+ucp->uc_stack.ss_size/sizeof(long);
sp -= argc;
sp = (void*)((uintptr_t)sp - (uintptr_t)sp%16); /* 16-align for OS X */
*--sp = 0; /* return address */
ucp->uc_mcontext.mc_rip = (long)func;
ucp->uc_mcontext.mc_rsp = (long)sp;
}
#endif
#ifdef NEEDARMMAKECONTEXT #ifdef NEEDARMMAKECONTEXT
void void
makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...) makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
@ -78,6 +109,23 @@ makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
} }
#endif #endif
#ifdef NEEDMIPSMAKECONTEXT
void
makecontext(ucontext_t *uc, void (*fn)(void), int argc, ...)
{
int i, *sp;
va_list arg;
va_start(arg, argc);
sp = (int*)uc->uc_stack.ss_sp+uc->uc_stack.ss_size/4;
for(i=0; i<4 && i<argc; i++)
uc->uc_mcontext.mc_regs[i+4] = va_arg(arg, int);
va_end(arg);
uc->uc_mcontext.mc_regs[29] = (int)sp;
uc->uc_mcontext.mc_regs[31] = (int)fn;
}
#endif
#ifdef NEEDSWAPCONTEXT #ifdef NEEDSWAPCONTEXT
int int
swapcontext(ucontext_t *oucp, const ucontext_t *ucp) swapcontext(ucontext_t *oucp, const ucontext_t *ucp)

77
mips-ucontext.h Normal file
View File

@ -0,0 +1,77 @@
typedef struct mcontext mcontext_t;
typedef struct ucontext ucontext_t;
extern int swapcontext(ucontext_t*, const ucontext_t*);
extern void makecontext(ucontext_t*, void(*)(), int, ...);
/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Ralph Campbell.
*
* 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.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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.
*
* @(#)ucontext.h 8.1 (Berkeley) 6/10/93
* JNPR: ucontext.h,v 1.2 2007/08/09 11:23:32 katta
* $FreeBSD: src/sys/mips/include/ucontext.h,v 1.2 2010/01/10 19:50:24 imp Exp $
*/
struct mcontext {
/*
* These fields must match the corresponding fields in struct
* sigcontext which follow 'sc_mask'. That way we can support
* struct sigcontext and ucontext_t at the same time.
*/
int mc_onstack; /* sigstack state to restore */
int mc_pc; /* pc at time of signal */
int mc_regs[32]; /* processor regs 0 to 31 */
int sr; /* status register */
int mullo, mulhi; /* mullo and mulhi registers... */
int mc_fpused; /* fp has been used */
int mc_fpregs[33]; /* fp regs 0 to 31 and csr */
int mc_fpc_eir; /* fp exception instruction reg */
void *mc_tls; /* pointer to TLS area */
int __spare__[8]; /* XXX reserved */
};
struct ucontext {
/*
* Keep the order of the first two fields. Also,
* keep them the first two fields in the structure.
* This way we can have a union with struct
* sigcontext and ucontext_t. This allows us to
* support them both at the same time.
* note: the union is not defined, though.
*/
sigset_t uc_sigmask;
mcontext_t uc_mcontext;
struct __ucontext *uc_link;
stack_t uc_stack;
int uc_flags;
int __spare__[4];
};

1
task.c
View File

@ -123,6 +123,7 @@ taskalloc(void (*fn)(void*), void *arg, uint stack)
* function that takes some number of word-sized variables, * function that takes some number of word-sized variables,
* and on 64-bit machines pointers are bigger than words. * and on 64-bit machines pointers are bigger than words.
*/ */
//print("make %p\n", t);
z = (ulong)t; z = (ulong)t;
y = z; y = z;
z >>= 16; /* hide undefined 32-bit shift from 32-bit compilers */ z >>= 16; /* hide undefined 32-bit shift from 32-bit compilers */

View File

@ -11,7 +11,7 @@
#define USE_UCONTEXT 1 #define USE_UCONTEXT 1
#if defined(__OpenBSD__) #if defined(__OpenBSD__) || defined(__mips__)
#undef USE_UCONTEXT #undef USE_UCONTEXT
#define USE_UCONTEXT 0 #define USE_UCONTEXT 0
#endif #endif
@ -95,6 +95,8 @@ extern void makecontext(ucontext_t*, void(*)(), int, ...);
# define ucontext_t libthread_ucontext_t # define ucontext_t libthread_ucontext_t
# if defined(__i386__) # if defined(__i386__)
# include "386-ucontext.h" # include "386-ucontext.h"
# elif defined(__x86_64__)
# include "amd64-ucontext.h"
# else # else
# include "power-ucontext.h" # include "power-ucontext.h"
# endif # endif
@ -128,6 +130,14 @@ void setmcontext(const mcontext_t*);
#define getcontext(u) getmcontext(&(u)->uc_mcontext) #define getcontext(u) getmcontext(&(u)->uc_mcontext)
#endif #endif
#if defined(__mips__)
#include "mips-ucontext.h"
int getmcontext(mcontext_t*);
void setmcontext(const mcontext_t*);
#define setcontext(u) setmcontext(&(u)->uc_mcontext)
#define getcontext(u) getmcontext(&(u)->uc_mcontext)
#endif
typedef struct Context Context; typedef struct Context Context;
enum enum