From e6416905c4afb34e61276cdc07c44813a3ebc5e7 Mon Sep 17 00:00:00 2001 From: Minep Date: Wed, 9 Nov 2022 18:44:24 +0000 Subject: [PATCH] fix: use wait queue for blocking process test: regression on the async io feature. refactor: centeralize process state changing. --- lunaix-os/hal/ahci/ahci.c | 20 +++++++++++--------- lunaix-os/hal/ahci/atapi.c | 2 +- lunaix-os/includes/lunaix/blkio.h | 7 +++++-- lunaix-os/includes/lunaix/buffer.h | 4 ++++ lunaix-os/includes/lunaix/process.h | 6 ++++++ lunaix-os/kernel/block/blkio.c | 9 ++++++++- lunaix-os/kernel/block/block.c | 27 ++++++++++++++++++++++++--- lunaix-os/kernel/ds/buffer.c | 7 +++---- lunaix-os/kernel/ds/waitq.c | 3 +-- lunaix-os/kernel/process/sched.c | 3 ++- 10 files changed, 65 insertions(+), 23 deletions(-) diff --git a/lunaix-os/hal/ahci/ahci.c b/lunaix-os/hal/ahci/ahci.c index c9f8297..21ccf56 100644 --- a/lunaix-os/hal/ahci/ahci.c +++ b/lunaix-os/hal/ahci/ahci.c @@ -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); diff --git a/lunaix-os/hal/ahci/atapi.c b/lunaix-os/hal/ahci/atapi.c index b6d41fa..26ad533 100644 --- a/lunaix-os/hal/ahci/atapi.c +++ b/lunaix-os/hal/ahci/atapi.c @@ -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); } diff --git a/lunaix-os/includes/lunaix/blkio.h b/lunaix-os/includes/lunaix/blkio.h index 3814917..07b53ac 100644 --- a/lunaix-os/includes/lunaix/blkio.h +++ b/lunaix-os/includes/lunaix/blkio.h @@ -3,14 +3,16 @@ #include #include +#include #include #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; diff --git a/lunaix-os/includes/lunaix/buffer.h b/lunaix-os/includes/lunaix/buffer.h index 605cf8b..851d568 100644 --- a/lunaix-os/includes/lunaix/buffer.h +++ b/lunaix-os/includes/lunaix/buffer.h @@ -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; diff --git a/lunaix-os/includes/lunaix/process.h b/lunaix-os/includes/lunaix/process.h index c014443..7674a92 100644 --- a/lunaix-os/includes/lunaix/process.h +++ b/lunaix-os/includes/lunaix/process.h @@ -93,6 +93,12 @@ struct proc_info extern volatile struct proc_info* __current; +static inline void +block_current() +{ + __current->state = PS_BLOCKED; +} + /** * @brief 分配并初始化一个进程控制块 * diff --git a/lunaix-os/kernel/block/blkio.c b/lunaix-os/kernel/block/blkio.c index 44531c4..bc0178c 100644 --- a/lunaix-os/kernel/block/blkio.c +++ b/lunaix-os/kernel/block/blkio.c @@ -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); } diff --git a/lunaix-os/kernel/block/block.c b/lunaix-os/kernel/block/block.c index e25cf42..7f1b0dd 100644 --- a/lunaix-os/kernel/block/block.c +++ b/lunaix-os/kernel/block/block.c @@ -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; } diff --git a/lunaix-os/kernel/ds/buffer.c b/lunaix-os/kernel/ds/buffer.c index 0efea6f..7b277c8 100644 --- a/lunaix-os/kernel/ds/buffer.c +++ b/lunaix-os/kernel/ds/buffer.c @@ -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; diff --git a/lunaix-os/kernel/ds/waitq.c b/lunaix-os/kernel/ds/waitq.c index 0d643d0..4b5abfd 100644 --- a/lunaix-os/kernel/ds/waitq.c +++ b/lunaix-os/kernel/ds/waitq.c @@ -10,8 +10,7 @@ pwait(waitq_t* queue) llist_append(&queue->waiters, ¤t_wq->waiters); - // FIXME centralize the state change. - __current->state = PS_BLOCKED; + block_current(); sched_yieldk(); } diff --git a/lunaix-os/kernel/process/sched.c b/lunaix-os/kernel/process/sched.c index 4e3f290..caec0e6 100644 --- a/lunaix-os/kernel/process/sched.c +++ b/lunaix-os/kernel/process/sched.c @@ -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(); } -- 2.27.0