summaryrefslogtreecommitdiff
path: root/src/kernel/arch
diff options
context:
space:
mode:
authordzwdz2022-08-28 14:53:48 +0200
committerdzwdz2022-08-28 14:53:48 +0200
commit96a1be7e79704d3d60324547b689f8dcdc357524 (patch)
tree17728f878af64669b16423e21a48b6bec1dc4d8e /src/kernel/arch
parent83567c386e4a50cc4303d2c3966d7518331e129f (diff)
kernel/driver: add postqueue_join / postqueue_pop
Diffstat (limited to 'src/kernel/arch')
-rw-r--r--src/kernel/arch/amd64/driver/ps2.c15
-rw-r--r--src/kernel/arch/amd64/driver/rtl8139.c13
-rw-r--r--src/kernel/arch/amd64/driver/serial.c12
-rw-r--r--src/kernel/arch/amd64/driver/util.c17
-rw-r--r--src/kernel/arch/amd64/driver/util.h4
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 *));