aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsotech117 <michael_foiani@brown.edu>2024-03-02 23:05:26 +0000
committersotech117 <michael_foiani@brown.edu>2024-03-02 23:05:26 +0000
commit8c2e0ce946012a4275e8dfa9d8dfd1d5a68d6e3e (patch)
tree1877a33c6488a5b16fb7962e1ffb0f72f13a5052
parent9c90e73fda0d5df2e1f11b32d459d3bb07a63192 (diff)
decent coding session
-rw-r--r--Config.mk2
-rw-r--r--kernel/drivers/disk/sata.c40
-rw-r--r--kernel/drivers/memdevs.c60
-rw-r--r--kernel/drivers/tty/ldisc.c165
-rw-r--r--kernel/drivers/tty/tty.c48
-rw-r--r--kernel/main/kmain.c15
-rw-r--r--kernel/proc/proc.c11
-rw-r--r--kernel/proc/sched.c10
-rw-r--r--kernel/test/proctest.c2
-rw-r--r--kernel/util/debug.c2
10 files changed, 322 insertions, 33 deletions
diff --git a/Config.mk b/Config.mk
index 1675c07..7281781 100644
--- a/Config.mk
+++ b/Config.mk
@@ -10,7 +10,7 @@
# Setting any of these variables will control which parts of the source tree
# are built. To enable something set it to 1, otherwise set it to 0.
#
- DRIVERS=0
+ DRIVERS=1
VFS=0
S5FS=0
VM=0
diff --git a/kernel/drivers/disk/sata.c b/kernel/drivers/disk/sata.c
index aa3ff41..0a083b4 100644
--- a/kernel/drivers/disk/sata.c
+++ b/kernel/drivers/disk/sata.c
@@ -488,7 +488,25 @@ void sata_init()
long sata_read_block(blockdev_t *bdev, char *buf, blocknum_t block,
size_t block_count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: sata_read_block");
+ // NOT_YET_IMPLEMENTED("DRIVERS: sata_read_block");
+
+ // convert block to sector
+ ssize_t lba = block * SATA_SECTORS_PER_BLOCK;
+ ssize_t count = block_count * SATA_SECTORS_PER_BLOCK;
+
+ // get the disk
+ ata_disk_t *disk = bdev_to_ata_disk(bdev);
+ if (disk == NULL)
+ {
+ dbg(DBG_DISK, "sata_read_block: disk is NULL\n");
+ return -1;
+ }
+
+ // call ahci_do_operation
+ long ret = ahci_do_operation(disk->port, lba, count, buf,
+ 0 // 0 for read
+ );
+
return -1;
}
@@ -507,6 +525,24 @@ long sata_read_block(blockdev_t *bdev, char *buf, blocknum_t block,
long sata_write_block(blockdev_t *bdev, const char *buf, blocknum_t block,
size_t block_count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: sata_write_block");
+ // NOT_YET_IMPLEMENTED("DRIVERS: sata_write_block");
+
+ // convert block to sector
+ ssize_t lba = block * SATA_SECTORS_PER_BLOCK;
+ ssize_t count = block_count * SATA_SECTORS_PER_BLOCK;
+
+ // get the disk
+ ata_disk_t *disk = bdev_to_ata_disk(bdev);
+ if (disk == NULL)
+ {
+ dbg(DBG_DISK, "sata_write_block: disk is NULL\n");
+ return -1;
+ }
+
+ // call ahci_do_operation
+ long ret = ahci_do_operation(disk->port, lba, count, (void *)buf,
+ 1 // 1 for write
+ );
+
return -1;
}
diff --git a/kernel/drivers/memdevs.c b/kernel/drivers/memdevs.c
index 50815d3..815143a 100644
--- a/kernel/drivers/memdevs.c
+++ b/kernel/drivers/memdevs.c
@@ -43,7 +43,31 @@ chardev_ops_t zero_dev_ops = {.read = zero_read,
*/
void memdevs_init()
{
- NOT_YET_IMPLEMENTED("DRIVERS: memdevs_init");
+ // NOT_YET_IMPLEMENTED("DRIVERS: memdevs_init");
+
+ // create chardev_t's for null and zero
+ chardev_t *null_dev = kmalloc(sizeof(chardev_t));
+ if (null_dev == NULL)
+ {
+ dbg(DBG_DISK, "ERROR: kmalloc failed on null_dev in memdevs_init\n");
+ return;
+ }
+ chardev_t *zero_dev = kmalloc(sizeof(chardev_t));
+ if (zero_dev == NULL)
+ {
+ dbg(DBG_DISK, "ERROR: kmalloc failed on zero_dev in memdevs_init\n");
+ return;
+ }
+
+ // fill them in
+ null_dev->cd_id = MEM_NULL_DEVID;
+ null_dev->cd_ops = &null_dev_ops;
+ zero_dev->cd_id = MEM_ZERO_DEVID;
+ zero_dev->cd_ops = &zero_dev_ops;
+
+ // register them
+ chardev_register(null_dev);
+ chardev_register(zero_dev);
}
/**
@@ -58,8 +82,9 @@ void memdevs_init()
*/
static ssize_t null_read(chardev_t *dev, size_t pos, void *buf, size_t count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: null_read");
- return -ENOMEM;
+ // NOT_YET_IMPLEMENTED("DRIVERS: null_read");
+ // TODO: ask about buffer checking
+ return 0; // return reading no bytes
}
/**
@@ -76,8 +101,18 @@ static ssize_t null_read(chardev_t *dev, size_t pos, void *buf, size_t count)
static ssize_t null_write(chardev_t *dev, size_t pos, const void *buf,
size_t count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: null_write");
- return -ENOMEM;
+ // NOT_YET_IMPLEMENTED("DRIVERS: null_write");
+
+ // check if the buffer is NULL
+ if (buf == NULL)
+ {
+ return -EINVAL;
+ }
+
+ // there is no true writing, so just do nothing here
+
+ // return the number of bytes written
+ return count;
}
/**
@@ -93,8 +128,19 @@ static ssize_t null_write(chardev_t *dev, size_t pos, const void *buf,
*/
static ssize_t zero_read(chardev_t *dev, size_t pos, void *buf, size_t count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: zero_read");
- return 0;
+ // NOT_YET_IMPLEMENTED("DRIVERS: zero_read");
+
+ // check if the buffer is NULL
+ if (buf == NULL)
+ {
+ return -EINVAL;
+ }
+
+ // fill the buffer with zeros
+ memset(buf, 0, count);
+
+ // return the number of bytes read
+ return count;
}
/**
diff --git a/kernel/drivers/tty/ldisc.c b/kernel/drivers/tty/ldisc.c
index eaf0440..dd67706 100644
--- a/kernel/drivers/tty/ldisc.c
+++ b/kernel/drivers/tty/ldisc.c
@@ -16,7 +16,19 @@
*/
void ldisc_init(ldisc_t *ldisc)
{
- NOT_YET_IMPLEMENTED("DRIVERS: ldisc_init");
+ // NOT_YET_IMPLEMENTED("DRIVERS: ldisc_init");
+
+ // reset static buffer
+ memset(ldisc->ldisc_buffer, 0, LDISC_BUFFER_SIZE);
+
+ // init the queue
+ sched_queue_init(&ldisc->ldisc_read_queue);
+
+ // fill in other fields
+ ldisc->ldisc_head = 0;
+ ldisc->ldisc_tail = 0;
+ ldisc->ldisc_cooked = 0;
+ ldisc->ldisc_full = 0; // 0 not full
}
/**
@@ -33,8 +45,31 @@ void ldisc_init(ldisc_t *ldisc)
*/
long ldisc_wait_read(ldisc_t *ldisc)
{
- NOT_YET_IMPLEMENTED("DRIVERS: ldisc_wait_read");
- return -1;
+ // NOT_YET_IMPLEMENTED("DRIVERS: ldisc_wait_read");
+
+ // if it's full, return 0
+ if (ldisc->ldisc_full)
+ {
+ return 0;
+ }
+
+ // while there are no need chars to be read, sleep
+ // TODO: check if this is the right condition
+ while (
+ (ldisc->ldisc_head == ldisc->ldisc_tail)
+ ||
+ (ldisc->ldisc_head == ldisc->ldisc_cooked)
+ )
+ {
+ long ret = sched_cancellable_sleep_on(&ldisc->ldisc_read_queue);
+ if (ret != 0)
+ {
+ return ret;
+ }
+ }
+
+ // if we are here, it means we have new chars to read
+ return 0;
}
/**
@@ -54,8 +89,51 @@ long ldisc_wait_read(ldisc_t *ldisc)
*/
size_t ldisc_read(ldisc_t *ldisc, char *buf, size_t count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: ldisc_read");
- return 0;
+ // NOT_YET_IMPLEMENTED("DRIVERS: ldisc_read");
+
+ // read from ldisc buffer to buf
+ size_t i = 0;
+ while (i < count)
+ {
+ // if we have new chars to read
+ if (ldisc->ldisc_head != ldisc->ldisc_tail)
+ {
+ // if we encounter a new line symbol
+ if (ldisc->ldisc_buffer[ldisc->ldisc_head] == '\n')
+ {
+ buf[i] = ldisc->ldisc_buffer[ldisc->ldisc_head];
+ ldisc->ldisc_head = (ldisc->ldisc_head + 1) % LDISC_BUFFER_SIZE;
+ i++;
+ break;
+ }
+ // if we encounter an EOT
+ else if (ldisc->ldisc_buffer[ldisc->ldisc_head] == EOT)
+ {
+ break;
+ }
+ // if we encounter an ETX
+ else if (ldisc->ldisc_buffer[ldisc->ldisc_head] == ETX)
+ {
+ // clear uncooked portion of the line
+ ldisc->ldisc_head = ldisc->ldisc_cooked;
+ break;
+ }
+ // if we encounter a normal char
+ else
+ {
+ buf[i] = ldisc->ldisc_buffer[ldisc->ldisc_head];
+ ldisc->ldisc_head = (ldisc->ldisc_head + 1) % LDISC_BUFFER_SIZE;
+ i++;
+ }
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ // return the number of bytes read
+ return i;
}
/**
@@ -103,7 +181,66 @@ size_t ldisc_read(ldisc_t *ldisc, char *buf, size_t count)
*/
void ldisc_key_pressed(ldisc_t *ldisc, char c)
{
- NOT_YET_IMPLEMENTED("DRIVERS: ldisc_key_pressed");
+ // NOT_YET_IMPLEMENTED("DRIVERS: ldisc_key_pressed");
+
+ // if the buffer is full, ignore the incoming char
+ if (ldisc->ldisc_full)
+ {
+ return;
+ }
+
+ switch (c)
+ {
+ case '\b':
+ // if there is a character to remove
+ if (ldisc->ldisc_head != ldisc->ldisc_tail)
+ {
+ // remove the last char
+ ldisc->ldisc_head = (ldisc->ldisc_head - 1 + LDISC_BUFFER_SIZE) % LDISC_BUFFER_SIZE;
+ // emit a `\b` to the vterminal
+ vterminal_write(ldisc_to_tty(ldisc), "\b", 1);
+ }
+ break;
+
+ case '\n':
+ // emit a `\n` to the vterminal
+ vterminal_write(ldisc_to_tty(ldisc), "\n", 1);
+
+ // add the new char to the buffer
+ ldisc->ldisc_buffer[ldisc->ldisc_tail] = c;
+ ldisc->ldisc_tail = (ldisc->ldisc_tail + 1) % LDISC_BUFFER_SIZE;
+ // set the buffer to full
+ ldisc->ldisc_full = 1;
+
+ // wake up the thread that is sleeping on the wait queue of the line discipline
+ sched_wakeup_on(&ldisc->ldisc_read_queue, 0);
+ break;
+
+ case EOT:
+ // add the new char to the buffer
+ ldisc->ldisc_buffer[ldisc->ldisc_tail] = c;
+ ldisc->ldisc_tail = (ldisc->ldisc_tail + 1) % LDISC_BUFFER_SIZE;
+ // set the buffer to full
+ ldisc->ldisc_full = 1;
+
+ // cook the buffer
+ ldisc->ldisc_cooked = ldisc->ldisc_tail;
+
+ // wake up the thread that is sleeping on the wait queue of the line discipline
+ sched_wakeup_on(&ldisc->ldisc_read_queue, 0);
+ break;
+
+ case ETX:
+ // clear uncooked portion of the line
+ ldisc->ldisc_head = ldisc->ldisc_cooked;
+ break;
+
+ default:
+ // if none applies, fallback to vterminal_key_pressed
+ vterminal_key_pressed(ldisc_to_tty(ldisc));
+
+ break;
+ }
}
/**
@@ -115,6 +252,18 @@ void ldisc_key_pressed(ldisc_t *ldisc, char c)
*/
size_t ldisc_get_current_line_raw(ldisc_t *ldisc, char *s)
{
- NOT_YET_IMPLEMENTED("DRIVERS: ldisc_get_current_line_raw");
- return 0;
+ // NOT_YET_IMPLEMENTED("DRIVERS: ldisc_get_current_line_raw");
+
+ // copy the raw part of the line discipline buffer into the buffer provided
+ size_t i = 0;
+ size_t j = ldisc->ldisc_cooked;
+ while (j != ldisc->ldisc_head)
+ {
+ s[i] = ldisc->ldisc_buffer[j];
+ j = (j + 1) % LDISC_BUFFER_SIZE;
+ i++;
+ }
+
+ // return the number of bytes copied
+ return i;
}
diff --git a/kernel/drivers/tty/tty.c b/kernel/drivers/tty/tty.c
index 3694877..c47a582 100644
--- a/kernel/drivers/tty/tty.c
+++ b/kernel/drivers/tty/tty.c
@@ -69,8 +69,29 @@ void tty_init()
*/
ssize_t tty_read(chardev_t *cdev, size_t pos, void *buf, size_t count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: tty_read");
- return -1;
+ // NOT_YET_IMPLEMENTED("DRIVERS: tty_read");
+
+ // get the mapped tty
+ tty_t *tty = cd_to_tty(cdev);
+
+ // set the IPL to INTR_KEYBOARD
+ uint8_t prev_ipl = intr_setipl(INTR_KEYBOARD);
+
+ // lock the read mutex of the tty
+ kmutex_lock(&tty->tty_read_mutex);
+
+ // wait until there is something in the line discipline's buffer
+ ldisc_wait_read(&tty->tty_ldisc);
+
+ // read from the ldisc's buffer if there are new characters
+ ssize_t bytes_read = ldisc_read(&tty->tty_ldisc, buf, count);
+ // unlock the read mutex of the tty
+ kmutex_unlock(&tty->tty_read_mutex);
+
+ // revert the IPL
+ intr_setipl(prev_ipl);
+
+ return bytes_read;
}
/**
@@ -88,8 +109,27 @@ ssize_t tty_read(chardev_t *cdev, size_t pos, void *buf, size_t count)
*/
ssize_t tty_write(chardev_t *cdev, size_t pos, const void *buf, size_t count)
{
- NOT_YET_IMPLEMENTED("DRIVERS: tty_write");
- return -1;
+ // NOT_YET_IMPLEMENTED("DRIVERS: tty_write");
+
+ // get the mapped tty
+ tty_t *tty = cd_to_tty(cdev);
+
+ // set the IPL to INTR_KEYBOARD
+ uint8_t prev_ipl = intr_setipl(INTR_KEYBOARD);
+
+ // lock the write mutex of the tty
+ kmutex_lock(&tty->tty_write_mutex);
+
+ // write to the terminal
+ size_t bytes_written = vterminal_write(&tty->tty_vterminal, buf, count);
+
+ // unlock the write mutex of the tty
+ kmutex_unlock(&tty->tty_write_mutex);
+ // revert the IPL
+ intr_setipl(prev_ipl);
+
+
+ return bytes_written;
}
static void tty_receive_char_multiplexer(uint8_t c)
diff --git a/kernel/main/kmain.c b/kernel/main/kmain.c
index b1402c5..0bca1c3 100644
--- a/kernel/main/kmain.c
+++ b/kernel/main/kmain.c
@@ -166,9 +166,20 @@ static void *initproc_run(long arg1, void *arg2)
// dbg(DBG_THR, "Thread: %s\n", thread->kt_proc->p_name);
// }
- proctest_main(0, NULL);
+ // proctest_main(0, NULL);
- dbg(DBG_PROC, "%s", "In main thread!\n");
+ // dbg(DBG_PROC, "%s", "In main thread!\n");
+
+#ifdef __DRIVERS__
+ char name[32] = {0};
+ for (long i = 0; i < __NTERMS__; i++)
+ {
+ snprintf(name, sizeof(name), "kshell%ld", i);
+ proc_t *proc = proc_create("ksh");
+ kthread_t *thread = kthread_create(proc, kshell_proc_run, i, NULL);
+ sched_make_runnable(thread);
+ }
+#endif
// see if there are any children to wait for
while (do_waitpid(-1, 0, 0) != -ECHILD)
diff --git a/kernel/proc/proc.c b/kernel/proc/proc.c
index a1f68f8..7ce42dc 100644
--- a/kernel/proc/proc.c
+++ b/kernel/proc/proc.c
@@ -216,7 +216,6 @@ proc_t *proc_create(const char *name)
proc->p_pproc = proc_initproc;
list_insert_tail(&curproc->p_children, &proc->p_child_link);
list_insert_tail(&proc_list, &proc->p_list_link);
-
dbg(DBG_PROC, "SUCESSFULLY created PROCESS name=%s & pid =%d\n", name, proc_pid);
return proc;
@@ -268,11 +267,11 @@ void proc_cleanup(long status)
// update state and status
curproc->p_state = PROC_DEAD;
- if (curthr->kt_cancelled) {
- curproc->p_status = curthr->kt_retval;
- } else {
+ // if (curthr->kt_cancelled) {
+ // curproc->p_status = curthr->kt_retval;
+ // } else {
curproc->p_status = status;
- }
+ // }
}
/*
@@ -337,7 +336,7 @@ void proc_kill_all()
{
if (p->p_pid != curproc->p_pid && p->p_pid != PID_IDLE)
{
- proc_kill(p, 0);
+ proc_kill(p, -1);
}
}
diff --git a/kernel/proc/sched.c b/kernel/proc/sched.c
index 31976bb..c8f209c 100644
--- a/kernel/proc/sched.c
+++ b/kernel/proc/sched.c
@@ -168,9 +168,17 @@ long sched_cancellable_sleep_on(ktqueue_t *queue)
curthr->kt_state = KT_SLEEP_CANCELLABLE;
+ if (curthr->kt_cancelled)
+ {
+ return -EINTR;
+ }
+
sched_switch(queue);
- // TODO: finish this function - consider the ipl_wait() function
+ if (curthr->kt_cancelled)
+ {
+ return -EINTR;
+ }
return 0;
}
diff --git a/kernel/test/proctest.c b/kernel/test/proctest.c
index ab69512..e8b8ba8 100644
--- a/kernel/test/proctest.c
+++ b/kernel/test/proctest.c
@@ -273,7 +273,6 @@ void test_out_of_order_termination()
"Expected: %d, Actual: %d number of processes have been cleaned up\n", 3, count);
}
-
/*
Test threads' cancellation fields.
*/
@@ -299,6 +298,7 @@ void test_cancellation()
int status;
int ret = do_waitpid(new_proc1->p_pid, &status, 0);
test_assert(ret != -ECHILD, "Should have found the process");
+ test_assert(ret == new_proc1->p_pid, "Should have found the correct process");
test_assert(status == 1, "Returned status not set correctly");
test_assert(did_run == 0, "Thread should not have run if it was cancelled");
}
diff --git a/kernel/util/debug.c b/kernel/util/debug.c
index b6ba72a..ba38c24 100644
--- a/kernel/util/debug.c
+++ b/kernel/util/debug.c
@@ -19,7 +19,7 @@
* always be the first thing in this variable. Note that this setting can be
* changed at runtime by modifying the dbg_modes global variable.
*/
-#define INIT_DBG_MODES "-all,test,print,thr,proc,sched"
+#define INIT_DBG_MODES "-all,test,print,disk"
/* Below is a truly terrible poll-driven serial driver that we use for debugging
* purposes - it outputs to COM1, but