diff options
author | dzwdz | 2022-08-28 14:53:48 +0200 |
---|---|---|
committer | dzwdz | 2022-08-28 14:53:48 +0200 |
commit | 96a1be7e79704d3d60324547b689f8dcdc357524 (patch) | |
tree | 17728f878af64669b16423e21a48b6bec1dc4d8e /src/kernel/arch/amd64/driver | |
parent | 83567c386e4a50cc4303d2c3966d7518331e129f (diff) |
kernel/driver: add postqueue_join / postqueue_pop
Diffstat (limited to 'src/kernel/arch/amd64/driver')
-rw-r--r-- | src/kernel/arch/amd64/driver/ps2.c | 15 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/rtl8139.c | 13 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/serial.c | 12 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/util.c | 17 | ||||
-rw-r--r-- | src/kernel/arch/amd64/driver/util.h | 4 |
5 files changed, 30 insertions, 31 deletions
diff --git a/src/kernel/arch/amd64/driver/ps2.c b/src/kernel/arch/amd64/driver/ps2.c index bac060e..196b890 100644 --- a/src/kernel/arch/amd64/driver/ps2.c +++ b/src/kernel/arch/amd64/driver/ps2.c @@ -63,16 +63,10 @@ void ps2_irq(void) { if (!(status & 1)) break; /* read while data available */ if (status & (1 << 5)) { ring_put1b((void*)&mouse_backlog, port_in8(PS2)); - if (mouse_queue) { - accept(mouse_queue); - mouse_queue = mouse_queue->postqueue_next; - } + postqueue_pop(&mouse_queue, accept); } else { ring_put1b((void*)&kb_backlog, port_in8(PS2)); - if (kb_queue) { - accept(kb_queue); - kb_queue = kb_queue->postqueue_next; - } + postqueue_pop(&kb_queue, accept); } } } @@ -85,10 +79,7 @@ enum { static void read_backlog(struct vfs_request *req, ring_t *r, struct vfs_request **queue) { if (ring_used(r) == 0) { - /* nothing to read, join queue */ - assert(!req->postqueue_next); - while (*queue) queue = &(*queue)->postqueue_next; - *queue = req; + postqueue_join(queue, req); } else if (req->caller) { int len = req->output.len; if (len < 0) len = 0; diff --git a/src/kernel/arch/amd64/driver/rtl8139.c b/src/kernel/arch/amd64/driver/rtl8139.c index 05a0f70..eb07494 100644 --- a/src/kernel/arch/amd64/driver/rtl8139.c +++ b/src/kernel/arch/amd64/driver/rtl8139.c @@ -1,4 +1,5 @@ #include <kernel/arch/amd64/driver/rtl8139.h> +#include <kernel/arch/amd64/driver/util.h> #include <kernel/arch/amd64/pci.h> #include <kernel/arch/amd64/port_io.h> #include <kernel/mem/virt.h> @@ -94,10 +95,7 @@ void rtl8139_irq(void) { /* bit 0 of cmd - Rx Buffer Empty * not a do while() because sometimes the bit is empty on IRQ. no clue why. */ while (!(port_in8(iobase + CMD) & 1)) { - if (blocked_on) { - accept(blocked_on); - blocked_on = blocked_on->postqueue_next; - } else { + if (!postqueue_pop(&blocked_on, accept)) { rx_irq_enable(false); break; } @@ -177,12 +175,7 @@ static void accept(struct vfs_request *req) { case VFSOP_READ: ret = try_rx(req->caller->pages, req->output.buf, req->output.len); if (ret == WAIT) { - // TODO this is a pretty common pattern in drivers, try to make it unneeded - // TODO those asserts should actually be regular panic checks - assert(!req->postqueue_next); - struct vfs_request **slot = &blocked_on; - while (*slot) slot = &(*slot)->postqueue_next; - *slot = req; + postqueue_join(&blocked_on, req); rx_irq_enable(true); } else { vfsreq_finish_short(req, ret); diff --git a/src/kernel/arch/amd64/driver/serial.c b/src/kernel/arch/amd64/driver/serial.c index 9ddb355..2b0812b 100644 --- a/src/kernel/arch/amd64/driver/serial.c +++ b/src/kernel/arch/amd64/driver/serial.c @@ -1,4 +1,5 @@ #include <kernel/arch/amd64/driver/serial.h> +#include <kernel/arch/amd64/driver/util.h> #include <kernel/arch/amd64/interrupts/irq.h> #include <kernel/arch/amd64/port_io.h> #include <kernel/mem/virt.h> @@ -43,10 +44,7 @@ void serial_preinit(void) { void serial_irq(void) { ring_put1b((void*)&backlog, port_in8(COM1)); - if (blocked_on) { - accept(blocked_on); - blocked_on = blocked_on->postqueue_next; - } + postqueue_pop(&blocked_on, accept); } @@ -71,11 +69,7 @@ static void accept(struct vfs_request *req) { break; case VFSOP_READ: if (ring_used((void*)&backlog) == 0) { - /* nothing to read, join queue */ - assert(!req->postqueue_next); - struct vfs_request **slot = &blocked_on; - while (*slot) slot = &(*slot)->postqueue_next; - *slot = req; + postqueue_join(&blocked_on, req); } else if (req->caller) { ret = ring_to_virt((void*)&backlog, req->caller->pages, req->output.buf, req->output.len); // TODO output.len can overflow here diff --git a/src/kernel/arch/amd64/driver/util.c b/src/kernel/arch/amd64/driver/util.c index 11aecca..4eeaa0d 100644 --- a/src/kernel/arch/amd64/driver/util.c +++ b/src/kernel/arch/amd64/driver/util.c @@ -15,3 +15,20 @@ int req_readcopy(struct vfs_request *req, const void *buf, size_t len) { /* read errors are ignored. TODO write a spec */ return req->output.len; } + +void postqueue_join(struct vfs_request **queue, struct vfs_request *req) { + if (req->postqueue_next) + panic_invalid_state(); + + while (*queue) + queue = &(*queue)->postqueue_next; + *queue = req; +} + +bool postqueue_pop(struct vfs_request **queue, void (*accept)(struct vfs_request *)) { + struct vfs_request *req = *queue; + if (req == NULL) return false; + *queue = req->postqueue_next; + accept(req); + return true; +} diff --git a/src/kernel/arch/amd64/driver/util.h b/src/kernel/arch/amd64/driver/util.h index c91605c..d89992a 100644 --- a/src/kernel/arch/amd64/driver/util.h +++ b/src/kernel/arch/amd64/driver/util.h @@ -1,4 +1,5 @@ #pragma once +#include <stdbool.h> #include <stddef.h> struct vfs_request; @@ -10,3 +11,6 @@ int req_readcopy(struct vfs_request *req, const void *buf, size_t len); (req->input.kern && \ req->input.len == plen && \ memcmp(req->input.buf_kern, path, plen) == 0) + +void postqueue_join(struct vfs_request **queue, struct vfs_request *req); +bool postqueue_pop(struct vfs_request **queue, void (*accept)(struct vfs_request *)); |