提交 4ce84865 创建 作者: Silas Boyd-Wickizer's avatar Silas Boyd-Wickizer

Merge branch 'scale-amd64' of git+ssh://amsterdam.csail.mit.edu/home/am0/6.828/xv6 into scale-amd64

...@@ -11,7 +11,6 @@ UPROGS= \ ...@@ -11,7 +11,6 @@ UPROGS= \
mapbench \ mapbench \
maptest \ maptest \
sh \ sh \
thrtest \
halt \ halt \
time \ time \
sleep \ sleep \
......
...@@ -4,12 +4,13 @@ ...@@ -4,12 +4,13 @@
#include "mtrace.h" #include "mtrace.h"
#include "amd64.h" #include "amd64.h"
#include "uspinlock.h" #include "uspinlock.h"
#include "pthread.h"
enum { readaccess = 0 }; enum { readaccess = 0 };
enum { verbose = 0 }; enum { verbose = 0 };
enum { npg = 1 }; enum { npg = 1 };
void void*
thr(void *arg) thr(void *arg)
{ {
u64 tid = (u64)arg; u64 tid = (u64)arg;
...@@ -34,6 +35,7 @@ thr(void *arg) ...@@ -34,6 +35,7 @@ thr(void *arg)
exit(); exit();
} }
} }
return 0;
} }
int int
...@@ -50,11 +52,9 @@ main(int ac, char **av) ...@@ -50,11 +52,9 @@ main(int ac, char **av)
// fprintf(1, "mapbench[%d]: start esp %x, nthread=%d\n", getpid(), rrsp(), nthread); // fprintf(1, "mapbench[%d]: start esp %x, nthread=%d\n", getpid(), rrsp(), nthread);
for(int i = 0; i < nthread; i++) { for(u64 i = 0; i < nthread; i++) {
sbrk(8192); pthread_t tid;
void *tstack = sbrk(0); pthread_create(&tid, 0, thr, (void*) i);
// fprintf(1, "tstack %lx\n", tstack);
int tid = forkt(tstack, (void*) thr, (void *)(u64)i);
if (0) fprintf(1, "mapbench[%d]: child %d\n", getpid(), tid); if (0) fprintf(1, "mapbench[%d]: child %d\n", getpid(), tid);
} }
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
#include "mtrace.h" #include "mtrace.h"
#include "amd64.h" #include "amd64.h"
#include "uspinlock.h" #include "uspinlock.h"
#include "pthread.h"
static volatile char *p; static volatile char *p;
static struct uspinlock l; static struct uspinlock l;
...@@ -17,8 +18,8 @@ spin(void) ...@@ -17,8 +18,8 @@ spin(void)
; ;
} }
void void*
thr(void) thr(void*)
{ {
for (;;) { for (;;) {
acquire(&l); acquire(&l);
...@@ -54,8 +55,8 @@ main(void) ...@@ -54,8 +55,8 @@ main(void)
exit(); exit();
} }
sbrk(4096); pthread_t tid;
forkt(sbrk(0), (void*) thr, 0); pthread_create(&tid, 0, thr, 0);
acquire(&l); acquire(&l);
state = 1; state = 1;
......
#include "types.h"
#include "stat.h"
#include "user.h"
#include "mtrace.h"
#include "amd64.h"
#include "uspinlock.h"
static struct uspinlock l;
static volatile int tcount;
enum { nthread = 8 };
void
thr(void *arg)
{
acquire(&l);
fprintf(1, "thrtest[%d]: arg 0x%lx rsp %lx\n", getpid(), arg, rrsp());
tcount++;
release(&l);
exit();
}
int
main(void)
{
acquire(&l);
fprintf(1, "thrtest[%d]: start esp %x\n", getpid(), rrsp());
for(int i = 0; i < nthread; i++) {
sbrk(8192);
void *tstack = sbrk(0);
int tid = forkt(tstack, (void*) thr, (void*)(u64)(0xc0ffee00|i));
fprintf(1, "thrtest[%d]: child %d\n", getpid(), tid);
}
for(;;){
int lastc = tcount;
fprintf(1, "thrtest[%d]: tcount=%d\n", getpid(), lastc);
release(&l);
if(lastc==nthread)
break;
while(tcount==lastc)
__asm __volatile("");
acquire(&l);
}
release(&l);
fprintf(1, "thrtest[%d]: done\n", getpid());
for(int i = 0; i < nthread; i++)
wait();
exit();
}
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "fcntl.h" #include "fcntl.h"
#include "syscall.h" #include "syscall.h"
#include "traps.h" #include "traps.h"
#include "pthread.h"
char buf[2048]; char buf[2048];
char name[3]; char name[3];
...@@ -1600,6 +1601,7 @@ preads(void) ...@@ -1600,6 +1601,7 @@ preads(void)
void void
tls_test(void) tls_test(void)
{ {
printf("tls_test\n");
u64 buf[128]; u64 buf[128];
for (int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++) for (int i = 0; i < sizeof(buf) / sizeof(buf[0]); i++)
...@@ -1626,6 +1628,49 @@ tls_test(void) ...@@ -1626,6 +1628,49 @@ tls_test(void)
fprintf(1, "tls_test ok\n"); fprintf(1, "tls_test ok\n");
} }
static pthread_key_t tkey;
static pthread_barrier_t bar0, bar1;
enum { nthread = 8 };
static void*
thr(void *arg)
{
pthread_setspecific(tkey, arg);
pthread_barrier_wait(&bar0);
u64 x = (u64) arg;
if ((x >> 8) != 0xc0ffee)
fprintf(2, "thr: x 0x%lx\n", x);
if (arg != pthread_getspecific(tkey))
fprintf(2, "thr: arg %p getspec %p\n", arg, pthread_getspecific(tkey));
pthread_barrier_wait(&bar1);
return 0;
}
void
thrtest(void)
{
printf("thrtest\n");
pthread_key_create(&tkey, 0);
pthread_barrier_init(&bar0, 0, nthread);
pthread_barrier_init(&bar1, 0, nthread+1);
for(int i = 0; i < nthread; i++) {
pthread_t tid;
pthread_create(&tid, 0, &thr, (void*) (0xc0ffee00ULL | i));
}
pthread_barrier_wait(&bar1);
for(int i = 0; i < nthread; i++)
wait();
printf("thrtest ok\n");
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
...@@ -1674,6 +1719,7 @@ main(int argc, char *argv[]) ...@@ -1674,6 +1719,7 @@ main(int argc, char *argv[])
exectest(); exectest();
tls_test(); tls_test();
thrtest();
exit(); exit();
} }
...@@ -133,6 +133,20 @@ ltr(u16 sel) ...@@ -133,6 +133,20 @@ ltr(u16 sel)
} }
static inline void static inline void
writefs(u16 v)
{
__asm volatile("movw %0, %%fs" : : "r" (v));
}
static inline u16
readfs(void)
{
u16 v;
__asm volatile("movw %%fs, %0" : "=r" (v));
return v;
}
static inline void
writegs(u16 v) writegs(u16 v)
{ {
__asm volatile("movw %0, %%gs" : : "r" (v)); __asm volatile("movw %0, %%gs" : : "r" (v));
......
#pragma once
/*
* Our minimal version of pthreads
*/
#include "atomic.hh"
typedef int pthread_t;
typedef int pthread_attr_t;
typedef int pthread_key_t;
typedef int pthread_barrierattr_t;
typedef std::atomic<unsigned> pthread_barrier_t;
int pthread_create(pthread_t* tid, const pthread_attr_t* attr,
void* (*start)(void*), void* arg);
pthread_t pthread_self(void);
int pthread_key_create(pthread_key_t* key, void (*destructor)(void*));
void* pthread_getspecific(pthread_key_t key);
int pthread_setspecific(pthread_key_t key, void* value);
int pthread_barrier_init(pthread_barrier_t *b,
const pthread_barrierattr_t *attr,
unsigned count);
int pthread_barrier_wait(pthread_barrier_t *b);
...@@ -50,6 +50,7 @@ int atoi(const char*); ...@@ -50,6 +50,7 @@ int atoi(const char*);
// uthread.S // uthread.S
int forkt(void *sp, void *pc, void *arg); int forkt(void *sp, void *pc, void *arg);
void forkt_setup(u64 pid);
// printf.c // printf.c
void printf(const char*, ...); void printf(const char*, ...);
......
...@@ -127,6 +127,8 @@ switchvm(struct proc *p) ...@@ -127,6 +127,8 @@ switchvm(struct proc *p)
lcr3(v2p(p->vmap->pml4)); // switch to new address space lcr3(v2p(p->vmap->pml4)); // switch to new address space
else else
switchkvm(); switchkvm();
writefs(UDSEG);
writemsr(MSR_FS_BASE, p->user_fs_); writemsr(MSR_FS_BASE, p->user_fs_);
popcli(); popcli();
......
ULIB = ulib.o usys.o printf.o umalloc.o uthread.o fmt.o stream.o ipc.o ULIB = ulib.o usys.o printf.o umalloc.o uthread.o fmt.o stream.o ipc.o \
threads.o
ULIB := $(addprefix $(O)/lib/, $(ULIB)) ULIB := $(addprefix $(O)/lib/, $(ULIB))
.PRECIOUS: $(O)/lib/%.o .PRECIOUS: $(O)/lib/%.o
......
#include "types.h"
#include "pthread.h"
#include "user.h"
#include "atomic.hh"
enum { stack_size = 8192 };
static std::atomic<int> nextkey;
struct tlsdata {
void* buf[128];
};
void
forkt_setup(u64 pid)
{
tlsdata* t = (tlsdata*) sbrk(sizeof(*t));
setfs((u64) t);
}
int
pthread_create(pthread_t* tid, const pthread_attr_t* attr,
void* (*start)(void*), void* arg)
{
char* base = (char*) sbrk(stack_size);
int t = forkt(base + stack_size, (void*) start, arg);
if (t < 0)
return t;
*tid = t;
return 0;
}
pthread_t
pthread_self()
{
return getpid();
}
int
pthread_key_create(pthread_key_t *key, void (*destructor)(void*))
{
// Ignore the destructor for now.
*key = nextkey++;
return 0;
}
void*
pthread_getspecific(pthread_key_t key)
{
u64 v;
__asm volatile("movq %%fs:(%1), %0" : "=r" (v) : "r" ((u64) key * 8));
return (void*) v;
}
int
pthread_setspecific(pthread_key_t key, void* value)
{
__asm volatile("movq %0, %%fs:(%1)" : : "r" (value), "r" ((u64) key * 8));
return 0;
}
int
pthread_barrier_init(pthread_barrier_t *b,
const pthread_barrierattr_t *attr, unsigned count)
{
b->store(count);
return 0;
}
int
pthread_barrier_wait(pthread_barrier_t *b)
{
(*b)--;
while (*b != 0)
; // spin
return 0;
}
...@@ -8,20 +8,23 @@ forkt: ...@@ -8,20 +8,23 @@ forkt:
pushq %r12 pushq %r12
andq $(~0xf), %rdi # new stack ptr amd64 ABI alignment andq $(~0xf), %rdi # new stack ptr amd64 ABI alignment
movq %rdi, %r12 movq %rdi, %r12
movq %rdx, -16(%r12) # arg subq $0x10, %r12
movq %rsi, -8(%r12) # function ptr movq %rdx, 0x00(%r12) # arg
movq %rsi, 0x08(%r12) # function ptr
movq $1, %rdi # flag for sys_fork movq $1, %rdi # flag for sys_fork
movq $SYS_fork, %rax movq $SYS_fork, %rax
int $T_SYSCALL syscall
cmpq $0, %rax # pid/tid cmpq $0, %rax # pid/tid
jne 1f jne 1f
# child # child
movq -8(%r12), %rax
movq -16(%r12), %rdi
movq %r12, %rsp movq %r12, %rsp
movq %rax, %rdi
call forkt_setup
popq %rdi
popq %rax
call *%rax call *%rax
call exit call exit
1: # parent 1: # parent
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论