From: acevest Date: Fri, 20 Oct 2023 10:43:47 +0000 (+0800) Subject: ... X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=45cfb5f44f18a0725a04856bfc3012334e1ee1a9;p=kernel.git ... --- 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 index 3074b29..a5f0777 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -8,6 +8,7 @@ */ #include +#include #define MAX_BBUFFER_CNT 985 @@ -17,55 +18,137 @@ 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 cache_list; list_head_t free_list; } bbuffer_store_t; // 1024, 2048, 4096 bbuffer_store_t store[3] = {0}; -int hashfn(dev_t dev, uint32_t block) { return ((dev) ^ block) % BLOCK_BUFFER_HASH_TABLE_SIZE; } - -bbuffer_t *get_hash_block_buffer(dev_t dev, uint32_t block, uint16_t size) {} - kmem_cache_t *bbufer_kmem_cache = 0; -bbuffer_t *bread(dev_t dev, uint64_t block, uint32_t size) { +bbuffer_store_t *getstore(uint32_t size) { assert(size == 1024 || size == 2048 || size == 4096); - // 暂时先只支持hard disk - assert(DEV_MAJOR(dev) == DEV_MAJOR_DISK); + bbuffer_store_t *s = 0; - // 先尝试从hash里分配 + 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) { + + 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的cached_list里尝试找 + // 如果没找到,则从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; + } + } - // 如果没找到,则尝试从store里的free_list里尝试分配 + // 如果还是没有找到,则就需要等待释放出新的空间 + 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); - // 如果free_list为空,且cached_list不为空, + return b; } void init_buffer() { @@ -74,22 +157,23 @@ void init_buffer() { } bbufer_kmem_cache = kmem_cache_create("bbuffer", sizeof(bbuffer_t), 4); - if (0 == bbufer_kmem_cache) { + 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].cache_list); list_init(&store[i].free_list); int page_left_space = 0; - void *data = 0; - page_t *page = 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)); @@ -97,7 +181,7 @@ void init_buffer() { } bbuffer_t *b = kmem_cache_alloc(bbufer_kmem_cache, 0); - assert(b != 0); + assert(NULL != b); b->block = 0; b->block_size = blocksize; @@ -105,9 +189,11 @@ void init_buffer() { b->data = data + j * blocksize; b->dev = 0; b->page = page; + b->uptodate = 0; + b->locked = 0; list_init(&b->node); - assert(0 != b->data); + assert(NULL != b->data); list_add(&b->node, &store[i].free_list); diff --git a/include/buffer.h b/include/buffer.h index a15b5c1..8f570cc 100644 --- a/include/buffer.h +++ b/include/buffer.h @@ -9,6 +9,7 @@ #pragma once +#include #include #include #include @@ -16,10 +17,13 @@ typedef struct bbuffer { uint32_t block; // block number - char *data; // - uint32_t ref_count; + 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/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/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/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); }