Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ UPROGS=\
$U/_bcachetest\
$U/_alloctest\
$U/_specialtest\
$U/_dhagatest\
# $U/_symlinktest\

fs.img: mkfs/mkfs README user/xargstest.sh $(UPROGS)
Expand Down
2 changes: 2 additions & 0 deletions kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ main()
iinit(); // inode cache
fileinit(); // file table
virtio_disk_init(minor(ROOTDEV)); // emulated hard disk
printf("yo1\n");
userinit(); // first user process
printf("yo2\n");
__sync_synchronize();
started = 1;
} else {
Expand Down
1 change: 1 addition & 0 deletions kernel/param.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
#define MAXPATH 128 // maximum file path name
#define NDISK 2
#define NNETIF 2
#define NTHREAD 128 // 2*NPROC
142 changes: 134 additions & 8 deletions kernel/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,16 @@
struct cpu cpus[NCPU];

struct proc proc[NPROC];
struct thread thread[NTHREAD];

struct proc *initproc;

int nextpid = 1;
struct spinlock pid_lock;

int nexttid = 1;
struct spinlock tid_lock;

extern void forkret(void);
static void wakeup1(struct proc *chan);

Expand Down Expand Up @@ -74,6 +78,40 @@ myproc(void) {
return p;
}

struct thread*
nextrunnablethread(struct proc *p)
{
printf("finding a runnable thread\n");
struct threadlist *t;

t = p->threads;
while (t!=0)
{
if(t->tcb->state == RUNNABLE)
{
printf("found thread with id:%d\n", t->tcb->tid);
return t->tcb;
}
t = t->next;
}

printf("could not find a runnable thread\n");
return 0;
}


int
alloctid() {
int tid;

acquire(&tid_lock);
tid = nexttid;
nexttid = nexttid + 1;
release(&tid_lock);

return tid;
}

int
allocpid() {
int pid;
Expand All @@ -86,6 +124,40 @@ allocpid() {
return pid;
}

static struct thread*
allocthread(uint64 stack, uint64 fnaddr)
{
printf("starting thread allocation\n");
struct thread *t;

for (t = thread; t < &thread[NTHREAD]; t++)
{
acquire(&t->lock);
if(t->state == UNUSED)
{
goto threadfound;
} else {
release(&t->lock);
}
}
printf("could not find a runnable thread\n");
return 0;

threadfound:
t->tid = alloctid();
printf("found thread, assigned id: %d\n", t->tid);
release(&t->lock);

// Set up new context to start executing at forkret,
// which returns to user space.
memset(&t->context, 0, sizeof t->context);
t->context.ra = fnaddr;
t->context.sp = stack;
printf("thread context set with ra: %u and sp: %u\n", t->context.ra, t->context.sp);
return t;

}

// Look in the process table for an UNUSED proc.
// If found, initialize state required to run in the kernel,
// and return with p->lock held.
Expand Down Expand Up @@ -117,15 +189,48 @@ allocproc(void)
// An empty user page table.
p->pagetable = proc_pagetable(p);

// Set up new context to start executing at forkret,
// which returns to user space.
memset(&p->context, 0, sizeof p->context);
p->context.ra = (uint64)forkret;
p->context.sp = p->kstack + PGSIZE;
// allocate main execution thread
uint64 fnaddr = (uint64)forkret;
uint64 stack = p->kstack + PGSIZE;

struct thread *t = allocthread(stack, fnaddr);

if(t==0)
{
printf("no thread allocated\n");
return 0;
}

struct threadlist threads;
threads.tcb = t;
threads.next = 0;
p->threads = &threads;

printf("%p %p\n", &threads, &threads.tcb);
return p;
}

static void
freethread(struct thread *t)
{
acquire(&t->lock);
t->state = UNUSED;
t->tid = 0;
release(&t->lock);
}

static void
freethreads(struct threadlist *threads)
{
struct threadlist *t = threads;

while (t!=0)
{
freethread(t->tcb);
t = t->next;
}
}

// free a proc structure and the data hanging from it,
// including user pages.
// p->lock must be held.
Expand All @@ -146,6 +251,8 @@ freeproc(struct proc *p)
p->killed = 0;
p->xstate = 0;
p->state = UNUSED;
freethreads(p->threads);
p->threads = 0;
}

// Create a page table for a given process,
Expand Down Expand Up @@ -218,7 +325,13 @@ userinit(void)

p->state = RUNNABLE;

// why no acquire for p-lock
struct thread *tcb = p->threads->tcb;

tcb->state = RUNNABLE;
release(&tcb->lock);
release(&p->lock);

}

// Grow or shrink user memory by n bytes.
Expand Down Expand Up @@ -283,6 +396,12 @@ fork(void)

np->state = RUNNABLE;

struct thread *tcb = p->threads->tcb;

acquire(&tcb->lock);
tcb->state = RUNNABLE;
release(&tcb->lock);

release(&np->lock);

return pid;
Expand Down Expand Up @@ -466,7 +585,13 @@ scheduler(void)
// before jumping back to us.
p->state = RUNNING;
c->proc = p;
swtch(&c->scheduler, &p->context);
struct thread *t = nextrunnablethread(p);
acquire(&t->lock);

t->state = RUNNING;
swtch(&c->scheduler, &t->context);

release(&t->lock);

// Process is done running for now.
// It should have changed its p->state before coming back.
Expand Down Expand Up @@ -499,7 +624,7 @@ sched(void)
{
int intena;
struct proc *p = myproc();

if(!holding(&p->lock))
panic("sched p->lock");
if(mycpu()->noff != 1)
Expand All @@ -510,7 +635,8 @@ sched(void)
panic("sched interruptible");

intena = mycpu()->intena;
swtch(&p->context, &mycpu()->scheduler);
struct thread *t = nextrunnablethread(p);
swtch(&t->context, &mycpu()->scheduler);
mycpu()->intena = intena;
}

Expand Down
24 changes: 23 additions & 1 deletion kernel/proc.h
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,26 @@ struct trapframe {

enum procstate { UNUSED, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };

struct thread
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We also need trapframe here.

{
struct spinlock lock;

// t->lock must be held when using these:
int tid;
enum procstate state;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need this. We need a pointer to parent proc itself.


// these are private to thread, lock need not be held
struct context context;
};

// linked list for dynamic thread allocation
struct threadlist
{
struct thread *tcb;
struct threadlist *next;
};

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the fancy list is nice and gives a container like ability, but let's keep things simple for now and just use an array.


// Per-process state
struct proc {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove trapFrame from here.

struct spinlock lock;
Expand All @@ -103,4 +123,6 @@ struct proc {
struct file *ofile[NOFILE]; // Open files
struct inode *cwd; // Current directory
char name[16]; // Process name (debugging)
};

struct threadlist *threads; // Data structure to handle dynamic allocation of threads
};
2 changes: 2 additions & 0 deletions kernel/syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ extern uint64 sys_write(void);
extern uint64 sys_uptime(void);
extern uint64 sys_ntas(void);
extern uint64 sys_nfree(void);
extern uint64 sys_clone(void);

static uint64 (*syscalls[])(void) = {
[SYS_fork] sys_fork,
Expand All @@ -131,6 +132,7 @@ static uint64 (*syscalls[])(void) = {
[SYS_close] sys_close,
[SYS_ntas] sys_ntas,
[SYS_nfree] sys_nfree,
[SYS_clone] sys_clone
};

void
Expand Down
3 changes: 3 additions & 0 deletions kernel/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@
// System calls for labs
#define SYS_ntas 22
#define SYS_nfree 23

// DHAGA calls
#define SYS_clone 24
6 changes: 6 additions & 0 deletions kernel/sysproc.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,3 +95,9 @@ sys_uptime(void)
release(&tickslock);
return xticks;
}

uint64
sys_clone(void)
{
return 0;
}
22 changes: 22 additions & 0 deletions user/dhagatest.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "kernel/types.h"
#include "kernel/stat.h"
#include "user/user.h"

void
dhagatest()
{
if(clone((void *)0,0)!=0)
{
printf("clone should return zero\n");
exit(1);
}

printf("all tests passing\n");
}

int
main(void)
{
dhagatest();
exit(0);
}
1 change: 1 addition & 0 deletions user/user.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ int crash(const char*, int);
int mount(char*, char *);
int umount(char*);
int nfree();
int clone(void*, int);

// ulib.c
int stat(const char*, struct stat*);
Expand Down
1 change: 1 addition & 0 deletions user/usys.pl
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,4 @@ sub entry {
entry("uptime");
entry("ntas");
entry("nfree");
entry("clone");