#include <console.h>
#include <sched.h>
+#include <semaphore.h>
#include <string.h>
#include <tty.h>
#include <wait.h>
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) {
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);
}
}
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);
schedule();
}
+#endif
}
end:
*/
#include <buffer.h>
+#include <irq.h>
#define MAX_BBUFFER_CNT 985
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() {
}
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));
}
bbuffer_t *b = kmem_cache_alloc(bbufer_kmem_cache, 0);
- assert(b != 0);
+ assert(NULL != b);
b->block = 0;
b->block_size = blocksize;
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);
#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;
#pragma once
+#if 0
#include <wait.h>
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
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;
// 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;
// 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();
} \
schedule(); \
} \
- __end_wait(head, &__wait); \
+ __end_wait(&__wait); \
} while (0)
#define wait_event(head, condition) \
* ------------------------------------------------------------------------
*/
+#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
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);
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);
}