diff options
author | sotech117 <michael_foiani@brown.edu> | 2024-03-02 23:05:26 +0000 |
---|---|---|
committer | sotech117 <michael_foiani@brown.edu> | 2024-03-02 23:05:26 +0000 |
commit | 8c2e0ce946012a4275e8dfa9d8dfd1d5a68d6e3e (patch) | |
tree | 1877a33c6488a5b16fb7962e1ffb0f72f13a5052 | |
parent | 9c90e73fda0d5df2e1f11b32d459d3bb07a63192 (diff) |
decent coding session
-rw-r--r-- | Config.mk | 2 | ||||
-rw-r--r-- | kernel/drivers/disk/sata.c | 40 | ||||
-rw-r--r-- | kernel/drivers/memdevs.c | 60 | ||||
-rw-r--r-- | kernel/drivers/tty/ldisc.c | 165 | ||||
-rw-r--r-- | kernel/drivers/tty/tty.c | 48 | ||||
-rw-r--r-- | kernel/main/kmain.c | 15 | ||||
-rw-r--r-- | kernel/proc/proc.c | 11 | ||||
-rw-r--r-- | kernel/proc/sched.c | 10 | ||||
-rw-r--r-- | kernel/test/proctest.c | 2 | ||||
-rw-r--r-- | kernel/util/debug.c | 2 |
10 files changed, 322 insertions, 33 deletions
@@ -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 |