fix: use wait queue for blocking process
authorMinep <zelong56@gmail.com>
Wed, 9 Nov 2022 18:44:24 +0000 (18:44 +0000)
committerMinep <zelong56@gmail.com>
Wed, 9 Nov 2022 18:49:24 +0000 (18:49 +0000)
test: regression on the async io feature.
refactor: centeralize process state changing.

lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/ahci/atapi.c
lunaix-os/includes/lunaix/blkio.h
lunaix-os/includes/lunaix/buffer.h
lunaix-os/includes/lunaix/process.h
lunaix-os/kernel/block/blkio.c
lunaix-os/kernel/block/block.c
lunaix-os/kernel/ds/buffer.c
lunaix-os/kernel/ds/waitq.c
lunaix-os/kernel/process/sched.c

index c9f8297bf42b4f14bd58c0264d12d9b253829dcb..21ccf56c90a4087fe96c9325fa6618f60689219a 100644 (file)
@@ -27,6 +27,8 @@
 #define HBA_FIS_SIZE 256
 #define HBA_CLB_SIZE 1024
 
+#define HBA_MY_IE (HBA_PxINTR_DHR | HBA_PxINTR_TFEE)
+
 // #define DO_HBA_FULL_RESET
 
 LOG_MODULE("AHCI")
@@ -287,7 +289,7 @@ sata_create_fis(struct sata_reg_fis* cmd_fis,
 int
 hba_bind_sbuf(struct hba_cmdh* cmdh, struct hba_cmdt* cmdt, struct membuf mbuf)
 {
-    assert_msg(mbuf.buffer <= 0x400000, "HBA: Buffer too big");
+    assert_msg(mbuf.size <= 0x400000, "HBA: Buffer too big");
     cmdh->prdt_len = 1;
     cmdt->entries[0] = (struct hba_prdte){ .data_base = vmm_v2p(mbuf.buffer),
                                            .byte_count = mbuf.size - 1 };
@@ -297,17 +299,17 @@ int
 hba_bind_vbuf(struct hba_cmdh* cmdh, struct hba_cmdt* cmdt, struct vecbuf* vbuf)
 {
     size_t i = 0;
-    struct vecbuf *pos, *n;
+    struct vecbuf* pos = vbuf;
 
-    llist_for_each(pos, n, &vbuf->components, components)
-    {
+    do {
         assert_msg(i < HBA_MAX_PRDTE, "HBA: Too many PRDTEs");
-        assert_msg(pos->buf.buffer <= 0x400000, "HBA: Buffer too big");
+        assert_msg(pos->buf.size <= 0x400000, "HBA: Buffer too big");
 
         cmdt->entries[i++] =
           (struct hba_prdte){ .data_base = vmm_v2p(pos->buf.buffer),
                               .byte_count = pos->buf.size - 1 };
-    }
+        pos = list_entry(pos->components.next, struct vecbuf, components);
+    } while (pos != vbuf);
 
     cmdh->prdt_len = i + 1;
 }
@@ -345,7 +347,7 @@ ahci_init_device(struct hba_port* port)
     struct hba_cmdh* cmd_header;
 
     // mask DHR interrupt
-    port->regs[HBA_RPxIE] &= ~HBA_PxINTR_DHR;
+    port->regs[HBA_RPxIE] &= ~HBA_MY_IE;
 
     // 预备DMA接收缓存,用于存放HBA传回的数据
     uint16_t* data_in = (uint16_t*)valloc_dma(512);
@@ -434,7 +436,7 @@ ahci_init_device(struct hba_port* port)
 
 done:
     // reset interrupt status and unmask D2HR interrupt
-    port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR;
+    port->regs[HBA_RPxIE] |= HBA_MY_IE;
     achi_register_ops(port);
 
     vfree_dma(data_in);
@@ -443,7 +445,7 @@ done:
     return 1;
 
 fail:
-    port->regs[HBA_RPxIE] |= HBA_PxINTR_DHR;
+    port->regs[HBA_RPxIE] |= HBA_MY_IE;
     vfree_dma(data_in);
     vfree_dma(cmd_table);
 
index b6d41fa6005020d071ab48d02905544c4347df5f..26ad5332aca66cf8c623a7c70c3ecd6e8220eb77 100644 (file)
@@ -77,7 +77,7 @@ scsi_submit(struct hba_device* dev, struct blkio_req* io_req)
     } else {
         scsi_create_packet12((struct scsi_cdb12*)cdb,
                              write ? SCSI_WRITE_BLOCKS_12 : SCSI_READ_BLOCKS_12,
-                             io_req->blk_addr,
+                             io_req->blk_addr & -1,
                              count);
     }
 
index 3814917171a533568c307962c7364f052049756c..07b53ac4ce1ca6276b31e995659789a6ff6170ed 100644 (file)
@@ -3,14 +3,16 @@
 
 #include <lunaix/buffer.h>
 #include <lunaix/ds/llist.h>
+#include <lunaix/ds/waitq.h>
 #include <lunaix/types.h>
 
 #define BLKIO_WRITE 0x1
 #define BLKIO_ERROR 0x2
 
-// Free on complete
 #define BLKIO_BUSY 0x4
 #define BLKIO_PENDING 0x8
+
+// Free on complete
 #define BLKIO_FOC 0x10
 
 #define BLKIO_SCHED_IDEL 0x1
@@ -24,8 +26,9 @@ struct blkio_req
 {
     struct llist_header reqs;
     struct blkio_context* io_ctx;
-    u32_t flags;
     struct vecbuf* vbuf;
+    u32_t flags;
+    waitq_t wait;
     u64_t blk_addr;
     void* evt_args;
     blkio_cb completed;
index 605cf8b47602e62fdcbe35bf1d864be022e7a15c..851d56844f3fd6854904c5e36da197f0818c453b 100644 (file)
@@ -40,6 +40,10 @@ vbuf_alloc(struct vecbuf* vec, void* buf, size_t len);
 static inline size_t
 vbuf_size(struct vecbuf* vbuf)
 {
+    if (!vbuf) {
+        return 0;
+    }
+
     struct vecbuf* last =
       list_entry(vbuf->components.prev, struct vecbuf, components);
     return last->acc_sz;
index c014443089bb557b35991bb7f1968c3873123a7b..7674a925ab182dc7b90bfa9f41cff7c59f3d663a 100644 (file)
@@ -93,6 +93,12 @@ struct proc_info
 
 extern volatile struct proc_info* __current;
 
+static inline void
+block_current()
+{
+    __current->state = PS_BLOCKED;
+}
+
 /**
  * @brief 分配并初始化一个进程控制块
  *
index 44531c4091636ef09309db1e6dc59135b553d767..bc0178c1be562c014fbee93b19979f94e7219c5c 100644 (file)
@@ -24,6 +24,7 @@ __blkio_req_create(struct vecbuf* buffer,
                                 .flags = options,
                                 .evt_args = evt_args };
     breq->vbuf = buffer;
+    waitq_init(&breq->wait);
     return breq;
 }
 
@@ -76,7 +77,7 @@ blkio_commit(struct blkio_context* ctx, struct blkio_req* req)
     llist_append(&ctx->queue, &req->reqs);
 
     // if the pipeline is not running (e.g., stalling). Then we should schedule
-    // one immediately and kick it start.
+    // one immediately and kick it started.
     if (!ctx->busy) {
         blkio_schedule(ctx);
     }
@@ -102,9 +103,15 @@ void
 blkio_complete(struct blkio_req* req)
 {
     req->flags &= ~(BLKIO_BUSY | BLKIO_PENDING);
+
     if (req->completed) {
         req->completed(req);
     }
+
+    // Wake all blocked processes on completion,
+    //  albeit should be no more than one process in everycase (by design)
+    pwake_all(&req->wait);
+
     if ((req->flags & BLKIO_FOC)) {
         blkio_free_req(req);
     }
index e25cf42ad3d0593c0365cf84a496749229a0a2e9..7f1b0ddc8489f7f9b0b8049c791677d609da48e1 100644 (file)
@@ -34,6 +34,7 @@ __block_register(struct block_dev* dev);
 void
 block_init()
 {
+    blkio_init();
     lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
     dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
     free_slot = 0;
@@ -48,6 +49,10 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len)
     size_t bsize = bdev->blk_size, rd_block = offset / bsize,
            r = offset % bsize, rd_size = 0;
 
+    if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
+        return 0;
+    }
+
     struct vecbuf* vbuf = vbuf_alloc(NULL, buf, len);
     struct blkio_req* req;
     void* tmp_buf = NULL;
@@ -63,10 +68,14 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len)
 
     req = blkio_vrd(vbuf, rd_block, NULL, NULL, 0);
     blkio_commit(bdev->blkio, req);
-    wait_if(req->flags & BLKIO_PENDING);
+
+    pwait(&req->wait);
 
     if (!(errno = req->errcode)) {
         memcpy(buf, tmp_buf + r, rd_size);
+        errno = len;
+    } else {
+        errno = -errno;
     }
 
     if (tmp_buf) {
@@ -85,6 +94,10 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len)
     size_t bsize = bdev->blk_size, rd_block = offset / bsize,
            r = offset % bsize;
 
+    if (!(len = MIN(len, ((size_t)bdev->end_lba - rd_block + 1) * bsize))) {
+        return 0;
+    }
+
     struct vecbuf* vbuf = vbuf_alloc(NULL, buf, len);
     struct blkio_req* req;
     void* tmp_buf = NULL;
@@ -101,9 +114,15 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len)
 
     req = blkio_vwr(vbuf, rd_block, NULL, NULL, 0);
     blkio_commit(bdev->blkio, req);
-    wait_if(req->flags & BLKIO_PENDING);
+
+    pwait(&req->wait);
 
     int errno = req->errcode;
+    if (!errno) {
+        errno = len;
+    } else {
+        errno = -errno;
+    }
 
     if (tmp_buf) {
         vfree(tmp_buf);
@@ -118,11 +137,13 @@ struct block_dev*
 block_alloc_dev(const char* blk_id, void* driver, req_handler ioreq_handler)
 {
     struct block_dev* bdev = cake_grab(lbd_pile);
-    *bdev = (struct block_dev){ .driver = driver };
+    memset(bdev, 0, sizeof(struct block_dev));
 
     strncpy(bdev->name, blk_id, PARTITION_NAME_SIZE);
 
     bdev->blkio = blkio_newctx(ioreq_handler);
+    bdev->driver = driver;
+    bdev->blkio->driver = driver;
 
     return bdev;
 }
index 0efea6fe054d7b67e3f699f95e74b90417fea722..7b277c8c768f142bc3881b48c617095c80fce69f 100644 (file)
@@ -6,14 +6,13 @@ vbuf_alloc(struct vecbuf* vec, void* buf, size_t size)
 {
     struct vecbuf* vbuf = valloc(sizeof(struct vecbuf));
 
-    *vbuf =
-      (struct vecbuf){ .buf = { .buffer = buf, .size = size }, .acc_sz = 0 };
+    *vbuf = (struct vecbuf){ .buf = { .buffer = buf, .size = size },
+                             .acc_sz = vbuf_size(vec) + size };
 
     if (vec) {
-        vbuf->acc_sz = vbuf_size(vec) + size;
         llist_append(&vec->components, &vbuf->components);
     } else {
-        llist_init_head(&vec->components);
+        llist_init_head(&vbuf->components);
     }
 
     return vbuf;
index 0d643d02e7de3649d4da25d50c7b9d41258cc4c1..4b5abfd89055024a75bd4f220c808ef9c0b14e33 100644 (file)
@@ -10,8 +10,7 @@ pwait(waitq_t* queue)
 
     llist_append(&queue->waiters, &current_wq->waiters);
 
-    // FIXME centralize the state change.
-    __current->state = PS_BLOCKED;
+    block_current();
     sched_yieldk();
 }
 
index 4e3f290c4ca61e36699988c9f77f899d567c3bf7..caec0e67cd05acd8d6ea26bf1d828eaed2f35b64 100644 (file)
@@ -172,7 +172,8 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
     llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers);
 
     __current->intr_ctx.registers.eax = seconds;
-    __current->state = PS_BLOCKED;
+
+    block_current();
     schedule();
 }