]> Zhao Yanbai Git Server - kernel.git/commitdiff
TASK_RUNNING 改成 TASK_READY; 将磁盘请求放到内核任务里执行
authoracevest <zhaoyanbai@126.com>
Sat, 20 Nov 2021 15:16:00 +0000 (23:16 +0800)
committeracevest <zhaoyanbai@126.com>
Sun, 21 Nov 2021 14:28:03 +0000 (22:28 +0800)
18 files changed:
drivers/ata.c
drivers/console.c
drivers/ide.c
include/disk.h [new file with mode: 0644]
include/list.h
include/task.h
include/types.h
kernel/clock.c
kernel/fork.c
kernel/sched.c
kernel/semaphore.c
kernel/setup.c
kernel/syscall.c
kernel/task_disk.c
kernel/task_root.c
kernel/wait.c
lib/vsprintf.c
test_list.c [new file with mode: 0644]

index 344d5791ccfc0e4a1d834b462ed00dca2344bd1d..8ee4e34a4d6c1a7ad07e792201913572ec631a95 100644 (file)
@@ -7,14 +7,13 @@
  * ------------------------------------------------------------------------
  */
 #include <ata.h>
+#include <disk.h>
 #include <ide.h>
 #include <io.h>
 #include <irq.h>
 #include <sched.h>
 #include <string.h>
 #include <system.h>
-#include <types.h>
-#include <wait.h>
 
 extern ide_pci_controller_t ide_pci_controller;
 
@@ -45,8 +44,50 @@ void ata_test(uint64_t nr) {
 //  3. 等到status的DRQ位或ERR位设置
 u16 identify[256];
 void ata_send_read_identify_cmd(int dev) {}
-void ata_read_identify(int dev) {  // 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3
 
+void ata_read_data(int dev, int sect_cnt, void *dst) { insl(REG_DATA(dev), dst, (512 * sect_cnt) / sizeof(uint32_t)); }
+
+void ata_read_identify(int dev) {
+    outb(0x00, REG_CTL(dev));
+    outb(0x00 | ((dev & 0x01) << 4), REG_DEVICE(dev));  // 根据文档P113,这里不用指定bit5, bit7,直接指示DRIVE就行
+
+    unsigned long flags;
+    irq_save(flags);
+
+    outb(ATA_CMD_IDENTIFY, REG_CMD(dev));
+    wait_on_ide();
+
+    irq_restore(flags);
+}
+
+void ata_init() {
+    disk_request_t r;
+    r.buf = (void *)identify;
+    r.count = 1;
+    r.pos = 0;
+    r.command = DISK_REQ_IDENTIFY;
+
+    send_disk_request(&r);
+
+    // 第49个word的第8个bit位表示是否支持DMA
+    // 第83个word的第10个bit位表示是否支持LBA48,为1表示支持。
+    // 第100~103个word的八个字节表示user的LBA最大值
+    printk("%04x %04x %d %d\n", identify[49], 1 << 8, identify[49] & (1 << 8), (identify[49] & (1 << 8)) != 0);
+    if ((identify[49] & (1 << 8)) != 0) {
+        printk("support DMA\n");
+    }
+
+    if ((identify[83] & (1 << 10)) != 0) {
+        printk("support LBA48\n");
+
+        u64 lba = *(u64 *)(identify + 100);
+        printk("hard disk size: %u MB\n", (lba * 512) >> 20);
+    }
+}
+
+void ata_read_identify_old(int dev) {  // 这里所用的dev是逻辑编号 ATA0、ATA1下的Master、Salve的dev分别为0,1,2,3
+    // void send_disk_request();
+    // send_disk_request();
     // DECLARE_WAIT_QUEUE_HEAD(wq_head);
     // DECLARE_WAIT_QUEUE(wait, current);
     // add_wait_queue(&wq_head, &wait);
index e9eaf600355f96b859d010338df911207b7a2522..32860c7d14d70ed0ca5b498da5852c8e760e300a 100644 (file)
@@ -111,7 +111,7 @@ int cnsl_read(char *buf, size_t count) {
             if (r) {
                 buf[cnt++] = ch;
 
-                task->state = TASK_RUNNING;
+                task->state = TASK_READY;
                 del_wait_queue(&rdwq, &wait);
 
                 if (ch == '\n') goto end;
index 781b28ec16678cd3f41331ca6dc5677e418e37bf..64fcd09fdebc3b51fd650f3715ce60d63aa946c6 100644 (file)
@@ -121,7 +121,7 @@ ide_intr_func_t ide_intr_func = ide_default_intr;
 //     }
 
 //     // printd("%s pid %d is really running\n", __func__, sysc_getpid());
-//     task->state = TASK_RUNNING;
+//     task->state = TASK_READY;
 //     del_wait_queue(&r->wait, &wait);
 // }
 
@@ -537,6 +537,8 @@ void ata_read_identify(int dev);
 DECLARE_WAIT_QUEUE_HEAD(ide_wait_queue_head);
 
 void sleep_on_ide() { sleep_on(&ide_wait_queue_head); }
+
+void prepare_to_wait_on_ide() { ide_pci_controller.done = 0; }
 void wait_on_ide() { wait_event(&ide_wait_queue_head, ide_pci_controller.done); }
 
 extern void *mbr_buf;
@@ -548,24 +550,9 @@ void ide_irq_handler(unsigned int irq, pt_regs_t *regs, void *devid) {
 
     printk("ide pci status after interrupt: %x\n", ata_pci_bus_status());
 
-#if 0
-    unsigned int v = pci_read_config_word(pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
-    pci_write_config_word(v & (~PCI_COMMAND_MASTER), pci_cmd(ide_pci_controller.pci, PCI_COMMAND));
-
-    uint16_t *p = (uint16_t *)mbr_buf;
-    for (int i = 0; i < 256; i++) {
-        if (i % 12 == 0) {
-            printk("\n%03d ", i);
-        }
-        printk("%04x ", p[i]);
-    }
-#endif
-
     ide_pci_controller.done = 1;
 
     wake_up(&ide_wait_queue_head);
-
-    // ide_pci_controller.task->state = TASK_RUNNING;
 }
 
 void ide_init() {
@@ -576,15 +563,4 @@ void ide_init() {
 
     // init_pci_controller(0x0106);
     init_pci_controller(0x0101);
-
-    // ide_detect();
-    // return;
-    // ide_read_identify();
-    ata_read_identify(0);
-    return;
-
-    // // 还没开启中断
-    // ide_read_partition();
-
-    // ide_printl();
 }
diff --git a/include/disk.h b/include/disk.h
new file mode 100644 (file)
index 0000000..0321bb5
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * ------------------------------------------------------------------------
+ *   File Name: disk.h
+ *      Author: Zhao Yanbai
+ *              2021-11-21 22:08:16 Sunday CST
+ * Description: none
+ * ------------------------------------------------------------------------
+ */
+
+#pragma once
+
+#include <list.h>
+#include <semaphore.h>
+#include <types.h>
+#include <wait.h>
+
+typedef enum {
+    DISK_REQ_IDENTIFY,
+    DISK_REQ_READ,
+} disk_request_cmd_t;
+
+typedef struct disk_request {
+    uint64_t pos;                // 扇区号
+    uint16_t count;              // 扇区数
+    void *buf;                   // 到的缓冲区
+    disk_request_cmd_t command;  // 命令
+    list_head_t list;
+    wait_queue_head_t wait;  // 等待队列
+    // 驱动器完全有可能在进程在进程睡眠到等待队列前返回数据并执行唤醒操作
+    // 这时等待队列上无进程,就相当于不执行任何操作
+    // 然后进程再睡眠到等待队列上,就会造成永远无法唤醒该进程
+    // 因此要添加一个字段,标志驱动器已经对该请求做过唤醒操作
+    // 进程在睡眠前需要检查该字段
+    int done;
+} disk_request_t;
+
+typedef struct {
+    uint32_t count;
+    semaphore_t sem;
+    list_head_t list;
+} disk_request_queue_t;
+
+void send_disk_request(disk_request_t *r);
\ No newline at end of file
index 475e7f38cbd0fd15414ec5cd4ec72df2de6a1999..8ee3395673c8f17b4083545fadfd3208db714698 100644 (file)
@@ -21,9 +21,6 @@ typedef struct list_head {
     struct list_head *prev, *next;
 } list_head_t;
 
-// TODO Remove
-typedef list_head_t ListHead, *pListHead;
-
 #define LIST_HEAD_INIT(name) \
     { &(name), &(name) }
 #define LIST_HEAD(name) list_head_t name = LIST_HEAD_INIT(name)
index add360271b7fa4b3cb77ca8b215ab49135c50941..ac27a6aec5481395f557bcf19bb0992a35e2677e 100644 (file)
@@ -25,7 +25,7 @@
 
 enum {
     TASK_UNUSED,
-    TASK_RUNNING,
+    TASK_READY,
     TASK_WAIT,
     TASK_INITING,
     TASK_EXITING,
index 769fa3c47580500c485a9d69672d37ea24c0f60a..04a3aaad23da66ce14ab253c022971ab31aa4ee8 100644 (file)
@@ -42,9 +42,13 @@ typedef unsigned long u32_t;
 typedef unsigned long long u64_t;
 
 typedef unsigned char uint8_t;
+typedef char int8_t;
 typedef unsigned short uint16_t;
+typedef short int16_t;
 typedef unsigned long uint32_t;
+typedef long int32_t;
 typedef unsigned long long uint64_t;
+typedef long long int64_t;
 
 typedef unsigned long pid_t;
 typedef unsigned long mode_t;
index 8e8be8f22d88a6e8e73b778a1511e43008d4ff53..bca611d4cafe64b4b152ea1db86b97512f875f19 100644 (file)
@@ -34,7 +34,7 @@ void clk_handler(unsigned int irq, pt_regs_t *regs, void *dev_id) {
         p->delay_cnt -= p->delay_cnt == 0 ? 0 : 1;
 
         if (0 == p->delay_cnt) {
-            p->state = TASK_RUNNING;
+            p->state = TASK_READY;
             list_del(&p->pend);
         }
     }
index 62915019570882875e2e323b0b27be7a63ffd8c0..c367af1347f47f16bc81fc69928de09d2dc4adb3 100644 (file)
@@ -107,7 +107,7 @@ int do_fork(pt_regs_t *regs, unsigned long flags) {
     list_add(&tsk->list, &all_tasks);
     irq_restore(iflags);
 
-    tsk->state = TASK_RUNNING;
+    tsk->state = TASK_READY;
 
     return (int)tsk->pid;
 }
index 798fd7656d63945a4f1eb1d0084fed110ce8c334..819fa3c33c5dfc5c0211aca9e4d4bd791ae8fa5f 100644 (file)
@@ -55,7 +55,7 @@ void init_root_task() {
 
     root_task.pid = get_next_pid();
     root_task.ppid = 0;
-    root_task.state = TASK_RUNNING;
+    root_task.state = TASK_READY;
     root_task.weight = TASK_INIT_WEIGHT;
     root_task.priority = 100;
     strcpy(root_task.name, "root");
@@ -141,7 +141,7 @@ task_union *find_task(pid_t pid) {
 
 static const char *task_state(unsigned int state) {
     static const char s[][16] = {
-        "  ERROR", "RUNNING", "   WAIT", "INITING", "EXITING",
+        "  ERROR", "READY", " WAIT", " INIT", " EXIT",
     };
 
     if (state >= TASK_END) {
@@ -165,7 +165,7 @@ unsigned long schedule() {
     bool need_reset_weight = true;
     list_for_each_safe(pos, t, &all_tasks) {
         p = list_entry(pos, task_union, list);
-        if (p->state != TASK_RUNNING) {
+        if (p->state != TASK_READY) {
             continue;
         }
         if (p->weight < p->priority) {
@@ -177,7 +177,7 @@ unsigned long schedule() {
     if (need_reset_weight) {
         list_for_each_safe(pos, t, &all_tasks) {
             p = list_entry(pos, task_union, list);
-            if (p->state != TASK_RUNNING) {
+            if (p->state != TASK_READY) {
                 continue;
             }
             p->weight = 0;
@@ -187,7 +187,7 @@ unsigned long schedule() {
     list_for_each_safe(pos, t, &all_tasks) {
         p = list_entry(pos, task_union, list);
 
-        if (p->state != TASK_RUNNING) {
+        if (p->state != TASK_READY) {
             continue;
         }
 
@@ -218,5 +218,5 @@ unsigned long schedule() {
 
 void debug_sched() {
     task_union *p = list_entry(current->list.next, task_union, list);
-    p->state = (p->state == TASK_RUNNING) ? TASK_WAIT : TASK_RUNNING;
+    p->state = (p->state == TASK_READY) ? TASK_WAIT : TASK_READY;
 }
index 4dd314a94a043aca7170e25147803f807c4dfcf3..278d33915a6fcb10068490e7c9ff24a64ed3f551 100644 (file)
@@ -44,7 +44,6 @@ void __down(semaphore_t *s) {
 void down(semaphore_t *s) {
     unsigned long iflags;
     irq_save(iflags);
-
     if (likely(s->cnt > 0)) {
         s->cnt--;
     } else {
@@ -59,16 +58,19 @@ void __up(semaphore_t *s) {
     list_del(&waiter->list);
     waiter->up = 1;
 
-    waiter->task->state = TASK_RUNNING;
+    waiter->task->state = TASK_READY;
 }
 
 void up(semaphore_t *s) {
     unsigned long iflags;
     irq_save(iflags);
 
-    if (likely(list_empty(&s->wait_list))) {
+    // if (likely(list_empty(&s->wait_list))) {
+    if (list_empty(&s->wait_list)) {
+        printk("++++++\n");
         s->cnt++;
     } else {
+        printk("upupupuppupupup\n");
         __up(s);
     }
 
index 7c1991d2e25de8a97b95baa9090ec50b74aea9ce..87d984ccf36af03d98487343097d5f5226863ce5 100644 (file)
@@ -89,12 +89,15 @@ void setup_kernel() {
 
     extern tty_t monitor_tty;
     tty_switch(&monitor_tty);
+
+    void ide_init();
+    ide_init();
 }
 
 // 在开中断的情况下继续初始化的内容
 void setup_under_irq() {
-    void ide_init();
-    ide_init();
+    void ata_init();
+    ata_init();
     return;
     setup_fs();
 }
\ No newline at end of file
index 40a6e5642515dba5f94219d219812a0fbdb2d207..2a25a9f996c793444b87b5ed0f3b279f5a509965 100644 (file)
@@ -52,7 +52,7 @@ int sysc_test() {
         // 下一次系统调用还可能走到这里
         // 所以这里就直接判断不是RUNNING就返回
         // 不再操作delay_tasks链表
-        if (current->state != TASK_RUNNING) {
+        if (current->state != TASK_READY) {
             return 0;
         }
 
index 9ed8f0cfd9132d0b49b539bd7c2d4d5ab42b1a33..3d29af2bf0d2b3ed892e2478a508cd00c3a6a49b 100644 (file)
  * ------------------------------------------------------------------------
  */
 
+#include <disk.h>
 #include <sched.h>
-#include <semaphore.h>
-#include <wait.h>
-
-#if 0
-typedef enum {
-    DISK_REQ_IDENTIFY,
-    DISK_REQ_READ,
-} disk_request_cmd_t;
-
-typedef struct disk_request {
-    uint64_t pos;                // 扇区号
-    uint16_t count;              // 扇区数
-    void *buf;                   // 到的缓冲区
-    disk_request_cmd_t command;  // 命令
-    wait_queue_head_t wait;      // 等待队列
-    // 驱动器完全有可能在进程在进程睡眠到等待队列前返回数据并执行唤醒操作
-    // 这时等待队列上无进程,就相当于不执行任何操作
-    // 然后进程再睡眠到等待队列上,就会造成永远无法唤醒该进程
-    // 因此要添加一个字段,标志驱动器已经对该请求做过唤醒操作
-    // 进程在睡眠前需要检查该字段
-    int done;
-} disk_request_t;
-
-void send_disk_request() {
-    disk_request_t r;
-    r.pos = 0;
-    r.count = 1;
-    r.buf = kmalloc(512, 0);
-    r.command = DISK_REQ_IDENTIFY;
-    INIT_LIST_HEAD(&r.wait.task_list);
-    r.done = 0;
-
-    list_add_tail(&wq->task_list, &head->task_list);
 
-    // 发送命令
-    //....
+disk_request_queue_t disk_request_queue;  // = {.count = 0,
+                                          //   .sem = SEMAPHORE_INITIALIZER(disk_request_queue.sem, 0),
+                                          //   .list = LIST_HEAD_INIT(disk_request_queue.list)};
+
+void disk_init() {
+    disk_request_queue.count = 0;
+    disk_request_queue.sem.cnt = 0;
+    INIT_LIST_HEAD(&disk_request_queue.sem.wait_list);
+    INIT_LIST_HEAD(&disk_request_queue.list);
+}
+
+#if 1
+void send_disk_request(disk_request_t *r) {
+    if (NULL == r) {
+        panic("null disk request");
+    }
+
+    // 校验pos,和pos+count是否大于硬盘返回的最大LBA48
+    // ...
+
+    // 校验buffer是否跨64K
+    // 先不处理
+    if (((uint32_t)r->buf & 0xFFFF0000) != (((uint32_t)(r->buf + r->count * 512)) & 0xFFFF0000)) {
+        panic("disk DMA read cross 64K");
+    }
 
+    INIT_LIST_HEAD(&r->wait.task_list);
+    r->done = 0;
+    // r.pos = pos;
+    // r.count = count;
+    // r.buf = kmalloc(512, 0);
+    // r.command = DISK_REQ_IDENTIFY;
+    // INIT_LIST_HEAD(&r.wait.task_list);
+    // r.done = 0;
+
+    // printk("do send disk request: %d %x %x %x\n", list_empty(&disk_request_queue.sem.wait_list),
+    //        &disk_request_queue.sem.wait_list, disk_request_queue.sem.wait_list.next,
+    //        disk_request_queue.sem.wait_list.prev);
+
+    // 发送命令
     unsigned long flags;
     irq_save(flags);
-    if (0 == r.done) {  // 驱动器还没完成
-        set_current_state(TASK_WAIT);
-        irq_restore(flags);
-        // 就算在schedule前驱动器触发中断也没有问题
-        // 因为该进程已经加到等待队列上了
-        // 所以它一定以唤醒该进程
-        schedule();
-    } else {  // 驱动器已经完成
-        irq_restore(flags);
-    }
-}
-#endif
+    list_add_tail(&r->list, &disk_request_queue.list);
+    irq_restore(flags);
 
-typedef struct {
-    semaphore_t sem;
-    list_head_t list;
-} disk_request_queue_t;
+    // 唤醒task_disk
+    printk("up sem\n");
+    up(&disk_request_queue.sem);
 
-disk_request_queue_t disk_request_queue = {.sem = SEMAPHORE_INITIALIZER(disk_request_queue.sem, 0),
-                                           .list = LIST_HEAD_INIT(disk_request_queue.list)};
+    // 等待task_dist结束
+    printk("wait event\n");
+    wait_event(&r->wait, r->done != 0);
+
+    printk("wait finished\n");
+}
+#endif
 
-int cnt = 0;
 void disk_task_entry() {
     while (1) {
-        printk("fuck you: %d\n", cnt);
+        void prepare_to_wait_on_ide();
+        prepare_to_wait_on_ide();
+
+        printk("wait for new hard disk request\n");
         down(&disk_request_queue.sem);
-        printk("fuck me: %d\n", cnt);
-        cnt++;
+        printk("hard disk request: %d\n", disk_request_queue.count++);
+
+        unsigned long flags;
+        irq_save(flags);
+
+        disk_request_t *r;
+        if (list_empty(&disk_request_queue.list)) {
+        } else {
+            r = list_first_entry(&disk_request_queue.list, disk_request_t, list);
+            if (NULL == r) {
+                panic("no disk request");
+            }
+
+            printk("disk request: pos %ld count %d cmd %d\n", r->pos, r->count, r->command);
+        }
+
+        irq_restore(flags);
+
+        if (NULL == r) {
+            continue;
+        }
+
+        int dev = 0;
+        switch (r->command) {
+        case DISK_REQ_IDENTIFY:
+            assert(r->count == 1);
+            void ata_read_identify(int dev);
+            ata_read_identify(dev);
+            break;
+
+        default:
+            break;
+        }
+
+        // 等待硬盘中断
+        void wait_on_ide();
+        wait_on_ide();
+
+        // 读数据
+        if (DISK_REQ_IDENTIFY == r->command) {
+            void ata_read_data(int dev, int sect_cnt, void *dst);
+            ata_read_data(dev, 1, r->buf);
+        }
+
+        // 唤醒等待该请求的进程
+        r->done = 1;
+        wake_up(&r->wait);
     }
 }
index 77ac5df37d86325ca584696bfaee24e13c4ceed1..62736a175edafb291c6e8a3aea1528f9b2f7574d 100644 (file)
@@ -57,6 +57,10 @@ void root_task_entry() {
     // 所以得先清空一下键盘
     inb(0x60);
 
+    //
+    void disk_init();
+    disk_init();
+
     kernel_task("init", init_task_entry);
     kernel_task("disk", disk_task_entry);
     kernel_task("user", user_task_entry);
index 51afc3eef4db7c27b6272172734d2891d1ff36d7..f671a39b7ef390527a8fde8cbfd129cd8ddea3d2 100644 (file)
@@ -39,7 +39,7 @@ void prepare_to_wait(wait_queue_head_t *head, wait_queue_t *wq, unsigned int sta
 }
 
 void __end_wait(wait_queue_head_t *head, wait_queue_t *wq) {
-    set_current_state(TASK_RUNNING);
+    set_current_state(TASK_READY);
     unsigned long flags;
     irq_save(flags);
     list_del_init(&wq->task_list);
@@ -67,8 +67,8 @@ void __wake_up(wait_queue_head_t *head, int nr) {
     irq_save(flags);
     list_for_each_entry_safe(p, tmp, &head->task_list, task_list) {
         list_del(&p->task_list);
-        printk("wakeup: %s\nread sector 0 with LBA48 and DMA", p->task->name);
-        p->task->state = TASK_RUNNING;
+        printk("wakeup: %s\n", p->task->name);
+        p->task->state = TASK_READY;
 
         --nr;
         if (nr == 0) {
@@ -107,7 +107,7 @@ int debug_wait_queue_get() {
     }
 
     printd("pid %d is really running\n", sysc_getpid());
-    task->state = TASK_RUNNING;
+    task->state = TASK_READY;
     del_wait_queue(&debug_wq, &wait);
 
     return v;
@@ -143,7 +143,7 @@ int sysc_wait(unsigned long pid) {
         schedule();
     }
 
-    task->state = TASK_RUNNING;
+    task->state = TASK_READY;
     del_wait_queue(&p->wait, &wait);
 
     return 0;
index f29433a45b4b9967d2ffb039bcd09701537f036a..40507716497c5fcc74c262fe3ca2d74d2bf4fb09 100644 (file)
@@ -4,11 +4,14 @@
 //     Add %012d %012x %12d %12x Support  Mon, 20 Jul 2009 19:30:34
 //     Add %u Support                     Sun, 06 Jul 2014 12:07:54
 // ========================================================================
+#include <types.h>
+
 #include "string.h"
 
 char *itoa(char *s, int n);
 char *itou(char *s, unsigned int n);
 char *itox(char *s, unsigned int n);
+char *i64tou(char *s, int64_t n);
 
 enum { ALIGN_RIGHT, ALIGN_LEFT };
 
@@ -77,6 +80,14 @@ int vsprintf(char *buf, const char *fmt, char *args) {
             itoa(tmp, *((int *)args));
             p += write_buf(p, tmp, char_fill, char_cnt, align);
             break;
+        case 'l':
+            fmt++;
+            if (*fmt == 'u' || *fmt == 'd') {  // d u都当成u来处理
+                i64tou(tmp, *((int64_t *)args));
+                p += write_buf(p, tmp, char_fill, char_cnt, align);
+                args += 4;
+            }
+            break;
         case 's':
             p += write_buf(p, (const char *)*((unsigned int *)args), char_fill, char_cnt, align);
             break;
@@ -131,6 +142,15 @@ char *itoa(char *s, int n) {
     }
 }
 
+char *i64tou(char *s, int64_t n) {
+    itou(s, n >> 32);
+    int i = 0;
+    if ((n >> 32) > 0) {
+        i = strlen(s);
+    }
+    itou(s + i, n & 0xFFFFFFFF);
+}
+
 char *itou(char *s, unsigned int n) {
     char c;
     char *p = s;
diff --git a/test_list.c b/test_list.c
new file mode 100644 (file)
index 0000000..88e8746
--- /dev/null
@@ -0,0 +1,120 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+/* Allmost Copy From Linux */
+typedef struct list_head {
+    struct list_head *prev, *next;
+} list_head_t;
+
+#define LIST_HEAD_INIT(name) \
+    { &(name), &(name) }
+#define LIST_HEAD(name) list_head_t name = LIST_HEAD_INIT(name)
+
+#define INIT_LIST_HEAD(ptr)  \
+    do {                     \
+        (ptr)->next = (ptr); \
+        (ptr)->prev = (ptr); \
+    } while (0)
+
+#define list_entry(ptr, type, member) ((type *)((char *)(ptr) - (unsigned long)(&((type *)0)->member)))
+
+#define list_first_entry(ptr, type, member) list_entry((ptr)->next, type, member)
+
+#define list_for_each(pos, head) for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, tmp, head) \
+    for (pos = (head)->next, tmp = pos->next; pos != (head); pos = tmp, tmp = pos->next)
+
+#define list_for_each_entry_safe(pos, tmp, head, member)          \
+    for (pos = list_entry((head)->next, typeof(*pos), member),    \
+        tmp = list_entry(pos->member.next, typeof(*pos), member); \
+         &pos->member != (head); pos = tmp, tmp = list_entry(tmp->member.next, typeof(*tmp), member))
+
+static inline void _list_add(list_head_t *pnew, list_head_t *prev, list_head_t *next) {
+    next->prev = pnew;
+    pnew->next = next;
+    pnew->prev = prev;
+    prev->next = pnew;
+}
+
+static inline void list_add(list_head_t *pnew, list_head_t *head) { _list_add(pnew, head, head->next); }
+
+static inline void list_add_tail(list_head_t *pnew, list_head_t *head) { _list_add(pnew, head->prev, head); }
+
+static inline void _list_del(list_head_t *prev, list_head_t *next) {
+    next->prev = prev;
+    prev->next = next;
+}
+
+static inline void list_del(list_head_t *entry) {
+    _list_del(entry->prev, entry->next);
+    entry->prev = NULL;
+    entry->next = NULL;
+}
+
+static inline void list_del_init(list_head_t *entry) {
+    _list_del(entry->prev, entry->next);
+    INIT_LIST_HEAD(entry);
+}
+
+static inline int list_empty(list_head_t *head) { return head->next == head; }
+
+typedef struct node {
+    int id;
+    list_head_t list;
+    list_head_t pend;
+} node_t;
+
+LIST_HEAD(allH);
+LIST_HEAD(pendH);
+
+int main() {
+    INIT_LIST_HEAD(&allH);
+    INIT_LIST_HEAD(&pendH);
+
+    for (int i = 0; i < 10; i++) {
+        node_t *n = (node_t *)malloc(sizeof(node_t));
+        n->id = i;
+        list_add(&n->list, &allH);
+        if (n->id % 3 == 0) {
+            list_add(&n->pend, &pendH);
+        }
+    }
+
+    list_head_t *pos;
+    list_head_t *tmp;
+    node_t *p, *p1;
+    list_for_each_safe(pos, tmp, &allH) {
+        p = list_entry(pos, node_t, list);
+        printf("allH: %d\n", p->id);
+    }
+
+    printf("-----\n");
+    list_for_each_safe(pos, tmp, &pendH) {
+        p = list_entry(pos, node_t, pend);
+        printf("pendH: %d\n", p->id);
+    }
+
+    // list_for_each_safe(pos, tmp, &allH) {
+
+    //    p = list_entry(pos, node_t, list);
+    list_for_each_entry_safe(p, p1, &pendH, pend) {
+        // printf("%d\n", p->id);
+        if (p->id == 3) {
+            list_del(&p->pend);
+        }
+    }
+
+    printf("-----\n");
+
+    list_for_each_safe(pos, tmp, &allH) {
+        p = list_entry(pos, node_t, list);
+        printf("allH: %d\n", p->id);
+    }
+
+    printf("-----\n");
+    list_for_each_safe(pos, tmp, &pendH) {
+        p = list_entry(pos, node_t, pend);
+        printf("pendH: %d\n", p->id);
+    }
+}
\ No newline at end of file