-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
576 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -16,4 +16,7 @@ kernel/kernel | |
user/usys.S | ||
.gdbinit | ||
*.pyc | ||
xv6.out* | ||
xv6.out* | ||
ph | ||
*.dSYM | ||
barrier |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
hello world |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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() | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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"); | ||
} |
Oops, something went wrong.