]> Zhao Yanbai Git Server - kernel.git/commitdiff
...
authoracevest <zhaoyanbai@126.com>
Fri, 20 Oct 2023 10:43:47 +0000 (18:43 +0800)
committeracevest <zhaoyanbai@126.com>
Fri, 20 Oct 2023 10:43:47 +0000 (18:43 +0800)
drivers/console.c
fs/buffer.c
include/buffer.h
include/completion.h
include/disk.h
include/semaphore.h
include/wait.h
kernel/completion.c
kernel/semaphore.c
kernel/wait.c

index c186740513ee58706dd8cbc421c503eae6f44b2c..85dcfe884e0ef6230736dcf8ff07d16c0fee1d38 100644 (file)
@@ -9,6 +9,7 @@
 
 #include <console.h>
 #include <sched.h>
+#include <semaphore.h>
 #include <string.h>
 #include <tty.h>
 #include <wait.h>
@@ -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:
index 3074b29311e8c9c615bba3ccfff3455370378243..a5f0777d745bca128e400d866f54ffbfde6f49e3 100644 (file)
@@ -8,6 +8,7 @@
  */
 
 #include <buffer.h>
+#include <irq.h>
 
 #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);
 
index a15b5c13b0af56f017b74dc6c36d647a32e8fc39..8f570cc5fa9519da3ff0029758be1646e1f5ee78 100644 (file)
@@ -9,6 +9,7 @@
 
 #pragma once
 
+#include <atomic.h>
 #include <fs.h>
 #include <mm.h>
 #include <page.h>
 
 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;
index db085be69e2e7d3c8a544b3e1f51be07a1be2a79..291f73ae122e7439d9d1c5885a105b77f3f6642f 100644 (file)
@@ -9,6 +9,7 @@
 
 #pragma once
 
+#if 0
 #include <wait.h>
 
 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
index 5c3894954545a9f188f1d10fceb7d071c1db7062..751b5c9077d84ceb096585e44f0d2a4f3f016cb0 100644 (file)
@@ -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;
 
index 7f29c1a98c9308988e1bd3888d09f5affa038e7c..27eb0094f546bf0576346d4a20ba7cd55873650a 100644 (file)
@@ -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;
 
index c54c0142312596d8ef232b6613eb2440aa7d0663..8f29e935d4e75cda0b18fd9ccce0b478171ef54e 100644 (file)
@@ -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)          \
index f127fb5a8b1c387df5b073f75366e4da3fc9f159..d556f3192fc99c02422a932782a806d9d34e7aaa 100644 (file)
@@ -7,17 +7,22 @@
  * ------------------------------------------------------------------------
  */
 
+#if 0
 #include <completion.h>
 #include <sched.h>
 
 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
index 9014f46d203f3484bb55938f7b1d9237f2e1d685..c7ff1283f9e2468055e1bfd734a9f76cd09ebe01 100644 (file)
@@ -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);
index 86ea8f24cbcae1b8f3f5f9603677a28a6ee921f2..316205e3eb2606cd3707ac09157922ab6a92c68d 100644 (file)
 
 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 <irq.h>
-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 <irq.h>
+// 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);
 }