p->s_free_blocks_count, p->s_magic);
printk("first ino %u inode size %u first data block %u\n", p->s_first_ino, p->s_inode_size, p->s_first_data_block);
printk("log block size %u write time %u\n", p->s_log_block_size, p->s_wtime);
- p->s_volume_name[63] = 0;
- printk("volume %s\n", p->s_volume_name);
+ char volume_name[16 + 1];
+ strncpy(volume_name, p->s_volume_name, 16);
+ volume_name[16] = 0;
+ printk("volume %s\n", volume_name);
+ // printk("last mounted %s\n", p->s_last_mounted);
kfree(bb->data);
}
#include <sched.h>
#include <semaphore.h>
+void semaphore_init(semaphore_t *s, unsigned int v) {
+ s->cnt = v;
+ INIT_LIST_HEAD(&(s->wait_list));
+}
+
+#if 1
+volatile void down(semaphore_t *s) {
+ unsigned long iflags;
+ irq_save(iflags);
+
+ if (likely(s->cnt > 0)) {
+ s->cnt--;
+ } else {
+ task_union *task = current;
+ list_add_tail(&task->wait, &s->wait_list);
+
+ task->state = TASK_WAIT;
+ task->reason = "down";
+
+ schedule();
+ }
+
+ irq_restore(iflags);
+}
+
+volatile void up(semaphore_t *s) {
+ unsigned long iflags;
+ irq_save(iflags);
+
+ if (list_empty(&s->wait_list)) {
+ s->cnt++;
+ } else {
+ task_union *task = list_first_entry(&s->wait_list, task_union, wait);
+ list_del(&task->wait);
+ task->state = TASK_READY;
+ task->reason = "up";
+
+ // 按理这里应该调用schedule再重新调度一次
+ // 原因是有可能多个任务都在一个循环里争抢一个锁
+ // 如果这里不让当前任务尝试放弃CPU重新调度,则在下一轮循环中它又可能抢到锁
+ // 这种情况如果一直发生,就可能导致其它任务一直抢不到
+ //
+ // 但这里为什么又没调用schedule呢?
+ // 这是因为在目前在ide_irq_bh_handler里调用了up来唤醒磁盘任务
+ // 而ide_irq_bh_handler又是中断的底半处理,不应该切换任务
+ // 否则会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务
+ // 这里暂时先保持这样,后续再来解决这里
+ // schedule();
+ }
+
+ irq_restore(iflags);
+}
+
+#else
+
typedef struct semaphore_waiter {
list_head_t list;
task_union *task;
#define DECLARE_SEMAPHORE_WAITER(name, task) semaphore_waiter_t name = SEMAPHORE_WAITER_INITIALIZER(name, task)
-void semaphore_init(semaphore_t *s, unsigned int v) {
- s->cnt = v;
- INIT_LIST_HEAD(&(s->wait_list));
-}
-
volatile void __down(semaphore_t *s) {
task_union *task = current;
DECLARE_SEMAPHORE_WAITER(waiter, task);
task->reason = "down";
schedule();
+ assert(waiter.up == 1);
if (waiter.up) {
break;
}
waiter->task->state = TASK_READY;
waiter->task->reason = "up";
+
+ // 按理这里应该调用schedule再重新调度一次
+ // 原因是有可能多个任务都在一个循环里争抢一个锁
+ // 如果这里不让当前任务尝试放弃CPU重新调度,则在下一轮循环中它又可能抢到锁
+ // 这种情况如果一直发生,就可能导致其它任务一直抢不到
+ //
+ // 但这里为什么又没调用schedule呢?
+ // 这是因为在目前在ide_irq_bh_handler里调用了up来唤醒磁盘任务
+ // 而ide_irq_bh_handler又是中断的底半处理,不应该切换任务
+ // 否则会引起irq里的reenter问题,导致不能再进底半处理,也无法切换任务
+ // 这里暂时先保持这样,后续再来解决这里
+ // schedule();
}
volatile void up(semaphore_t *s) {
irq_restore(iflags);
}
+#endif
void mutex_lock(semaphore_t *s) { down(s); }
void mutex_unlock(semaphore_t *s) { up(s); }