From 5f21444c129a49a8c264e9877e7225841cc6afd6 Mon Sep 17 00:00:00 2001 From: acevest Date: Wed, 18 Oct 2023 09:35:51 +0800 Subject: [PATCH] =?utf8?q?=E5=88=9D=E6=AD=A5=E6=B7=BB=E5=8A=A0=20buffer=20?= =?utf8?q?=E7=9B=B8=E5=85=B3=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit --- drivers/block.c | 17 +--- drivers/console.c | 27 +++++- fs/buffer.c | 203 +++++++++++++++++++++++++++++++++++++++++++ include/buffer.h | 19 ++++ include/completion.h | 4 +- include/disk.h | 8 -- include/fs.h | 10 --- include/list.h | 2 + include/semaphore.h | 6 +- include/wait.h | 6 +- kernel/buffer.c | 14 --- kernel/completion.c | 7 +- kernel/semaphore.c | 9 ++ kernel/setup.c | 3 + kernel/wait.c | 144 ++++++++++++++++-------------- 15 files changed, 357 insertions(+), 122 deletions(-) create mode 100644 fs/buffer.c delete mode 100644 kernel/buffer.c diff --git a/drivers/block.c b/drivers/block.c index baacea9..674e57e 100644 --- a/drivers/block.c +++ b/drivers/block.c @@ -7,22 +7,13 @@ * ------------------------------------------------------------------------ */ +#include #include #include #include -#define BLOCK_BUFFER_HASH_TABLE_SIZE 37 -atomic_t hash_cnt; -blk_buffer_t *block_buffer_hash_table[BLOCK_BUFFER_HASH_TABLE_SIZE] = { - 0, -}; - -int hash(dev_t dev, uint32_t block) { return ((~dev) ^ block) % BLOCK_BUFFER_HASH_TABLE_SIZE; } - -blk_buffer_t *get_hash_block_buffer(dev_t dev, uint32_t block, uint16_t size) {} - -blk_buffer_t *block_read(dev_t dev, uint32_t block) { - blk_buffer_t *bb = 0; +bbuffer_t *block_read(dev_t dev, uint32_t block) { + bbuffer_t *bb = 0; assert(DEV_MAJOR(dev) == DEV_MAJOR_DISK); // assert(DEV_MINOR(dev) == 1); @@ -51,7 +42,7 @@ void ata_read_ext2_sb() { const int size = offset + 1024; const int block = 1; - blk_buffer_t *bb = block_read(system.root_dev, block); + bbuffer_t *bb = block_read(system.root_dev, block); ext2_sb_t *p = (ext2_sb_t *)(bb->data + offset); printk("inodes count %u inodes per group %u free %u\n", p->s_inodes_count, p->s_inodes_per_group, diff --git a/drivers/console.c b/drivers/console.c index c186740..85dcfe8 100644 --- a/drivers/console.c +++ b/drivers/console.c @@ -9,6 +9,7 @@ #include #include +#include #include #include #include @@ -56,13 +57,14 @@ static void cnsl_queue_init(cnsl_queue_t *cq) { init_wait_queue_head(&cq->wait); } -wait_queue_head_t rdwq; - +// wait_queue_head_t rdwq; +semaphore_t sem; void cnsl_init() { cnsl_queue_init(&cnsl.rd_q); cnsl_queue_init(&cnsl.wr_q); cnsl_queue_init(&cnsl.sc_q); - init_wait_queue_head(&rdwq); + // init_wait_queue_head(&rdwq); + semaphore_init(&sem, 0); } int cnsl_kbd_write(char ch) { @@ -87,7 +89,8 @@ int cnsl_kbd_write(char ch) { clear(&cnsl.wr_q); return 0; // TODO FIX while (get(&cnsl.sc_q, &ch)) put(&cnsl.rd_q, ch); - wake_up(&rdwq); + // wake_up(&rdwq); + up(&sem); } } @@ -98,6 +101,21 @@ int cnsl_read(char *buf, size_t count) { int cnt = 0; for (cnt = 0; cnt < count;) { char ch; +#if 1 + while (true) { + down(&sem); + + bool r = get(&cnsl.rd_q, &ch); + if (r) { + buf[cnt++] = ch; + if (ch == '\n') { + goto end; + } + } else { + break; + } + } +#else task_union *task = current; DECLARE_WAIT_QUEUE(wait, task); add_wait_queue(&rdwq, &wait); @@ -121,6 +139,7 @@ int cnsl_read(char *buf, size_t count) { schedule(); } +#endif } end: diff --git a/fs/buffer.c b/fs/buffer.c new file mode 100644 index 0000000..a5f0777 --- /dev/null +++ b/fs/buffer.c @@ -0,0 +1,203 @@ +/* + * ------------------------------------------------------------------------ + * File Name: buffer.c + * Author: Zhao Yanbai + * 2023-06-20 19:30:33 Tuesday CST + * Description: 目前只支持只读,因此可以先写得简单一点 + * ------------------------------------------------------------------------ + */ + +#include +#include + +#define MAX_BBUFFER_CNT 985 + +#define BLOCK_BUFFER_HASH_TABLE_SIZE 211 +// atomic_t hash_cnt; +list_head_t block_buffer_hash_table[BLOCK_BUFFER_HASH_TABLE_SIZE] = { + 0, +}; + +int hashfn(dev_t dev, uint32_t block) { return ((dev) ^ block) % BLOCK_BUFFER_HASH_TABLE_SIZE; } + +typedef struct bbuffer_store { + int blocksize; + // list_head_t cache_list; + list_head_t free_list; +} bbuffer_store_t; + +// 1024, 2048, 4096 +bbuffer_store_t store[3] = {0}; + +kmem_cache_t *bbufer_kmem_cache = 0; + +bbuffer_store_t *getstore(uint32_t size) { + assert(size == 1024 || size == 2048 || size == 4096); + + bbuffer_store_t *s = 0; + + if (1024 == size) { + s = store + 0; + } else if (2048 == size) { + s = store + 1; + } else if (4096 == size) { + s = store + 2; + } + + assert(0 != s); + + return s; +} + +bbuffer_t *get_from_hash_table(dev_t dev, uint64_t block, uint32_t size) { + list_head_t *p = 0; + uint32_t hash = hashfn(dev, block); + assert(hash < BLOCK_BUFFER_HASH_TABLE_SIZE); + list_for_each(p, block_buffer_hash_table + hash) { + bbuffer_t *b = list_entry(p, bbuffer_t, node); + if (b->dev != dev) { + continue; + } + + if (b->block != block) { + continue; + } + + assert(b->block_size == size); + + break; + } + + // 如果找到了就直接返回 + if (0 != p) { + bbuffer_t *b = list_entry(p, bbuffer_t, node); + atomic_inc(&b->ref_count); + assert(0 != b); + assert(0 != b->data); + + // 等待buffer的lock释放 + // wait on b + return b; + } + + return NULL; +} + +bbuffer_t *getblk(dev_t dev, uint64_t block, uint32_t size) { + assert(size == 1024 || size == 2048 || size == 4096); + + // 暂时先只支持hard disk + assert(DEV_MAJOR(dev) == DEV_MAJOR_DISK); + + int retry = 0; +again: + uint32_t iflags; + irq_save(iflags); + + // 先尝试从hash里分配 + bbuffer_t *b = get_from_hash_table(dev, block, size); + if (NULL != b) { + return b; + } + + // 如果没找到,则从store的free_list里尝试找到第一个ref_count == 0 且未上锁的 + bbuffer_store_t *s = getstore(size); + list_head_t *p = 0; + list_for_each(p, &s->free_list) { + bbuffer_t *t = list_entry(p, bbuffer_t, node); + assert(NULL != t); + assert(t->block_size == size); + + if (t->ref_count == 0 && t->locked == 0) { + b = t; + break; + } + } + + // 如果还是没有找到,则就需要等待释放出新的空间 + if (b == NULL) { + irq_restore(iflags); + retry++; + // wait on free list + // ... + goto again; + } + + // 此时b->locked不一定为0 + // 因为可能有的进程调用了write、read后再直接调用brelse + // 虽然此时ref_count为0,但io操作标记的b->locked并未结束 + // 所以需要在此等待其结束 + while (b->locked == 1) { + // 此时是不用担心wake_up在这个sleep_on之前调用 + } + + // 找到了 + b->block = block; + b->block_size = size; + b->dev = dev; + b->ref_count = 1; + b->uptodate = 0; + + list_init(&b->node); + + irq_restore(iflags); + + return b; +} + +bbuffer_t *bread(dev_t dev, uint64_t block, uint32_t size) { + bbuffer_t *b = getblk(dev, block, size); + + return b; +} + +void init_buffer() { + for (int i = 0; i < BLOCK_BUFFER_HASH_TABLE_SIZE; i++) { + list_init(block_buffer_hash_table + i); + } + + bbufer_kmem_cache = kmem_cache_create("bbuffer", sizeof(bbuffer_t), 4); + if (NULL == bbufer_kmem_cache) { + panic("no memory for bbufer kmem cache"); + } + + printk("bbufer kmem cache %08x\n", bbufer_kmem_cache); + printk("SIZE %u\n", sizeof(bbuffer_t)); + + for (int i = 0; i < 3; i++) { + int blocksize = 1 << (10 + i); + + store[i].blocksize = blocksize; + // list_init(&store[i].cache_list); + list_init(&store[i].free_list); + + int page_left_space = 0; + void *data = NULL; + page_t *page = NULL; + for (int j = 0; j < MAX_BBUFFER_CNT; j++) { + if (page_left_space < blocksize) { + data = (void *)(alloc_one_page(0)); + page = va2page(data); + } + + bbuffer_t *b = kmem_cache_alloc(bbufer_kmem_cache, 0); + assert(NULL != b); + + b->block = 0; + b->block_size = blocksize; + b->ref_count = 0; + b->data = data + j * blocksize; + b->dev = 0; + b->page = page; + b->uptodate = 0; + b->locked = 0; + list_init(&b->node); + + assert(NULL != b->data); + + list_add(&b->node, &store[i].free_list); + + page_left_space -= blocksize; + } + } +} diff --git a/include/buffer.h b/include/buffer.h index fe84e13..8f570cc 100644 --- a/include/buffer.h +++ b/include/buffer.h @@ -8,3 +8,22 @@ */ #pragma once + +#include +#include +#include +#include +#include + +typedef struct bbuffer { + uint32_t block; // block number + void *data; // + atomic_t ref_count; + dev_t dev; + page_t *page; + list_head_t node; + uint16_t block_size; // block size + uint16_t uptodate : 1; + uint16_t locked : 1; + uint16_t dirt : 1; // 还不支持 +} bbuffer_t; diff --git a/include/completion.h b/include/completion.h index db085be..291f73a 100644 --- a/include/completion.h +++ b/include/completion.h @@ -9,6 +9,7 @@ #pragma once +#if 0 #include typedef struct completion { @@ -22,4 +23,5 @@ typedef struct completion { void wait_completion(completion_t *x); void init_completion(completion_t *x); -void complete(completion_t *x); \ No newline at end of file +void complete(completion_t *x); +#endif diff --git a/include/disk.h b/include/disk.h index 5c38949..751b5c9 100644 --- a/include/disk.h +++ b/include/disk.h @@ -26,14 +26,6 @@ typedef struct disk_request { void *buf; // 到的缓冲区 disk_request_cmd_t command; // 命令 list_head_t list; - // // wait_queue_head_t wait; // 等待队列 - // // 驱动器完全有可能在进程在进程睡眠到等待队列前返回数据并执行唤醒操作 - // // 这时等待队列上无进程,就相当于不执行任何操作 - // // 然后进程再睡眠到等待队列上,就会造成永远无法唤醒该进程 - // // 因此要添加一个字段,标志驱动器已经对该请求做过唤醒操作 - // // 进程在睡眠前需要检查该字段 - // // int done; - // completion_t completion; semaphore_t sem; } disk_request_t; diff --git a/include/fs.h b/include/fs.h index b84216f..7750690 100644 --- a/include/fs.h +++ b/include/fs.h @@ -109,14 +109,4 @@ static inline pInode find_empty_inode() typedef uint32_t dev_t; -typedef struct blk_buffer { - uint32_t block; // block number - char *data; // - uint16_t block_size; // block size - dev_t dev; - page_t *page; - struct blk_buffer *next; - struct blk_buffer *hash_next; -} blk_buffer_t; - #endif //_FS_H diff --git a/include/list.h b/include/list.h index 8ee3395..e995408 100644 --- a/include/list.h +++ b/include/list.h @@ -69,3 +69,5 @@ static inline void list_del_init(list_head_t *entry) { } static inline int list_empty(list_head_t *head) { return head->next == head; } + +static inline void list_init(list_head_t *head) { INIT_LIST_HEAD(head); } diff --git a/include/semaphore.h b/include/semaphore.h index 7f29c1a..27eb009 100644 --- a/include/semaphore.h +++ b/include/semaphore.h @@ -26,11 +26,13 @@ void semaphore_init(semaphore_t *s, unsigned int v); // down // 如果s->cnt > 0不会立即重新调度进程 // 如果s->cnt == 0 会重新调度进程 -void down(semaphore_t *s); +volatile void down(semaphore_t *s); + +// volatile bool try_down(semaphore_t *s); // up // 只会唤醒进程,但不会立即重新调度进程 -void up(semaphore_t *s); +volatile void up(semaphore_t *s); typedef semaphore_t mutex_t; diff --git a/include/wait.h b/include/wait.h index c54c014..8f29e93 100644 --- a/include/wait.h +++ b/include/wait.h @@ -43,9 +43,9 @@ void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq); // prepare_to_wait 不会调用schedule void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state); -void __end_wait(wait_queue_head_t *head, wait_queue_t *wq); +void __end_wait(wait_queue_t *wq); -void sleep_on(wait_queue_head_t *head); +// void sleep_on(wait_queue_head_t *head); void wake_up(wait_queue_head_t *head); void schedule(); @@ -59,7 +59,7 @@ void schedule(); } \ schedule(); \ } \ - __end_wait(head, &__wait); \ + __end_wait(&__wait); \ } while (0) #define wait_event(head, condition) \ diff --git a/kernel/buffer.c b/kernel/buffer.c deleted file mode 100644 index 18b7c9b..0000000 --- a/kernel/buffer.c +++ /dev/null @@ -1,14 +0,0 @@ -/* - * ------------------------------------------------------------------------ - * File Name: buffer.c - * Author: Zhao Yanbai - * 2023-06-20 19:30:33 Tuesday CST - * Description: none - * ------------------------------------------------------------------------ - */ - -typedef struct buffer { - // -} buffer_t; - -void init_buffer() {} diff --git a/kernel/completion.c b/kernel/completion.c index f127fb5..d556f31 100644 --- a/kernel/completion.c +++ b/kernel/completion.c @@ -7,17 +7,22 @@ * ------------------------------------------------------------------------ */ +#if 0 #include #include void wait_completion(completion_t *x) { wait_event(&x->wait, (x->done == 1)); } void complete(completion_t *x) { + uint32_t iflags; + irq_save(iflags); x->done = 1; wake_up(&x->wait); + irq_restore(iflags); } void init_completion(completion_t *x) { x->done = 0; init_wait_queue_head(&x->wait); -} \ No newline at end of file +} +#endif diff --git a/kernel/semaphore.c b/kernel/semaphore.c index 9014f46..c7ff128 100644 --- a/kernel/semaphore.c +++ b/kernel/semaphore.c @@ -35,6 +35,15 @@ volatile void down(semaphore_t *s) { irq_restore(iflags); } +// volatile bool try_down(semaphore_t *s) { +// unsigned long iflags; +// irq_save(iflags); + +// // if(s->cnt ) + +// irq_restore(iflags); +// } + volatile void up(semaphore_t *s) { unsigned long iflags; irq_save(iflags); diff --git a/kernel/setup.c b/kernel/setup.c index d947589..12e2314 100644 --- a/kernel/setup.c +++ b/kernel/setup.c @@ -20,6 +20,7 @@ #include extern void init_mm(); +extern void init_buffer(); extern void setup_gdt(); extern void setup_idt(); extern void setup_gate(); @@ -55,6 +56,8 @@ void setup_kernel() { init_mm(); + init_buffer(); + // printk("kernel: %08x - %08x\n", system.kernel_begin, system.kernel_end); boot_delay(DEFAULT_BOOT_DELAY_TICKS); diff --git a/kernel/wait.c b/kernel/wait.c index 86ea8f2..316205e 100644 --- a/kernel/wait.c +++ b/kernel/wait.c @@ -14,111 +14,123 @@ volatile void init_wait_queue_head(wait_queue_head_t *wqh) { INIT_LIST_HEAD(&wqh->task_list); } -volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { +volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state) { unsigned long flags; irq_save(flags); - list_add_tail(&wq->task_list, &head->task_list); + if (list_empty(&wq->task_list)) { + list_add_tail(&wq->task_list, &head->task_list); + } + set_current_state(state); irq_restore(flags); } -volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { +volatile void __end_wait(wait_queue_t *wq) { + set_current_state(TASK_READY); unsigned long flags; irq_save(flags); - list_del(&wq->task_list); + list_del_init(&wq->task_list); irq_restore(flags); } -volatile void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int state) { +volatile void wake_up(wait_queue_head_t *head) { unsigned long flags; + wait_queue_t *p, *tmp; irq_save(flags); - if (list_empty(&wq->task_list)) { - list_add_tail(&wq->task_list, &head->task_list); + list_for_each_entry_safe(p, tmp, &head->task_list, task_list) { + list_del(&p->task_list); + // printk("wakeup: %s\n", p->task->name); + p->task->state = TASK_READY; } - set_current_state(state); irq_restore(flags); } -volatile void __end_wait(wait_queue_head_t *head, wait_queue_t *wq) { - set_current_state(TASK_READY); +volatile void add_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { unsigned long flags; irq_save(flags); - list_del_init(&wq->task_list); + list_add_tail(&wq->task_list, &head->task_list); irq_restore(flags); } -volatile void sleep_on(wait_queue_head_t *head) { - DECLARE_WAIT_QUEUE(wait, current); - +volatile void del_wait_queue(wait_queue_head_t *head, wait_queue_t *wq) { unsigned long flags; irq_save(flags); + list_del(&wq->task_list); + irq_restore(flags); +} - current->state = TASK_WAIT; - current->reason = "sleep_on"; +// volatile void sleep_on(wait_queue_head_t *head) { +// DECLARE_WAIT_QUEUE(wait, current); - list_add_tail(&wait.task_list, &head->task_list); +// unsigned long flags; +// irq_save(flags); - irq_restore(flags); +// current->state = TASK_WAIT; +// current->reason = "sleep_on"; - schedule(); +// list_add_tail(&wait.task_list, &head->task_list); - // wake_up操作会把wait从heat链表上删除 - // 所以这里就不用做什么了 -} +// irq_restore(flags); -volatile void __wake_up(wait_queue_head_t *head, int nr) { - unsigned long flags; - wait_queue_t *p, *tmp; - irq_save(flags); - list_for_each_entry_safe(p, tmp, &head->task_list, task_list) { - list_del(&p->task_list); - // printk("wakeup: %s\n", p->task->name); - p->task->state = TASK_READY; - current->reason = "wake_up"; +// schedule(); - --nr; - if (nr == 0) { - break; - } - } - irq_restore(flags); +// // wake_up操作会把wait从heat链表上删除 +// // 所以这里就不用做什么了 +// } - // no schedule() here. -} +// volatile void __wake_up(wait_queue_head_t *head, int nr) { +// unsigned long flags; +// wait_queue_t *p, *tmp; +// irq_save(flags); +// list_for_each_entry_safe(p, tmp, &head->task_list, task_list) { +// list_del(&p->task_list); +// // printk("wakeup: %s\n", p->task->name); +// p->task->state = TASK_READY; +// current->reason = "wake_up"; -volatile void wake_up(wait_queue_head_t *head) { __wake_up(head, 1); } +// --nr; +// if (nr == 0) { +// break; +// } +// } +// irq_restore(flags); -#include -DECLARE_WAIT_QUEUE_HEAD(debug_wq); -unsigned int debug_global_var = 0; -int debug_wait_queue_get() { - unsigned int v = 0; - task_union *task = current; - DECLARE_WAIT_QUEUE(wait, task); - add_wait_queue(&debug_wq, &wait); +// // no schedule() here. +// } - while (1) { - printd("pid %d is going to wait\n", sysc_getpid()); - task->state = TASK_WAIT; +// volatile void wake_up(wait_queue_head_t *head) { __wake_up(head, 1); } - disable_irq(); - v = debug_global_var; - if (debug_global_var != 0) debug_global_var--; - enable_irq(); +// #include +// DECLARE_WAIT_QUEUE_HEAD(debug_wq); +// unsigned int debug_global_var = 0; +// int debug_wait_queue_get() { +// unsigned int v = 0; +// task_union *task = current; +// DECLARE_WAIT_QUEUE(wait, task); +// add_wait_queue(&debug_wq, &wait); - if (v != 0) break; +// while (1) { +// printd("pid %d is going to wait\n", sysc_getpid()); +// task->state = TASK_WAIT; - schedule(); - printd("pid %d is running\n", sysc_getpid()); - } +// disable_irq(); +// v = debug_global_var; +// if (debug_global_var != 0) debug_global_var--; +// enable_irq(); - printd("pid %d is really running\n", sysc_getpid()); - task->state = TASK_READY; - del_wait_queue(&debug_wq, &wait); +// if (v != 0) break; - return v; -} +// schedule(); +// printd("pid %d is running\n", sysc_getpid()); +// } + +// printd("pid %d is really running\n", sysc_getpid()); +// task->state = TASK_READY; +// del_wait_queue(&debug_wq, &wait); + +// return v; +// } int debug_wait_queue_put(unsigned int v) { - debug_global_var = v; - wake_up(&debug_wq); + // debug_global_var = v; + // wake_up(&debug_wq); } -- 2.44.0