Skip to content

Commit

Permalink
finish lab thread
Browse files Browse the repository at this point in the history
  • Loading branch information
ejunjsh committed Jul 29, 2021
1 parent a3b32ea commit a765902
Show file tree
Hide file tree
Showing 9 changed files with 576 additions and 11 deletions.
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,7 @@ kernel/kernel
user/usys.S
.gdbinit
*.pyc
xv6.out*
xv6.out*
ph
*.dSYM
barrier
21 changes: 19 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -156,21 +156,38 @@ UPROGS=\
$U/_bttest\
$U/_lazytests\
$U/_cowtest\
$U/_uthread\

$U/uthread_switch.o : $U/uthread_switch.S
$(CC) $(CFLAGS) -c -o $U/uthread_switch.o $U/uthread_switch.S

$U/_uthread: $U/uthread.o $U/uthread_switch.o $(ULIB)
$(LD) $(LDFLAGS) -N -e main -Ttext 0 -o $U/_uthread $U/uthread.o $U/uthread_switch.o $(ULIB)
$(OBJDUMP) -S $U/_uthread > $U/uthread.asm

ph: notxv6/ph.c
gcc -o ph -g -O2 notxv6/ph.c -pthread

barrier: notxv6/barrier.c
gcc -o barrier -g -O2 notxv6/barrier.c -pthread

fs.img: mkfs/mkfs README $(UPROGS) user/xargstest.sh
mkfs/mkfs fs.img README $(UPROGS) user/xargstest.sh

-include kernel/*.d user/*.d

clean:
rm -f *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
rm -rf *.tex *.dvi *.idx *.aux *.log *.ind *.ilg \
*/*.o */*.d */*.asm */*.sym \
$U/initcode $U/initcode.out $K/kernel fs.img \
mkfs/mkfs .gdbinit \
$U/usys.S \
$(UPROGS) \
xv6.out* \
gradelib.pyc
gradelib.pyc \
ph \
barrier \
*.dSYM \

# 尝试去生成一个唯一的GDB端口
GDBPORT = $(shell expr `id -u` % 5000 + 25000)
Expand Down
31 changes: 23 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,15 @@

$ usertests # 进入系统后执行

## lab
## Lab

这个lab跟原来的不同,是每个lab是基于上个lab基础继续做的,所以这样最后代码就基本是所有lab的集合,很有挑战哈

每个lab跑下面每个测试之前最好清空下文件
每个lab跑测试之前最好清空下文件

make clean

### [Lab Utilities](https://pdos.csail.mit.edu/6.828/2020/labs/util.html)
### [Utilities(工具)](https://pdos.csail.mit.edu/6.828/2020/labs/util.html)

$ ./grade-lab-util
make: `kernel/kernel' is up to date.
Expand All @@ -73,7 +73,7 @@
Score: 100/100


### [Lab System calls](https://pdos.csail.mit.edu/6.828/2020/labs/syscall.html)
### [System calls(系统调用)](https://pdos.csail.mit.edu/6.828/2020/labs/syscall.html)

$ ./grade-lab-syscall
make: `kernel/kernel' is up to date.
Expand All @@ -86,7 +86,7 @@
time: OK
Score: 35/35

### [Lab Page tables](https://pdos.csail.mit.edu/6.828/2020/labs/pgtbl.html)
### [Page tables(页表)](https://pdos.csail.mit.edu/6.828/2020/labs/pgtbl.html)

$ LAB=pgtbl ./grade-lab-pgtbl
make: `kernel/kernel' is up to date.
Expand All @@ -110,7 +110,7 @@
time: OK
Score: 66/66

### [Lab Traps](https://pdos.csail.mit.edu/6.828/2020/labs/traps.html)
### [Traps(陷阱)](https://pdos.csail.mit.edu/6.828/2020/labs/traps.html)

$ LAB=traps ./grade-lab-traps
make: `kernel/kernel' is up to date.
Expand All @@ -129,7 +129,7 @@
time: OK
Score: 85/85

### [Lazy page allocation](https://pdos.csail.mit.edu/6.828/2020/labs/lazy.html)
### [Lazy page allocation(页的延迟分配)](https://pdos.csail.mit.edu/6.828/2020/labs/lazy.html)

$ ./grade-lab-lazy
make: `kernel/kernel' is up to date.
Expand Down Expand Up @@ -253,7 +253,7 @@
time: OK
Score: 119/119

### [Lab Copy-on-Write Fork for xv6](https://pdos.csail.mit.edu/6.828/2020/labs/cow.html)
### [Copy-on-Write Fork(fork的写时复制)](https://pdos.csail.mit.edu/6.828/2020/labs/cow.html)

$ ./grade-lab-cow
== Test running cowtest == (11.4s)
Expand All @@ -274,6 +274,21 @@
time: OK
Score: 110/110

### [Multithreading(多线程)](https://pdos.csail.mit.edu/6.828/2020/labs/thread.html)

$ ./grade-lab-thread
== Test uthread == uthread: OK (7.0s)
== Test answers-thread.txt == answers-thread.txt: OK
== Test ph_safe == gcc -o ph -g -O2 notxv6/ph.c -pthread
ph_safe: OK (8.9s)
== Test ph_fast == make: `ph' is up to date.
ph_fast: OK (18.1s)
== Test barrier == gcc -o barrier -g -O2 notxv6/barrier.c -pthread
barrier: OK (2.3s)
== Test time ==
time: OK
Score: 60/60

## 来自书的截图

![](https://github.com/ejunjsh/myxv6/raw/main/res/1.1.png)
Expand Down
1 change: 1 addition & 0 deletions answers-thread.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello world
70 changes: 70 additions & 0 deletions grade-lab-thread
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env python3

import re
import subprocess
from gradelib import *


r = Runner(save("xv6.out"))

@test(20, "uthread")
def test_uthread():
r.run_qemu(shell_script([
'uthread'
]))
expected = ['thread_a started', 'thread_b started', 'thread_c started']
expected.extend(['thread_%s %d' % (tid, n) for n in range(100) for tid in ('c', 'a', 'b')])
expected.extend(['thread_c: exit after 100', 'thread_a: exit after 100', 'thread_b: exit after 100'])
expected.append('thread_schedule: no runnable threads')
if not re.findall('\n'.join(expected), r.qemu.output, re.M):
raise AssertionError('Output does not match expected output')

@test(5, "answers-thread.txt")
def test_answers():
# just a simple sanity check, will be graded manually
check_answers("answers-thread.txt")

# test the first ph task: add locks to eliminate the missing keys.
@test(10, "ph_safe")
def test_ph_safe():
subprocess.run(['make', 'ph'], check=True)
result = subprocess.run(['./ph', '2'], stdout=subprocess.PIPE, check=True)
out = result.stdout.decode("utf-8")
matches = re.findall(r'^\d+: (\d+) keys missing$', out, re.MULTILINE)
assert_equal(len(matches), 2)
assert_equal(int(matches[0]), 0)
assert_equal(int(matches[1]), 0)

# test the second ph task: locking that allows put() parallelism
@test(10, "ph_fast")
def test_ph_fast():
subprocess.run(['make', 'ph'], check=True)
result = subprocess.run(['./ph', '2'], stdout=subprocess.PIPE, check=True)
out = result.stdout.decode("utf-8")
rate2 = re.findall(r' (\d+) puts.second$', out, re.MULTILINE)
assert_equal(len(rate2), 1)
result = subprocess.run(['./ph', '1'], stdout=subprocess.PIPE)
out = result.stdout.decode("utf-8")
rate1 = re.findall(r' (\d+) puts.second$', out, re.MULTILINE)
assert_equal(len(rate1), 1)
rate1 = float(rate1[0])
rate2 = float(rate2[0])
# demand that 2 threads yield at least 1.25x the
# throughput of a single thread.
if rate2 < 1.25 * rate1:
raise AssertionError('Parallel put() speedup is less than 1.25x')

@test(14, "barrier")
def test_barrier():
subprocess.run(['make', 'barrier'])
result = subprocess.run(['./barrier', '2'], stdout=subprocess.PIPE)
out = result.stdout.decode("utf-8")
if not re.match(r'^OK; passed$', out):
raise AssertionError('Barrier failed')

@test(1, "time")
def test_time():
check_time()

run_tests()

84 changes: 84 additions & 0 deletions notxv6/barrier.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include <pthread.h>

static int nthread = 1;
static int round = 0;

struct barrier {
pthread_mutex_t barrier_mutex;
pthread_cond_t barrier_cond;
int nthread; // Number of threads that have reached this round of the barrier
int round; // Barrier round
} bstate;

static void
barrier_init(void)
{
assert(pthread_mutex_init(&bstate.barrier_mutex, NULL) == 0);
assert(pthread_cond_init(&bstate.barrier_cond, NULL) == 0);
bstate.nthread = 0;
}

static void
barrier()
{
// YOUR CODE HERE
//
// Block until all threads have called barrier() and
// then increment bstate.round.
//
pthread_mutex_lock(&bstate.barrier_mutex);
bstate.nthread++;
if (bstate.nthread == nthread) {
bstate.nthread = 0; bstate.round++;
pthread_cond_broadcast(&bstate.barrier_cond);
} else pthread_cond_wait(&bstate.barrier_cond, &bstate.barrier_mutex);
pthread_mutex_unlock(&bstate.barrier_mutex);
}

static void *
thread(void *xa)
{
long n = (long) xa;
long delay;
int i;

for (i = 0; i < 20000; i++) {
int t = bstate.round;
assert (i == t);
barrier();
usleep(random() % 100);
}

return 0;
}

int
main(int argc, char *argv[])
{
pthread_t *tha;
void *value;
long i;
double t1, t0;

if (argc < 2) {
fprintf(stderr, "%s: %s nthread\n", argv[0], argv[0]);
exit(-1);
}
nthread = atoi(argv[1]);
tha = malloc(sizeof(pthread_t) * nthread);
srandom(0);

barrier_init();

for(i = 0; i < nthread; i++) {
assert(pthread_create(&tha[i], NULL, thread, (void *) i) == 0);
}
for(i = 0; i < nthread; i++) {
assert(pthread_join(tha[i], &value) == 0);
}
printf("OK; passed\n");
}
Loading

0 comments on commit a765902

Please sign in to comment.