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
11 changes: 10 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ OBJS = \
$K/sysfile.o \
$K/kernelvec.o \
$K/plic.o \
$K/virtio_disk.o
$K/shm.o \
$K/mbox.o \
$K/virtio_disk.o\



# riscv64-unknown-elf- or riscv64-linux-gnu-
# perhaps in /opt/riscv/bin
Expand Down Expand Up @@ -141,6 +145,11 @@ UPROGS=\
$U/_grind\
$U/_wc\
$U/_zombie\
$U/_ipctest\
$U/_gamemaster\
$U/_player\
$U/_run_race\


fs.img: mkfs/mkfs README $(UPROGS)
mkfs/mkfs fs.img README $(UPROGS)
Expand Down
20 changes: 20 additions & 0 deletions kernel/defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,5 +185,25 @@ void virtio_disk_init(void);
void virtio_disk_rw(struct buf *, int);
void virtio_disk_intr(void);

// ... in sem.c
void seminit(void);
int sem_init(int, int);
int sem_down(int);
int sem_up(int);

// shm.c
void shm_init(void);
int shm_create(int key);
void* shm_get(int key);
int shm_close(int key);
void shm_cleanup(struct proc *p);
// number of elements in fixed-size array

// mbox.c
void mbox_init(void);
int mbox_create(int key);
int mbox_send(int mbox_id, int msg);
int mbox_recv(int mbox_id, uint64 user_addr_msg);


#define NELEM(x) (sizeof(x)/sizeof((x)[0]))
2 changes: 2 additions & 0 deletions kernel/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ main()
iinit(); // inode table
fileinit(); // file table
virtio_disk_init(); // emulated hard disk
shm_init(); // shared memory system
mbox_init();
userinit(); // first user process
__sync_synchronize();
started = 1;
Expand Down
134 changes: 134 additions & 0 deletions kernel/mbox.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
// kernel/mbox.c

#include "types.h"
#include "param.h"
#include "memlayout.h"
#include "riscv.h"
#include "spinlock.h"
#include "proc.h"
#include "defs.h"

#define MAX_MAILBOXES 16
#define MBOX_SIZE 8

struct mailbox {
int key;
int messages[MBOX_SIZE];
int head;
int tail;
int count;
int in_use;
struct spinlock lock;
};

static struct mailbox mailboxes[MAX_MAILBOXES];
static struct spinlock mbox_table_lock;

void
mbox_init(void)
{
initlock(&mbox_table_lock, "mbox_table");
for(int i = 0; i < MAX_MAILBOXES; i++) {
mailboxes[i].in_use = 0;
mailboxes[i].key = -1;
mailboxes[i].head = 0;
mailboxes[i].tail = 0;
mailboxes[i].count = 0;
initlock(&mailboxes[i].lock, "mailbox");
}
}

int
mbox_create(int key)
{
acquire(&mbox_table_lock);

for(int i = 0; i < MAX_MAILBOXES; i++) {
if(mailboxes[i].in_use && mailboxes[i].key == key) {
release(&mbox_table_lock);
return i;
}
}

int mbox_id = -1;
for(int i = 0; i < MAX_MAILBOXES; i++) {
if(!mailboxes[i].in_use) {
mbox_id = i;
break;
}
}

if(mbox_id == -1) {
release(&mbox_table_lock);
return -1;
}

mailboxes[mbox_id].key = key;
mailboxes[mbox_id].head = 0;
mailboxes[mbox_id].tail = 0;
mailboxes[mbox_id].count = 0;
mailboxes[mbox_id].in_use = 1;

release(&mbox_table_lock);
return mbox_id;
}

int
mbox_send(int mbox_id, int msg)
{
if(mbox_id < 0 || mbox_id >= MAX_MAILBOXES || !mailboxes[mbox_id].in_use) {
return -1;
}

struct mailbox* mb = &mailboxes[mbox_id];

acquire(&mb->lock);

while(mb->count >= MBOX_SIZE) {
sleep(mb, &mb->lock);
}

mb->messages[mb->tail] = msg;
mb->tail = (mb->tail + 1) % MBOX_SIZE;
mb->count++;

wakeup(mb);

release(&mb->lock);
return 0;
}

int
mbox_recv(int mbox_id, uint64 user_addr_msg)
{
if(mbox_id < 0 || mbox_id >= MAX_MAILBOXES || !mailboxes[mbox_id].in_use) {
return -1;
}

if(user_addr_msg == 0) {
return -1;
}

struct mailbox* mb = &mailboxes[mbox_id];
int received_msg;

acquire(&mb->lock);

while(mb->count == 0) {
sleep(mb, &mb->lock);
}

received_msg = mb->messages[mb->head];
mb->head = (mb->head + 1) % MBOX_SIZE;
mb->count--;

wakeup(mb);

release(&mb->lock);

if(copyout(myproc()->pagetable, user_addr_msg, (char*)&received_msg, sizeof(int)) < 0) {
return -1;
}

return 0;
}
2 changes: 1 addition & 1 deletion kernel/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ exit(int status)
p->state = ZOMBIE;

release(&wait_lock);

shm_cleanup(p);
// Jump into the scheduler, never to return.
sched();
panic("zombie exit");
Expand Down
92 changes: 92 additions & 0 deletions kernel/sem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// kernel/sem.c

#include "types.h"
#include "riscv.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "spinlock.h"
#include "proc.h"

struct semaphore sems[NSEM];
struct spinlock sems_lock; // protects the sems array

void
seminit(void)
{
initlock(&sems_lock, "sems");
for(int i = 0; i < NSEM; i++) {
initlock(&sems[i].lock, "semaphore");
sems[i].valid = 0;
}
}

int
sem_init(int sem_id, int value)
{
if(sem_id < 0 || sem_id >= NSEM) {
return -1; // Invalid ID
}

// This function now acts as a reset if the semaphore is already valid.
acquire(&sems_lock);
sems[sem_id].count = value;
sems[sem_id].valid = 1;
release(&sems_lock);

return 0;
}
// sem_down(int sem_id) -> P operation
// sem_down(int sem_id) -> P operation
int
sem_down(int sem_id)
{
if(sem_id < 0 || sem_id >= NSEM) {
return -1;
}

// Acquire the global lock to safely check the valid flag.
acquire(&sems_lock);
if(!sems[sem_id].valid) {
release(&sems_lock);
return -1; // Not initialized
}
release(&sems_lock);

struct semaphore *s = &sems[sem_id];

acquire(&s->lock);
while(s->count == 0) {
sleep(s, &s->lock);
}
s->count--;
release(&s->lock);

return 0;
}

// sem_up(int sem_id) -> V operation
int
sem_up(int sem_id)
{
if(sem_id < 0 || sem_id >= NSEM) {
return -1;
}

// Acquire the global lock to safely check the valid flag.
acquire(&sems_lock);
if(!sems[sem_id].valid) {
release(&sems_lock);
return -1; // Not initialized
}
release(&sems_lock);

struct semaphore *s = &sems[sem_id];

acquire(&s->lock);
s->count++;
wakeup(s);
release(&s->lock);

return 0;
}
Loading