提交 8121ab00 创建 作者: 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

......@@ -8,8 +8,11 @@
#include <sys/mman.h>
#include "atomic.hh"
#include <utility>
static int cpu;
static pthread_barrier_t bar;
std::atomic<int> barrier;
enum { ncore = 8 };
void
......@@ -23,11 +26,34 @@ next()
cpu++;
}
void
ready(void)
{
int slot = --barrier;
if (slot == 1) {
mtenable_type(mtrace_record_ascope, "xv6-asharing");
--barrier;
} else {
while (barrier)
asm volatile("pause");
}
}
u64
rnd(void)
{
static u64 rseed;
rseed = rseed * 6364136223846793005 + 1442695040888963407;
return rseed;
}
void*
vmsharing(void* arg)
{
u64 i = (u64) arg;
ready();
volatile char *p = (char*)(0x40000UL + i * 4096);
if (mmap((void *) p, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) < 0)
die("mmap failed");
......@@ -38,6 +64,48 @@ vmsharing(void* arg)
return 0;
}
std::atomic<int> round;
void*
vm2sharing(void *arg)
{
u64 i = (u64) arg;
char *base = (char*)0x1000;
ready();
while (true) {
while (round % ncore != i)
asm volatile("pause");
if (round >= 50) {
round++;
return 0;
}
int op = rnd() % 2;
int lo = rnd() % 10, hi = rnd() % 10;
if (lo > hi)
std::swap(lo, hi);
if (lo == hi)
continue;
if (op == 0) {
// Map
void *res = mmap(base + lo * 4096, (hi-lo) * 4096, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0);
if (res == MAP_FAILED)
die("asharing: mmap failed");
} else {
// Unmap
int res = munmap(base + lo * 4096, (hi-lo) * 4096);
if (res < 0)
die("asharing: munmap failed");
}
round++;
}
}
void*
fssharing(void* arg)
{
......@@ -52,7 +120,7 @@ fssharing(void* arg)
open(filename, O_CREATE|O_RDWR);
pthread_barrier_wait(&bar);
ready();
for (u64 j = 0; j < ncore; j++) {
snprintf(filename, sizeof(filename), "f%d", j);
......@@ -67,14 +135,15 @@ main(int ac, char **av)
void* (*op)(void*) = 0;
if (ac == 2 && strcmp(av[1], "vm") == 0)
op = vmsharing;
else if (ac == 2 && strcmp(av[1], "vm2") == 0)
op = vm2sharing;
else if (ac == 2 && strcmp(av[1], "fs") == 0)
op = fssharing;
else
fprintf(1, "usage: %s vm|fs\n", av[0]);
if (op) {
mtenable_type(mtrace_record_ascope, "xv6-asharing");
pthread_barrier_init(&bar, 0, ncore);
barrier = ncore + 1;
for (u64 i = 0; i < ncore; i++) {
next();
pthread_t tid;
......@@ -83,6 +152,8 @@ main(int ac, char **av)
for (u64 i = 0; i < ncore; i++)
wait();
if (barrier)
die("forgot to call ready()");
mtdisable("xv6-asharing");
}
}
#pragma once
#include "pstream.hh"
class console_stream : public print_stream
{
public:
constexpr console_stream(bool enabled = true)
: print_stream(enabled) { }
protected:
void write(char c);
void write(sbuf buf);
};
extern console_stream console;
// Errors caused by user processes (page faults, failed system calls,
// etc.)
extern console_stream uerr;
#pragma once
// Extensible, type-safe, usable print streams.
//
// External users of this API should call the print or println methods
// of a print_stream. To specially format numbers, use sfmt or shex.
// To output byte buffers, use sbuf.
//
// Extensions of this API to add printable types should be implemented
// as overloads of to_stream and should call other to_stream
// functions.
//
// Output stream types should be implemented as subclasses of
// print_stream.
#include <utility>
struct sbuf
{
const char *base;
size_t len;
sbuf(const char *b, size_t l) : base(b), len(l) { }
sbuf(const sbuf &o) = default;
sbuf(sbuf &&o) = default;
};
class print_stream
{
public:
// By making this constexpr (and assuming derived classes have
// either no constructor or a constexpr constructor), print_streams
// can be fully initialized at compile time, including the vtable
// pointer (meaning global print_streams don't require static
// construction).
constexpr print_stream() : enabled(true) { }
virtual ~print_stream() { }
// Write each of the arguments to this stream in order.
template<typename... T>
void print(T&&... args)
{
if (enabled)
_print(std::forward<T>(args)...);
}
// Like print, but append a newline.
template<typename... T>
void println(T&&... args)
{
if (enabled) {
_print(std::forward<T>(args)...);
write('\n');
}
}
protected:
bool enabled;
constexpr print_stream(bool enabled) : enabled(enabled) { }
virtual void write(char c)
{
write(sbuf(&c, 1));
}
virtual void write(sbuf buf) = 0;
friend void to_stream(print_stream *s, char c);
friend void to_stream(print_stream *s, sbuf b);
private:
template<typename T1, typename... T>
void _print(T1 &&arg1, T&&... rest)
{
to_stream(this, std::forward<T1>(arg1));
_print(std::forward<T>(rest)...);
}
void _print() { }
};
class null_stream : public print_stream
{
public:
constexpr null_stream() : print_stream(false) { }
protected:
void write(char c) { }
void write(sbuf buf) { }
};
inline
void to_stream(print_stream *s, char c)
{
s->write(c);
}
inline
void to_stream(print_stream *s, sbuf b)
{
s->write(b);
}
void to_stream(print_stream *s, int v);
void to_stream(print_stream *s, unsigned v);
void to_stream(print_stream *s, long v);
void to_stream(print_stream *s, unsigned long v);
void to_stream(print_stream *s, long long v);
void to_stream(print_stream *s, unsigned long long v);
void to_stream(print_stream *s, const char *str);
void to_stream(print_stream *s, void *ptr);
class integer_formatter
{
unsigned long long val_;
int width_;
unsigned char base_;
char pad_;
bool neg_;
bool alt_;
friend void to_stream(print_stream *s, const integer_formatter &n);
public:
integer_formatter(unsigned long long v, bool neg)
: val_(v), width_(0), base_(10), pad_(' '), neg_(neg), alt_(false) { }
integer_formatter &width(int width)
{
width_ = width;
return *this;
}
integer_formatter &base(unsigned base)
{
if (base == 0 || base > 16)
base = 10;
base_ = base;
return *this;
}
integer_formatter &pad(char pad)
{
pad_ = pad;
return *this;
}
// Format the number using an alternate form. If base is 8 and the
// number is non-zero, this will prefix the output with "0". If
// base is 16 and the number of non-zero, this will prefix the
// output with "0x".
integer_formatter &alt(bool alt = true)
{
alt_ = alt;
return *this;
}
};
void to_stream(print_stream *s, const integer_formatter &n);
// Format any integral value. The default formatting is equivalent to
// passing the value directly to the print stream, but can be
// manipulated using the methods of integer_formatter.
template<typename T>
integer_formatter sfmt(T v)
{
bool neg = v < 0;
if (neg)
v = -v;
return integer_formatter(v, neg);
}
// Format v in hexadecimal and, if non-zero, preceded by an 0x.
template<typename T>
integer_formatter shex(T v)
{
return sfmt(v).base(16).alt();
}
......@@ -68,6 +68,9 @@ struct vma
NEW_DELETE_OPS(vma)
};
class print_stream;
void to_stream(print_stream *s, vma *v);
// An address space: a set of vmas plus h/w page table.
// The elements of e[] are not ordered by address.
struct vmap {
......
......@@ -57,6 +57,7 @@ OBJS = \
zalloc.o \
incbin.o \
sysvectors.o \
pstream.o
ifeq ($(EXCEPTIONS),y)
OBJS += \
......
......@@ -19,6 +19,7 @@
#include "sperf.hh"
#include "wq.hh"
#include "major.h"
#include "kstream.hh"
#define BACKSPACE 0x100
......@@ -336,6 +337,24 @@ consoleread(struct inode *ip, char *dst, u32 off, u32 n)
return target - n;
}
// Console stream support
void
console_stream::write(char c)
{
consputc(c);
}
void
console_stream::write(sbuf buf)
{
for (size_t i = 0; i < buf.len; i++)
consputc(buf.base[i]);
}
console_stream console;
console_stream uerr(false);
void
initconsole(void)
{
......
......@@ -127,6 +127,7 @@ idleloop(void)
exit();
} while(worked);
sti();
nop_pause();
}
}
}
......
......@@ -301,8 +301,10 @@ acquire(struct spinlock *lk)
locking(lk);
retries = 0;
while(xchg32(&lk->locked, 1) != 0)
while(xchg32(&lk->locked, 1) != 0) {
retries++;
nop_pause();
}
locked(lk, retries);
}
......
......@@ -12,6 +12,7 @@
#include "bits.hh"
#include "kalloc.hh"
#include "apic.hh"
#include "kstream.hh"
extern "C" void __uaccess_end(void);
......@@ -73,7 +74,7 @@ do_pagefault(struct trapframe *tf)
#endif
return 0;
}
cprintf("pagefault: failed in user\n");
uerr.println("pagefault: failed in user");
cli();
}
return -1;
......@@ -171,10 +172,11 @@ trap(struct trapframe *tf)
kerneltrap(tf);
// In user space, assume process misbehaved.
cprintf("pid %d %s: trap %lu err %d on cpu %d "
"rip 0x%lx rsp 0x%lx addr 0x%lx--kill proc\n",
myproc()->pid, myproc()->name, tf->trapno, tf->err,
mycpu()->id, tf->rip, tf->rsp, rcr2());
uerr.println("pid ", myproc()->pid, ' ', myproc()->name,
": trap ", (u64)tf->trapno, " err ", (u32)tf->err,
" on cpu ", mycpuid(), " rip ", shex(tf->rip),
" rsp ", shex(tf->rsp), " addr ", shex(rcr2()),
"--kill proc");
myproc()->killed = 1;
}
......
......@@ -16,6 +16,7 @@
#include "sperf.hh"
#include "uwq.hh"
#include "kmtrace.hh"
#include "kstream.hh"
enum { vm_debug = 0 };
enum { tlb_shootdown = 1 };
......@@ -188,6 +189,13 @@ vma::~vma()
n->decref();
}
void
to_stream(print_stream *s, vma *v)
{
s->print("vma@[", shex(v->vma_start), ',', shex(v->vma_end), ')',
v->va_type == COW ? "/COW" : "");
}
/*
* vmap
*/
......@@ -425,8 +433,7 @@ again:
goto again;
vma *rvma = (vma*) r;
cprintf("vmap::insert: overlap with %p: 0x%lx--0x%lx\n",
rvma, rvma->vma_start, rvma->vma_end);
uerr.println("vmap::insert: overlap with ", rvma);
return -1;
}
#endif
......@@ -509,8 +516,9 @@ vmap::remove(uptr vma_start, uptr len)
for (auto r: span) {
vma *rvma = (vma*) r;
if (rvma->vma_start < vma_start || rvma->vma_end > vma_end) {
cprintf("vmap::remove: partial unmap not supported; unmapping [%#lx,%#lx) from [%#lx,%#lx)\n",
vma_start, vma_start+len, rvma->vma_start, rvma->vma_end);
uerr.println("vmap::remove: partial unmap not supported; "
"unmapping [", shex(vma_start),",",shex(vma_start+len), ")"
" from ", rvma);
return -1;
}
}
......@@ -821,8 +829,8 @@ vmap::sbrk(ssize_t n, uptr *addr)
prev = e;
#endif
} else {
cprintf("growproc: overlap with existing mapping; brk %lx n %ld\n",
curbrk, n);
uerr.println("growproc: overlap with existing mapping; "
"brk ", shex(curbrk), " n ", n);
return -1;
}
}
......
......@@ -2,7 +2,8 @@ $(O)/lib/%.o: CFLAGS:=$(CFLAGS) -DXV6_USER
$(O)/lib/%.o: CXXFLAGS:=$(CXXFLAGS) -DXV6_USER -fno-exceptions -fno-rtti
ULIB = ulib.o printf.o umalloc.o uthread.o fmt.o stream.o ipc.o \
threads.o crt.o wqlib.o wquser.o perf.o wqalloc.o sysstubs.o
threads.o crt.o wqlib.o wquser.o perf.o wqalloc.o sysstubs.o \
pstream.o
ULIB := $(addprefix $(O)/lib/, $(ULIB))
$(O)/lib/sysstubs.S: tools/syscalls.py kernel/*.cc
......
#include "pstream.hh"
#include "user.h" // For strlen
static void
streamnum (print_stream *s, unsigned long long num,
bool neg = false, unsigned base = 10, int width = 0, char pad = 0,
bool alt = false)
{
char buf[68], *x = buf + sizeof(buf);
if (num == 0)
*--x = '0';
else {
for (; num; num /= base)
*--x = "0123456789abcdef"[num % base];
if (alt) {
if (base == 16) {
*--x = 'x';
*--x = '0';
} else if (base == 8) {
*--x = '0';
}
}
if (neg)
*--x = '-';
}
size_t len = buf + sizeof(buf) - x;
for (; width > len; width--)
to_stream(s, pad);
to_stream(s, sbuf(x, len));
for (; width < 0; width++)
to_stream(s, pad);
}
#define INT_TO_STREAM(typ) \
void to_stream(print_stream *s, typ v) \
{ \
streamnum(s, v); \
} \
\
void to_stream(print_stream *s, unsigned typ v) \
{ \
if (v < 0) \
streamnum(s, -v, true); \
else \
streamnum(s, v, false); \
} \
static_assert(true, "need a semicolon")
INT_TO_STREAM(int);
INT_TO_STREAM(long);
INT_TO_STREAM(long long);
void to_stream(print_stream *s, const char *str)
{
to_stream(s, sbuf(str, strlen(str)));
}
void to_stream(print_stream *s, void *ptr)
{
to_stream(s, sbuf("0x", 2));
streamnum(s, (unsigned long long)ptr, false, 16);
}
void to_stream(print_stream *s, const integer_formatter &n)
{
streamnum(s, n.val_, n.neg_, n.base_, n.width_, n.pad_, n.alt_);
}
......@@ -2,9 +2,24 @@
#pragma once
#include "types.h" // For size_t
#include <type_traits>
namespace std {
template <class T>
T&&
forward(typename remove_reference<T>::type& t)
{
return static_cast<T&&>(t);
}
template <class T>
T&&
forward(typename remove_reference<T>::type&& t)
{
return static_cast<T&&>(t);
}
template<class T>
typename remove_reference<T>::type&&
move(T&& a)
......
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论