Merge branch 'device-sys'
authorMinep <zelong56@gmail.com>
Sat, 17 Sep 2022 11:30:46 +0000 (12:30 +0100)
committerMinep <zelong56@gmail.com>
Sat, 17 Sep 2022 11:30:46 +0000 (12:30 +0100)
90 files changed:
README.md
docs/img/lunaix-os-mem.png
lunaix-os/hal/ahci/ahci.c
lunaix-os/hal/pci.c
lunaix-os/includes/hal/pci.h
lunaix-os/includes/klibc/stdio.h
lunaix-os/includes/klibc/string.h
lunaix-os/includes/lunaix/block.h
lunaix-os/includes/lunaix/common.h
lunaix-os/includes/lunaix/device.h
lunaix-os/includes/lunaix/dirent.h
lunaix-os/includes/lunaix/ds/fifo.h
lunaix-os/includes/lunaix/ds/llist.h
lunaix-os/includes/lunaix/ds/mutex.h
lunaix-os/includes/lunaix/ds/rwlock.h [new file with mode: 0644]
lunaix-os/includes/lunaix/ds/waitq.h [new file with mode: 0644]
lunaix-os/includes/lunaix/fs.h
lunaix-os/includes/lunaix/fs/devfs.h [new file with mode: 0644]
lunaix-os/includes/lunaix/fs/taskfs.h [new file with mode: 0644]
lunaix-os/includes/lunaix/fs/twifs.h
lunaix-os/includes/lunaix/fs/twimap.h [new file with mode: 0644]
lunaix-os/includes/lunaix/input.h [new file with mode: 0644]
lunaix-os/includes/lunaix/ioctl.h [new file with mode: 0644]
lunaix-os/includes/lunaix/keyboard.h
lunaix-os/includes/lunaix/lunistd.h
lunaix-os/includes/lunaix/lxconsole.h
lunaix-os/includes/lunaix/mm/cake.h
lunaix-os/includes/lunaix/mm/page.h
lunaix-os/includes/lunaix/peripheral/ps2kbd.h
lunaix-os/includes/lunaix/process.h
lunaix-os/includes/lunaix/sched.h
lunaix-os/includes/lunaix/status.h
lunaix-os/includes/lunaix/syscall.h
lunaix-os/includes/lunaix/tty/console.h
lunaix-os/includes/lunaix/tty/tty.h
lunaix-os/includes/lunaix/types.h
lunaix-os/includes/ulibc/stdio.h [new file with mode: 0644]
lunaix-os/kernel/asm/x86/intr_routines.c
lunaix-os/kernel/asm/x86/pfault.c
lunaix-os/kernel/asm/x86/syscall.S
lunaix-os/kernel/block/blk_mapping.c [new file with mode: 0644]
lunaix-os/kernel/block/block.c [moved from lunaix-os/kernel/block.c with 89% similarity]
lunaix-os/kernel/demos/dir_read.c
lunaix-os/kernel/demos/input_test.c [new file with mode: 0644]
lunaix-os/kernel/demos/iotest.c
lunaix-os/kernel/demos/signal_demo.c
lunaix-os/kernel/demos/simple_sh.c [new file with mode: 0644]
lunaix-os/kernel/device.c [deleted file]
lunaix-os/kernel/device/devfs.c [new file with mode: 0644]
lunaix-os/kernel/device/device.c [new file with mode: 0644]
lunaix-os/kernel/device/input.c [new file with mode: 0644]
lunaix-os/kernel/ds/fifo.c
lunaix-os/kernel/ds/mutex.c [new file with mode: 0644]
lunaix-os/kernel/ds/rwlock.c [new file with mode: 0644]
lunaix-os/kernel/ds/waitq.c [new file with mode: 0644]
lunaix-os/kernel/fs/fs_export.c [new file with mode: 0644]
lunaix-os/kernel/fs/fs_setup.c
lunaix-os/kernel/fs/mount.c
lunaix-os/kernel/fs/path_walk.c
lunaix-os/kernel/fs/pcache.c
lunaix-os/kernel/fs/ramfs/ramfs.c
lunaix-os/kernel/fs/twifs/twifs.c
lunaix-os/kernel/fs/twimap.c [new file with mode: 0644]
lunaix-os/kernel/fs/vfs.c
lunaix-os/kernel/k_init.c
lunaix-os/kernel/kprintf.c
lunaix-os/kernel/lxconsole.c [deleted file]
lunaix-os/kernel/mm/cake.c
lunaix-os/kernel/mm/cake_export.c [new file with mode: 0644]
lunaix-os/kernel/mm/dmm.c
lunaix-os/kernel/mm/kalloc.c
lunaix-os/kernel/mm/mmio.c
lunaix-os/kernel/mm/region.c
lunaix-os/kernel/mm/vmap.c
lunaix-os/kernel/peripheral/ps2kbd.c
lunaix-os/kernel/proc0.c
lunaix-os/kernel/process/process.c [moved from lunaix-os/kernel/process.c with 97% similarity]
lunaix-os/kernel/process/sched.c [moved from lunaix-os/kernel/sched.c with 79% similarity]
lunaix-os/kernel/process/signal.c [moved from lunaix-os/kernel/signal.c with 99% similarity]
lunaix-os/kernel/process/task_attr.c [new file with mode: 0644]
lunaix-os/kernel/process/taskfs.c [new file with mode: 0644]
lunaix-os/kernel/service/pconsole.c [deleted file]
lunaix-os/kernel/spike.c
lunaix-os/kernel/time/clock.c
lunaix-os/kernel/tty/lxconsole.c [new file with mode: 0644]
lunaix-os/kernel/tty/tty.c
lunaix-os/libs/klibc/stdio/ksprintf.c [moved from lunaix-os/libs/klibc/stdio/sprintf.c with 94% similarity]
lunaix-os/libs/klibc/string/strcpy.c
lunaix-os/libs/klibc/string/trim.c
lunaix-os/libs/ulibc/printf.c [new file with mode: 0644]

index 1a71e5753cedf56bdbffe52481d6e55df8979526..77920e7a3a539c5bd0d97d7b0bedf8f466b58def 100644 (file)
--- a/README.md
+++ b/README.md
@@ -22,7 +22,7 @@ LunaixOS - 一个简单的,详细的,POSIX兼容的(但愿!),带有
 + 内存管理与按需分页(Demand Paging)
 + 键盘输入
 + 多进程
-+ 44个常见的Linux/POSIX系统调用([附录1](#appendix1))
++ 47个常见的Linux/POSIX系统调用([附录1](#appendix1))
 + 用户模式
 + 信号机制
 + PCI 3.0
@@ -98,10 +98,6 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 
 正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。
 
-#### 问题#4:键盘的上下方向键(用于滚屏)在VirtualBox下有时不好使
-
-可以试试`Shift+<方向键>`,这个问题的解决需要重写键盘驱动的状态机。我会找时间去做,毕竟这不是燃眉之急。
-
 ## 参考教程
 
 **没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。
@@ -193,6 +189,9 @@ qemu-img create -f vdi machine/disk0.vdi 128M
 2. `setxattr(2)`※
 2. `fgetxattr(2)`※
 2. `fsetxattr(2)`※
+2. `ioctl(2)`※
+2. `getpgid(2)`
+2. `setpgid(2)`
 
 **LunaixOS自有**
 
index 75c82a46b874ce7ae3e3fc17546b0979c03b4f3c..dd64890099997887137c7c49e93cbed2232ec12b 100644 (file)
Binary files a/docs/img/lunaix-os-mem.png and b/docs/img/lunaix-os-mem.png differ
index 9a7073a6c0c17c58363eb8091434e37d15d96d26..43b8f1ea6e1f0978b3429b7cfb2ccac643574c92 100644 (file)
@@ -78,9 +78,8 @@ ahci_init()
     struct pci_device* ahci_dev = pci_get_device_by_class(AHCI_HBA_CLASS);
     assert_msg(ahci_dev, "AHCI: Not found.");
 
-    uintptr_t bar6, size;
-    size = pci_bar_sizing(ahci_dev, &bar6, 6);
-    assert_msg(bar6 && PCI_BAR_MMIO(bar6), "AHCI: BAR#6 is not MMIO.");
+    struct pci_base_addr* bar6 = &ahci_dev->bar[5];
+    assert_msg(bar6->type & BAR_TYPE_MMIO, "AHCI: BAR#6 is not MMIO.");
 
     pci_reg_t cmd = pci_read_cspace(ahci_dev->cspace_base, PCI_REG_STATUS_CMD);
 
@@ -94,7 +93,7 @@ ahci_init()
 
     memset(&hba, 0, sizeof(hba));
 
-    hba.base = (hba_reg_t*)ioremap(PCI_BAR_ADDR_MM(bar6), size);
+    hba.base = (hba_reg_t*)ioremap(bar6->start, bar6->size);
 
 #ifdef DO_HBA_FULL_RESET
     // 重置HBA
@@ -194,7 +193,7 @@ __ahci_hba_isr(const isr_param* param)
 {
     // TODO: clear the interrupt status
     // TODO: I/O-operation scheduler should be here
-    kprintf(KDEBUG "HBA INTR\n");
+    // kprintf(KDEBUG "HBA INTR\n");
 }
 
 void
index 3d6accfafaacf31dc9d026c44b4a60e471a11191..aa6acd16f036ff0adb8b2c864a0370a54ae750a9 100644 (file)
@@ -11,6 +11,7 @@
 #include <hal/acpi/acpi.h>
 #include <hal/apic.h>
 #include <hal/pci.h>
+#include <lunaix/fs/twifs.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/spike.h>
 #include <lunaix/syslog.h>
@@ -55,13 +56,14 @@ pci_probe_device(int bus, int dev, int funct)
     pci_reg_t intr = pci_read_cspace(base, 0x3c);
     pci_reg_t class = pci_read_cspace(base, 0x8);
 
-    struct pci_device* device = valloc(sizeof(struct pci_device));
+    struct pci_device* device = vzalloc(sizeof(struct pci_device));
     *device = (struct pci_device){ .cspace_base = base,
                                    .class_info = class,
                                    .device_info = reg1,
                                    .intr_info = intr };
 
     pci_probe_msi_info(device);
+    pci_probe_bar_info(device);
 
     llist_append(&pci_devices, &device->dev_chain);
 }
@@ -78,6 +80,24 @@ pci_probe()
     }
 }
 
+void
+pci_probe_bar_info(struct pci_device* device)
+{
+    uint32_t bar;
+    struct pci_base_addr* ba;
+    for (size_t i = 0; i < 6; i++) {
+        ba = &device->bar[i];
+        ba->size = pci_bar_sizing(device, &bar, i + 1);
+        if (PCI_BAR_MMIO(bar)) {
+            ba->start = PCI_BAR_ADDR_MM(bar);
+            ba->type |= PCI_BAR_CACHEABLE(bar) ? BAR_TYPE_CACHABLE : 0;
+            ba->type |= BAR_TYPE_MMIO;
+        } else {
+            ba->start = PCI_BAR_ADDR_IO(bar);
+        }
+    }
+}
+
 void
 pci_probe_msi_info(struct pci_device* device)
 {
@@ -106,47 +126,99 @@ pci_probe_msi_info(struct pci_device* device)
     }
 }
 
-#define PCI_PRINT_BAR_LISTING
+void
+__pci_read_cspace(struct twimap* map)
+{
+    struct pci_device* pcidev = (struct pci_device*)(map->data);
+
+    for (size_t i = 0; i < 256; i += sizeof(pci_reg_t)) {
+        *(pci_reg_t*)(map->buffer + i) =
+          pci_read_cspace(pcidev->cspace_base, i);
+    }
+
+    map->size_acc = 256;
+}
+
+void
+__pci_read_revid(struct twimap* map)
+{
+    int class = twimap_data(map, struct pci_device*)->class_info;
+    twimap_printf(map, "0x%x", PCI_DEV_REV(class));
+}
 
 void
-pci_print_device()
+__pci_read_class(struct twimap* map)
 {
+    int class = twimap_data(map, struct pci_device*)->class_info;
+    twimap_printf(map, "0x%x", PCI_DEV_CLASS(class));
+}
+
+void
+__pci_bar_read(struct twimap* map)
+{
+    struct pci_device* pcidev = twimap_data(map, struct pci_device*);
+    int bar_index = twimap_index(map, int);
+
+    struct pci_base_addr* bar = &pcidev->bar[bar_index];
+
+    if (!bar->start && !bar->size) {
+        twimap_printf(map, "[%d] not present \n", bar_index);
+        return;
+    }
+
+    twimap_printf(
+      map, "[%d] base=%.8p, size=%.8p, ", bar_index, bar->start, bar->size);
+
+    if ((bar->type & BAR_TYPE_MMIO)) {
+        twimap_printf(map, "mmio");
+        if ((bar->type & BAR_TYPE_CACHABLE)) {
+            twimap_printf(map, ", prefetchable");
+        }
+    } else {
+        twimap_printf(map, "io");
+    }
+
+    twimap_printf(map, "\n");
+}
+
+int
+__pci_bar_gonext(struct twimap* map)
+{
+    if (twimap_index(map, int) >= 5) {
+        return 0;
+    }
+    map->index += 1;
+    return 1;
+}
+
+void
+pci_build_fsmapping()
+{
+    struct twifs_node *pci_class = twifs_dir_node(NULL, "pci"), *pci_dev;
     struct pci_device *pos, *n;
+    struct twimap* map;
     llist_for_each(pos, n, &pci_devices, dev_chain)
     {
-        kprintf(KINFO "(B%xh:D%xh:F%xh) Dev %x:%x, Class 0x%x\n",
-                PCI_BUS_NUM(pos->cspace_base),
-                PCI_SLOT_NUM(pos->cspace_base),
-                PCI_FUNCT_NUM(pos->cspace_base),
-                PCI_DEV_VENDOR(pos->device_info),
-                PCI_DEV_DEVID(pos->device_info),
-                PCI_DEV_CLASS(pos->class_info));
-
-        kprintf(KINFO "\t IRQ: %d, INT#x: %d\n",
-                PCI_INTR_IRQ(pos->intr_info),
-                PCI_INTR_PIN(pos->intr_info));
-#ifdef PCI_PRINT_BAR_LISTING
-        uint32_t bar;
-        for (size_t i = 1; i <= 6; i++) {
-            size_t size = pci_bar_sizing(pos, &bar, i);
-            if (!bar)
-                continue;
-            if (PCI_BAR_MMIO(bar)) {
-                kprintf(KINFO "\t BAR#%d (MMIO) %p [%d]\n",
-                        i,
-                        PCI_BAR_ADDR_MM(bar),
-                        size);
-            } else {
-                kprintf(KINFO "\t BAR#%d (I/O) %p [%d]\n",
-                        i,
-                        PCI_BAR_ADDR_IO(bar),
-                        size);
-            }
-        }
-#endif
-        if (pos->msi_loc) {
-            kprintf(KINFO "\t MSI supported (@%xh)\n", pos->msi_loc);
-        }
+        pci_dev = twifs_dir_node(pci_class,
+                                 "%.2d:%.2d:%.2d.%.4x:%.4x",
+                                 PCI_BUS_NUM(pos->cspace_base),
+                                 PCI_SLOT_NUM(pos->cspace_base),
+                                 PCI_FUNCT_NUM(pos->cspace_base),
+                                 PCI_DEV_VENDOR(pos->device_info),
+                                 PCI_DEV_DEVID(pos->device_info));
+
+        map = twifs_mapping(pci_dev, pos, "config");
+        map->read = __pci_read_cspace;
+
+        map = twifs_mapping(pci_dev, pos, "revision");
+        map->read = __pci_read_revid;
+
+        map = twifs_mapping(pci_dev, pos, "class");
+        map->read = __pci_read_class;
+
+        map = twifs_mapping(pci_dev, pos, "io_bases");
+        map->read = __pci_bar_read;
+        map->go_next = __pci_bar_gonext;
     }
 }
 
@@ -241,4 +313,6 @@ pci_init()
     }
     // Otherwise, fallback to use legacy PCI 3.0 method.
     pci_probe();
+
+    pci_build_fsmapping();
 }
\ No newline at end of file
index 57c04ca6d4661a9b19cc87cf754065482532a5ec..95d5fb80f0c17d12b1c1028c1977d1a0dbdd4480 100644 (file)
@@ -56,6 +56,16 @@ typedef unsigned int pci_reg_t;
 // PCI device header format
 // Ref: "PCI Local Bus Specification, Rev.3, Section 6.1"
 
+#define BAR_TYPE_MMIO 0x1
+#define BAR_TYPE_CACHABLE 0x2
+
+struct pci_base_addr
+{
+    uint32_t start;
+    uint32_t size;
+    uint32_t type;
+};
+
 struct pci_device
 {
     struct llist_header dev_chain;
@@ -64,6 +74,7 @@ struct pci_device
     uint32_t cspace_base;
     uint32_t msi_loc;
     uint16_t intr_info;
+    struct pci_base_addr bar[6];
 };
 
 // PCI Configuration Space (C-Space) r/w:
@@ -91,9 +102,6 @@ pci_write_cspace(uint32_t base, int offset, pci_reg_t data)
 void
 pci_init();
 
-void
-pci_print_device();
-
 /**
  * @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备
  * 类型代码请参阅: PCI LB Spec. Appendix D.
index d97f0285968d09e16bac247760d29b2157381280..9af99e9f811279dc477c4fa1e41b784f60d07022 100644 (file)
@@ -4,10 +4,10 @@
 #include <stddef.h>
 
 size_t
-__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs);
+__ksprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs);
 
 size_t
-sprintf(char* buffer, char* fmt, ...);
+ksprintf(char* buffer, char* fmt, ...);
 size_t
-snprintf(char* buffer, size_t n, char* fmt, ...);
+ksnprintf(char* buffer, size_t n, char* fmt, ...);
 #endif /* __LUNAIX_STDIO_H */
index fcb0df5286167ebf9a43586efe30da7fa13f6b43..dc4e6e1f1bcb605a81adba289dc33b7ebe15e34c 100644 (file)
@@ -36,7 +36,7 @@ streq(const char* a, const char* b);
 void
 strrtrim(char* str);
 
-void*
+char*
 strltrim_safe(char* str);
 
 #endif /* __LUNAIX_STRING_H */
index 40935f9f630bb79da872ea7874606e743630647c..df481d82c32bb245986ee80bba0fe4081b8c5c99 100644 (file)
@@ -44,4 +44,10 @@ block_init();
 int
 block_mount_disk(struct hba_device* hd_dev);
 
+void
+blk_mapping_init();
+
+void
+blk_set_blkmapping(struct block_dev* bdev);
+
 #endif /* __LUNAIX_BLOCK_H */
index 4c8c794f8a1026851d5583c232eb1cf0491b6acd..f5a24a7bdab924bd9d286998f7b8217814051823 100644 (file)
@@ -1,24 +1,20 @@
 #ifndef __LUNAIX_CONSTANTS_H
 #define __LUNAIX_CONSTANTS_H
 
-#define KSTACK_SIZE (64 << 10)
+#define MEM_1MB 0x100000
+#define MEM_4MB 0x400000
+
+#define KSTACK_SIZE MEM_1MB
 #define KSTACK_START ((0x3FFFFFU - KSTACK_SIZE) + 1)
 #define KSTACK_TOP 0x3FFFF0U
 
 #define KERNEL_MM_BASE 0xC0000000
-#define MEM_1MB 0x100000
-#define MEM_4MB 0x400000
 
 #define KCODE_MAX_SIZE MEM_4MB
-#define KHEAP_START (KERNEL_MM_BASE + KCODE_MAX_SIZE)
-#define KHEAP_SIZE_MB 256
-
-#define PROC_TABLE_SIZE_MB 4
-#define PROC_START (KHEAP_START + (KHEAP_SIZE_MB * MEM_1MB))
+// #define KHEAP_START (KERNEL_MM_BASE + KCODE_MAX_SIZE)
+// #define KHEAP_SIZE_MB 256
 
-#define VGA_BUFFER_VADDR (PROC_START + (PROC_TABLE_SIZE_MB * MEM_1MB))
-#define VGA_BUFFER_PADDR 0xB8000
-#define VGA_BUFFER_SIZE 4096
+#define VGA_FRAMEBUFFER 0xB8000
 
 #define KCODE_SEG 0x08
 #define KDATA_SEG 0x10
index 414809a233aff8aa6d69c63eb8c8feb793456b42..c456df41bc6c08b960d66667a091e7ee54e0e859 100644 (file)
@@ -5,24 +5,40 @@
 
 #include <lunaix/ds/hstr.h>
 #include <lunaix/ds/llist.h>
+#include <lunaix/types.h>
+
+#define DEV_STRUCT_MAGIC 0x5645444c
+
+#define DEV_MSKIF 0x00000003
+
+#define DEV_IFVOL 0x0 // volumetric (block) device
+#define DEV_IFSEQ 0x1 // sequential (character) device
+#define DEV_IFCAT 0x2 // a device category (as device groupping)
 
 typedef unsigned int dev_t;
 
 struct device
 {
-    struct llist_header dev_list;
+    uint32_t magic;
+    struct llist_header siblings;
+    struct llist_header children;
     struct device* parent;
     struct hstr name;
     dev_t dev_id;
+    int dev_type;
     char name_val[DEVICE_NAME_SIZE];
     void* underlay;
-    void* fs_node;
     int (*read)(struct device* dev, void* buf, size_t offset, size_t len);
     int (*write)(struct device* dev, void* buf, size_t offset, size_t len);
+    int (*exec_cmd)(struct device* dev, uint32_t req, va_list args);
 };
 
-void
-device_init();
+struct device*
+device_add(struct device* parent,
+           void* underlay,
+           char* name_fmt,
+           uint32_t type,
+           va_list args);
 
 struct device*
 device_addseq(struct device* parent, void* underlay, char* name_fmt, ...);
@@ -30,7 +46,22 @@ device_addseq(struct device* parent, void* underlay, char* name_fmt, ...);
 struct device*
 device_addvol(struct device* parent, void* underlay, char* name_fmt, ...);
 
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...);
+
 void
 device_remove(struct device* dev);
 
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id);
+
+struct device*
+device_getbyhname(struct device* root_dev, struct hstr* name);
+
+struct device*
+device_getbyname(struct device* root_dev, const char* name, size_t len);
+
+struct device*
+device_getbyoffset(struct device* root_dev, int pos);
+
 #endif /* __LUNAIX_DEVICE_H */
index faa56a6ceee5cae0abe21dbf1b90a8a39def4cda..160365d6c3db97bbee27dbf90f005ca0086a81d7 100644 (file)
@@ -3,6 +3,11 @@
 
 #define DIRENT_NAME_MAX_LEN 256
 
+#define DT_FILE 0x0
+#define DT_DIR 0x1
+#define DT_SYMLINK 0x2
+#define DT_PIPE 0x2
+
 struct dirent
 {
     unsigned int d_type;
index 3a21824624220eab6e92a2c9260bb600550c451b..b6c0dec765a78055ead1a00465085b95c66d4388 100644 (file)
@@ -23,6 +23,15 @@ fifo_backone(struct fifo_buf* fbuf);
 size_t
 fifo_putone(struct fifo_buf* fbuf, uint8_t data);
 
+size_t
+fifo_readone_async(struct fifo_buf* fbuf, uint8_t* data);
+
+void
+fifo_set_rdptr(struct fifo_buf* fbuf, size_t rdptr);
+
+void
+fifo_set_wrptr(struct fifo_buf* fbuf, size_t wrptr);
+
 void
 fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags);
 
@@ -32,4 +41,7 @@ fifo_write(struct fifo_buf* fbuf, void* data, size_t count);
 size_t
 fifo_read(struct fifo_buf* fbuf, void* buf, size_t count);
 
+void
+fifo_clear(struct fifo_buf* fbuf);
+
 #endif /* __LUNAIX_FIFO_BUF_H */
index 22e0f931b3e22fb9cad6c29963dc6f8b18b958ca..a4797c34d3f889ab9c0e970ed693607ee7953fbe 100644 (file)
@@ -67,6 +67,12 @@ llist_empty(struct llist_header* elem)
     return elem->next == elem && elem->prev == elem;
 }
 
+#define DEFINE_LLIST(name)                                                     \
+    struct llist_header name = (struct llist_header)                           \
+    {                                                                          \
+        .prev = &name, .next = &name                                           \
+    }
+
 /**
  * list_entry - get the struct for this entry
  * @ptr:       the &struct list_head pointer.
index 5e166e55ac2456c503e559caaef0b5a19ca193e3..97101ef4ce68090c086fc7d61020964a2e81659b 100644 (file)
@@ -2,25 +2,33 @@
 #define __LUNAIX_MUTEX_H
 
 #include "semaphore.h"
-
-// TODO: implement mutex lock
-
-typedef struct sem_t mutex_t;
-
-static inline void mutex_init(mutex_t *mutex) {
-    sem_init(mutex, 1);
+#include <lunaix/types.h>
+
+typedef struct mutex_s
+{
+    struct sem_t sem;
+    pid_t owner;
+} mutex_t;
+
+static inline void
+mutex_init(mutex_t* mutex)
+{
+    sem_init(&mutex->sem, 1);
 }
 
-static inline unsigned int mutex_on_hold(mutex_t *mutex) {
-    return !atomic_load(&mutex->counter);
+static inline int
+mutex_on_hold(mutex_t* mutex)
+{
+    return !atomic_load(&mutex->sem.counter);
 }
 
-static inline void mutex_lock(mutex_t *mutex) {
-    sem_wait(mutex);
-}
+void
+mutex_lock(mutex_t* mutex);
 
-static inline void mutex_unlock(mutex_t *mutex) {
-    sem_post(mutex);
-}
+void
+mutex_unlock(mutex_t* mutex);
+
+void
+mutex_unlock_for(mutex_t* mutex, pid_t pid);
 
 #endif /* __LUNAIX_MUTEX_H */
diff --git a/lunaix-os/includes/lunaix/ds/rwlock.h b/lunaix-os/includes/lunaix/ds/rwlock.h
new file mode 100644 (file)
index 0000000..7dda9ad
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __LUNAIX_RWLOCK_H
+#define __LUNAIX_RWLOCK_H
+
+#include "mutex.h"
+#include "waitq.h"
+#include <stdatomic.h>
+
+typedef struct rwlock_s
+{
+    atomic_uint readers;
+    atomic_flag writer;
+    waitq_t waiting_readers;
+    waitq_t waiting_writers;
+} rwlock_t;
+
+void
+rwlock_begin_read(rwlock_t* rwlock);
+
+void
+rwlock_end_read(rwlock_t* rwlock);
+
+void
+rwlock_begin_write(rwlock_t* rwlock);
+
+void
+rwlock_end_write(rwlock_t* rwlock);
+
+#endif /* __LUNAIX_RWLOCK_H */
diff --git a/lunaix-os/includes/lunaix/ds/waitq.h b/lunaix-os/includes/lunaix/ds/waitq.h
new file mode 100644 (file)
index 0000000..4014d05
--- /dev/null
@@ -0,0 +1,32 @@
+#ifndef __LUNAIX_CODVAR_H
+#define __LUNAIX_CODVAR_H
+
+#include <lunaix/ds/llist.h>
+
+typedef struct waitq
+{
+    struct llist_header waiters;
+} waitq_t;
+
+static inline void
+waitq_init(waitq_t* waitq)
+{
+    llist_init_head(&waitq->waiters);
+}
+
+static inline int
+waitq_empty(waitq_t* waitq)
+{
+    return llist_empty(&waitq->waiters);
+}
+
+void
+pwait(waitq_t* queue);
+
+void
+pwake_one(waitq_t* queue);
+
+void
+pwake_all(waitq_t* queue);
+
+#endif /* __LUNAIX_CODVAR_H */
index 099d47ed94378936e164f02f7566a22b80a66eba..539f0a8aa0d8ccd658e522751319606440f936b8 100644 (file)
@@ -44,7 +44,7 @@
 #define VFS_VALID_CHAR(chr)                                                    \
     (('A' <= (chr) && (chr) <= 'Z') || ('a' <= (chr) && (chr) <= 'z') ||       \
      ('0' <= (chr) && (chr) <= '9') || (chr) == '.' || (chr) == '_' ||         \
-     (chr) == '-')
+     (chr) == '-' || (chr) == ':')
 
 #define unlock_inode(inode) mutex_unlock(&inode->lock)
 #define lock_inode(inode)                                                      \
@@ -172,6 +172,18 @@ struct v_fd
     int flags;
 };
 
+// FIXME how do we invalidate corresponding v_dnodes given the v_inode?
+/*
+    Consider taskfs, which is Lunaix's speak of Linux's procfs, that allow
+    info of every process being accessible via file system. Each process's
+    creation will result a creation of a directory under the root of task fs
+    with it's pid as name. But that dir must delete when process is killed, and
+    such deletion does not mediated by vfs itself, so there is a need of cache
+    syncing.
+    And this is also the case of all ramfs where argumentation to file tree is
+    performed by third party.
+*/
+
 struct v_inode
 {
     inode_t id;
@@ -185,12 +197,13 @@ struct v_inode
     uint32_t link_count;
     uint32_t lb_usage;
     uint32_t fsize;
+    void* data; // 允许底层FS绑定他的一些专有数据
+    struct llist_header aka_dnodes;
     struct llist_header xattrs;
     struct v_superblock* sb;
     struct hlist_node hash_list;
     struct lru_node lru;
     struct pcache* pg_cache;
-    void* data; // 允许底层FS绑定他的一些专有数据
     struct v_inode_ops* ops;
     struct v_file_ops* default_fops;
 };
@@ -216,6 +229,7 @@ struct v_dnode
     struct v_inode* inode;
     struct v_dnode* parent;
     struct hlist_node hash_list;
+    struct llist_header aka_list;
     struct llist_header children;
     struct llist_header siblings;
     struct v_superblock* super_block;
@@ -250,7 +264,7 @@ struct pcache_pg
     uint32_t flags;
     uint32_t fpos;
 };
-/* --- file system manager --- */
+
 void
 fsm_init();
 
@@ -269,6 +283,9 @@ fsm_get(const char* fs_name);
 void
 vfs_init();
 
+void
+vfs_export_attributes();
+
 struct v_dnode*
 vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
 
@@ -318,6 +335,9 @@ vfs_mkdir(const char* path, struct v_dnode** dentry);
 int
 vfs_open(struct v_dnode* dnode, struct v_file** file);
 
+int
+vfs_pclose(struct v_file* file, pid_t pid);
+
 int
 vfs_close(struct v_file* file);
 
@@ -357,6 +377,18 @@ vfs_dup_fd(struct v_fd* old, struct v_fd** new);
 int
 vfs_getfd(int fd, struct v_fd** fd_s);
 
+int
+vfs_get_dtype(int itype);
+
+void
+vfs_ref_dnode(struct v_dnode* dnode);
+
+void
+vfs_unref_dnode(struct v_dnode* dnode);
+
+int
+vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth);
+
 void
 pcache_init(struct pcache* pcache);
 
@@ -369,7 +401,7 @@ pcache_new_page(struct pcache* pcache, uint32_t index);
 void
 pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg);
 
-struct pcache_pg*
+int
 pcache_get_page(struct pcache* pcache,
                 uint32_t index,
                 uint32_t* offset,
diff --git a/lunaix-os/includes/lunaix/fs/devfs.h b/lunaix-os/includes/lunaix/fs/devfs.h
new file mode 100644 (file)
index 0000000..324706c
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __LUNAIX_DEVFS_H
+#define __LUNAIX_DEVFS_H
+
+void
+devfs_init();
+
+#endif /* __LUNAIX_DEVFS_H */
diff --git a/lunaix-os/includes/lunaix/fs/taskfs.h b/lunaix-os/includes/lunaix/fs/taskfs.h
new file mode 100644 (file)
index 0000000..0d50be3
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef __LUNAIX_TASKFS_H
+#define __LUNAIX_TASKFS_H
+
+#include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
+
+struct task_attribute
+{
+    struct llist_header siblings;
+    struct hlist_node attrs;
+    struct hstr key;
+    struct twimap* map_file;
+    char key_val[32];
+};
+
+void
+taskfs_init();
+
+void
+taskfs_export_attr(const char* key, struct twimap* attr_map_file);
+
+struct task_attribute*
+taskfs_get_attr(struct hstr* key);
+
+void
+taskfs_invalidate(pid_t pid);
+
+#endif /* __LUNAIX_TASKFS_H */
index f4614d8f72d4fe4e9f3a1a42664f059f1ed4cabc..a8117ef7cddb61ff4c67b59598c45365ef128691 100644 (file)
@@ -2,6 +2,8 @@
 #define __LUNAIX_TWIFS_H
 
 #include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
+#include <lunaix/spike.h>
 
 struct twifs_node
 {
@@ -9,6 +11,7 @@ struct twifs_node
     inode_t ino_id;
     void* data;
     uint32_t itype;
+    char name_val[VFS_NAME_MAXLEN];
     struct llist_header children;
     struct llist_header siblings;
     struct
@@ -24,25 +27,29 @@ struct twifs_node
     } ops;
 };
 
+#define twinode_getdata(inode, type)                                           \
+    ({                                                                         \
+        struct twifs_node* twinode = (struct twifs_node*)(inode)->data;        \
+        assert(twinode);                                                       \
+        (type) twinode->data;                                                  \
+    })
+
 void
 twifs_init();
 
 struct twifs_node*
-twifs_file_node(struct twifs_node* parent,
-                const char* name,
-                int name_len,
-                uint32_t itype);
+twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args);
 
 struct twifs_node*
-twifs_dir_node(struct twifs_node* parent,
-               const char* name,
-               int name_len,
-               uint32_t itype);
+twifs_file_node(struct twifs_node* parent, const char* fmt, ...);
 
 struct twifs_node*
-twifs_toplevel_node(const char* name, int name_len, uint32_t itype);
+twifs_dir_node(struct twifs_node* parent, const char* fmt, ...);
 
 int
 twifs_rm_node(struct twifs_node* node);
 
+struct twimap*
+twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...);
+
 #endif /* __LUNAIX_TWIFS_H */
diff --git a/lunaix-os/includes/lunaix/fs/twimap.h b/lunaix-os/includes/lunaix/fs/twimap.h
new file mode 100644 (file)
index 0000000..7adbc53
--- /dev/null
@@ -0,0 +1,37 @@
+#ifndef __LUNAIX_TWIMAP_H
+#define __LUNAIX_TWIMAP_H
+
+#include <lunaix/types.h>
+
+#define twimap_index(twimap, type) ((type)((twimap)->index))
+#define twimap_data(twimap, type) ((type)((twimap)->data))
+
+extern struct v_file_ops twimap_file_ops;
+
+struct twimap
+{
+    void* index;
+    void* buffer;
+    void* data;
+    size_t size_acc;
+    void (*read)(struct twimap* mapping);
+    int (*go_next)(struct twimap* mapping);
+    void (*reset)(struct twimap* mapping);
+};
+
+int
+twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos);
+
+void
+twimap_printf(struct twimap* mapping, const char* fmt, ...);
+
+int
+twimap_memcpy(struct twimap* mapping, const void* src, const size_t len);
+
+int
+twimap_memappend(struct twimap* mapping, const void* src, const size_t len);
+
+struct twimap*
+twimap_create(void* data);
+
+#endif /* __LUNAIX_TWIMAP_H */
diff --git a/lunaix-os/includes/lunaix/input.h b/lunaix-os/includes/lunaix/input.h
new file mode 100644 (file)
index 0000000..872ea04
--- /dev/null
@@ -0,0 +1,57 @@
+#ifndef __LUNAIX_INPUT_H
+#define __LUNAIX_INPUT_H
+
+#include <lunaix/clock.h>
+#include <lunaix/device.h>
+#include <lunaix/ds/llist.h>
+#include <lunaix/ds/waitq.h>
+#include <lunaix/types.h>
+
+// event should propagate further
+#define INPUT_EVT_NEXT 0
+// event should be captured here
+#define INPUT_EVT_CATCH 1
+
+// key pressed (key-type device)
+#define PKT_PRESS 0x1
+// key released (key-type device)
+#define PKT_RELEASE 0x2
+// vector (e.g. mice wheel scroll, mice maneuver)
+#define PKT_VECTOR 0x3
+
+struct input_evt_pkt
+{
+    uint32_t pkt_type;  // packet type
+    uint32_t scan_code; // hardware raw code
+    uint32_t sys_code;  // driver translated code
+    time_t timestamp;   // event timestamp
+};
+
+struct input_device
+{
+    struct device* dev_if;            // device interface
+    struct input_evt_pkt current_pkt; // recieved event packet
+    waitq_t readers;                  // reader wait queue
+};
+
+typedef int (*input_evt_cb)(struct input_device* dev);
+
+struct input_evt_chain
+{
+    struct llist_header chain;
+    input_evt_cb evt_cb;
+};
+
+void
+input_init();
+
+void
+input_fire_event(struct input_device* idev, struct input_evt_pkt* pkt);
+
+void
+input_add_listener(input_evt_cb listener);
+
+struct input_device*
+input_add_device(char* name_fmt, ...);
+
+#endif /* __LUNAIX_INPUT_H */
diff --git a/lunaix-os/includes/lunaix/ioctl.h b/lunaix-os/includes/lunaix/ioctl.h
new file mode 100644 (file)
index 0000000..e074bba
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef __LUNAIX_IOCTL_H
+#define __LUNAIX_IOCTL_H
+
+#include <lunaix/syscall.h>
+
+#define IOREQ(cmd, arg_num) ((((cmd)&0xffff) << 8) | ((arg_num)&0xff))
+
+#define IOCMD(req) ((req) >> 8)
+
+#define IOARGNUM(req) ((req)&0xff)
+
+#define TIOCGPGRP IOREQ(1, 0)
+#define TIOCSPGRP IOREQ(1, 1)
+#define TIOCCLSBUF IOREQ(2, 0)
+#define TIOCFLUSH IOREQ(3, 0)
+
+__LXSYSCALL2_VARG(int, ioctl, int, fd, int, req);
+
+#endif /* __LUNAIX_IOCTL_H */
index 2dd40dd6df093af64196ad4229e949ee5b668781..aa4d6581a78959275f96475ad8b316587c9721e4 100644 (file)
 typedef unsigned short kbd_keycode_t;
 typedef unsigned short kbd_kstate_t;
 
-#define KEYPAD  0x0100
-#define FN_KEY  0x0200
-#define CURSOR  0x0300
-#define MODIFR  0x0400
-#define OTHERS  0xff00
+#define KEYPAD 0x0100
+#define FN_KEY 0x0200
+#define CURSOR 0x0300
+#define MODIFR 0x0400
+#define OTHERS 0xff00
 
-#define ON_KEYPAD(x)    ((x & 0xff) | KEYPAD)
+#define ON_KEYPAD(x) ((x & 0xff) | KEYPAD)
 
 // backspace key
-#define KEY_BS  (0x08)
+#define KEY_BS (0x08)
 
 // enter/return key
-#define KEY_LF  (0x0a)
+#define KEY_LF (0x0a)
 
 #define KEY_HTAB (0x9)
 #define KEY_SPACE (0x20)
 #define KEY_ESC (0x1b)
 
-#define KEY_F1  (0x00 | FN_KEY)
-#define KEY_F2  (0x01 | FN_KEY)
-#define KEY_F3  (0x02 | FN_KEY)
-#define KEY_F4  (0x03 | FN_KEY)
-#define KEY_F5  (0x04 | FN_KEY)
-#define KEY_F6  (0x05 | FN_KEY)
-#define KEY_F7  (0x06 | FN_KEY)
-#define KEY_F8  (0x07 | FN_KEY)
-#define KEY_F9  (0x08 | FN_KEY)
+#define KEY_F1 (0x00 | FN_KEY)
+#define KEY_F2 (0x01 | FN_KEY)
+#define KEY_F3 (0x02 | FN_KEY)
+#define KEY_F4 (0x03 | FN_KEY)
+#define KEY_F5 (0x04 | FN_KEY)
+#define KEY_F6 (0x05 | FN_KEY)
+#define KEY_F7 (0x06 | FN_KEY)
+#define KEY_F8 (0x07 | FN_KEY)
+#define KEY_F9 (0x08 | FN_KEY)
 #define KEY_F10 (0x09 | FN_KEY)
 #define KEY_F11 (0x0a | FN_KEY)
 #define KEY_F12 (0x0b | FN_KEY)
@@ -51,25 +51,25 @@ typedef unsigned short kbd_kstate_t;
 #define KEY_NUMSLK (0x0d | FN_KEY)
 #define KEY_SCRLLK (0x0e | FN_KEY)
 
-#define KEY_PG_UP       (0x0 | OTHERS)
-#define KEY_PG_DOWN     (0x1 | OTHERS)
-#define KEY_INSERT      (0x2 | OTHERS)
-#define KEY_DELETE      (0x3 | OTHERS)
-#define KEY_HOME        (0x4 | OTHERS)
-#define KEY_END         (0x5 | OTHERS)
-#define KEY_PAUSE       (0x6 | OTHERS)
-
-#define KEY_LEFT        (0x0 | CURSOR)
-#define KEY_RIGHT       (0x1 | CURSOR)
-#define KEY_UP          (0x2 | CURSOR)
-#define KEY_DOWN        (0x3 | CURSOR)
-
-#define KEY_LSHIFT       (0x0 | MODIFR)
-#define KEY_RSHIFT       (0x1 | MODIFR)
-#define KEY_LCTRL        (0x2 | MODIFR)
-#define KEY_RCTRL        (0x3 | MODIFR)
-#define KEY_LALT         (0x4 | MODIFR)
-#define KEY_RALT         (0x5 | MODIFR)
+#define KEY_PG_UP (0x0 | OTHERS)
+#define KEY_PG_DOWN (0x1 | OTHERS)
+#define KEY_INSERT (0x2 | OTHERS)
+#define KEY_DELETE (0x3 | OTHERS)
+#define KEY_HOME (0x4 | OTHERS)
+#define KEY_END (0x5 | OTHERS)
+#define KEY_PAUSE (0x6 | OTHERS)
+
+#define KEY_LEFT (0x0 | CURSOR)
+#define KEY_RIGHT (0x1 | CURSOR)
+#define KEY_UP (0x2 | CURSOR)
+#define KEY_DOWN (0x3 | CURSOR)
+
+#define KEY_LSHIFT (0x0 | MODIFR)
+#define KEY_RSHIFT (0x1 | MODIFR)
+#define KEY_LCTRL (0x2 | MODIFR)
+#define KEY_RCTRL (0x3 | MODIFR)
+#define KEY_LALT (0x4 | MODIFR)
+#define KEY_RALT (0x5 | MODIFR)
 
 #define KBD_KEY_FRELEASED 0x0
 #define KBD_KEY_FPRESSED 0x1
@@ -84,15 +84,4 @@ typedef unsigned short kbd_kstate_t;
 #define KBD_KEY_FLALT_HELD 0x100
 #define KBD_KEY_FRALT_HELD 0x200
 
-typedef unsigned char kbd_scancode_t;
-
-struct kdb_keyinfo_pkt {
-    kbd_scancode_t scancode;
-    kbd_keycode_t keycode;
-    kbd_kstate_t state;
-    time_t timestamp;
-};
-
-int kbd_recv_key(struct kdb_keyinfo_pkt* key_event);
-
 #endif /* __LUNAIX_KEYBOARD_H */
index d9644289087005b811496b2adf08048da86a37d3..9f2ef9ec75da987aa7e6d2b6222de50184f4dff7 100644 (file)
@@ -15,6 +15,10 @@ __LXSYSCALL(pid_t, getpid)
 
 __LXSYSCALL(pid_t, getppid)
 
+__LXSYSCALL(pid_t, getpgid)
+
+__LXSYSCALL2(pid_t, setpgid, pid_t, pid, pid_t, pgid)
+
 __LXSYSCALL1(void, _exit, int, status)
 
 __LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
index 02e21980db359d98b40b30806cb6a0ba93a463b6..fbf59a462d65568c71fa2708c74873a3d4b394fc 100644 (file)
@@ -1,6 +1,13 @@
 #ifndef __LUNAIX_LXCONSOLE_H
 #define __LUNAIX_LXCONSOLE_H
 
+#define TCINTR 0x03 // ETX
+#define TCEOF 0x04  // EOT
+#define TCBS 0x08   // BS
+#define TCLF 0x0A   // LF
+#define TCCR 0x0D   // CR
+#define TCSTOP 0x1A // SUB
+
 void
 lxconsole_init();
 
index 0312c45d381ac7854a802cb248eb792ac496cbf6..81321f87b898c7ce1b6bd05b50f35d342dc5d8ff 100644 (file)
@@ -7,6 +7,10 @@
 
 #define PILE_CACHELINE 1
 
+struct cake_pile;
+
+typedef void (*pile_cb)(struct cake_pile*, void*);
+
 struct cake_pile
 {
     struct llist_header piles;
@@ -20,6 +24,8 @@ struct cake_pile
     unsigned int pieces_per_cake;
     unsigned int pg_per_cake;
     char pile_name[PILE_NAME_MAXLEN];
+
+    pile_cb ctor;
 };
 
 typedef unsigned int piece_index_t;
@@ -49,6 +55,9 @@ cake_new_pile(char* name,
               unsigned int pg_per_cake,
               int options);
 
+void
+cake_set_constructor(struct cake_pile* pile, pile_cb ctor);
+
 /**
  * @brief 拿一块儿蛋糕
  *
@@ -70,11 +79,12 @@ cake_release(struct cake_pile* pile, void* area);
 void
 cake_init();
 
-/**
- * @brief 统计蛋糕数量 - 问问Pinkie :D
- *
- */
 void
-cake_stats();
+cake_export();
+
+/********** some handy constructor ***********/
+
+void
+cake_ctor_zeroing(struct cake_pile* pile, void* piece);
 
 #endif /* __LUNAIX_VALLOC_H */
index 8883a6b70eab665206c42d63f23678205cac1e7f..9458277eac1db33a61b8bfc6fd31f929bb7d2724 100644 (file)
@@ -99,7 +99,7 @@ extern void __pg_mount_point;
 
 /* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */
 #define PG_MOUNT_RANGE(l1_index) (701 <= l1_index && l1_index <= 703)
-#define PD_MOUNT_1 (VGA_BUFFER_VADDR + MEM_4MB)
+#define PD_MOUNT_1 (KERNEL_MM_BASE + MEM_4MB)
 #define PG_MOUNT_BASE (PD_MOUNT_1 + MEM_4MB)
 #define PG_MOUNT_1 (PG_MOUNT_BASE)
 #define PG_MOUNT_2 (PG_MOUNT_BASE + 0x1000)
index 08a0d56c6660e2f72d6776b9e8e849a69d54c229..3ebaa984aa1770e69f43dc78c6b6b0d5f7fad07d 100644 (file)
@@ -44,7 +44,6 @@
 #define PS2_DELAY 1000
 
 #define PS2_CMD_QUEUE_SIZE 8
-#define PS2_KBD_RECV_BUFFER_SIZE 8
 
 #define PS2_NO_ARG 0xff00
 
@@ -70,14 +69,6 @@ struct ps2_cmd_queue
     mutex_t mutex;
 };
 
-struct ps2_key_buffer
-{
-    struct kdb_keyinfo_pkt buffer[PS2_KBD_RECV_BUFFER_SIZE];
-    int read_ptr;
-    int buffered_len;
-    mutex_t mutex;
-};
-
 /**
  * @brief 向PS/2控制器的控制端口(0x64)发送指令并等待返回代码。
  * 注意,对于没有返回代码的命令请使用`ps2_post_cmd`,否则会造成死锁。
index 18cddb94f6d29e4ad947e495af8c329dd74972ab..c7b925ef59651532d3da80ab6a6f0fbc68fe0f28 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <arch/x86/interrupts.h>
 #include <lunaix/clock.h>
+#include <lunaix/ds/waitq.h>
 #include <lunaix/fs.h>
 #include <lunaix/mm/mm.h>
 #include <lunaix/signal.h>
@@ -13,7 +14,7 @@
 // 虽然内核不是进程,但为了区分,这里使用Pid=-1来指代内核。这主要是方便物理页所有权检查。
 #define KERNEL_PID -1
 
-#define PS_STOPPED 0
+#define PS_READY 0
 #define PS_RUNNING 1
 #define PS_TERMNAT 2
 #define PS_DESTROY 4
@@ -57,9 +58,11 @@ struct proc_info
 
     /* ---- critical section end ---- */
 
+    struct llist_header tasks;
     struct llist_header siblings;
     struct llist_header children;
     struct llist_header grp_member;
+    waitq_t waitqueue;
 
     struct
     {
index 021b55e9e68a58830d5b08b2dd1b6fa8e4fcdd79..f31eab52daa9ce7ddc34b2d220812b64c9a27985 100644 (file)
@@ -3,9 +3,12 @@
 
 #define SCHED_TIME_SLICE 300
 
+#define PROC_TABLE_SIZE 8192
+#define MAX_PROCESS (PROC_TABLE_SIZE / sizeof(uintptr_t))
+
 struct scheduler
 {
-    struct proc_info* _procs;
+    struct proc_info** _procs;
     int procs_index;
     unsigned int ptable_len;
 };
index 0e381b48a63d5e54dbca6abfa3f87fb5a81c3365..cc105b469ccede5f2ff622a155c0c24a7b463232 100644 (file)
@@ -17,7 +17,7 @@
 #define EEXIST -12
 #define EBADF -13
 #define ENOTSUP -14
-#define ENXIO -15
+#define EIO -15
 #define ELOOP -16
 #define ENOTEMPTY -17
 #define EROFS -18
index 98f5585a16fb202a931765f5716d2773ef17071e..8a523ad2c4ea787a2b866b56dee567865643fabc 100644 (file)
 #define __SYSCALL_fgetxattr 46
 #define __SYSCALL_fsetxattr 47
 
+#define __SYSCALL_ioctl 48
+#define __SYSCALL_getpgid 49
+#define __SYSCALL_setpgid 50
+
 #define __SYSCALL_MAX 0x100
 
 #ifndef __ASM__
@@ -130,5 +134,13 @@ syscall_install();
         asm("\n" ::"b"(p1), "c"(p2), "d"(p3), "D"(p4));                        \
         ___DOINT33(__SYSCALL_##name, rettype)                                  \
     }
+
+#define __LXSYSCALL2_VARG(rettype, name, t1, p1, t2, p2)                       \
+    static rettype name(__PARAM_MAP2(t1, p1, t2, p2), ...)                     \
+    {                                                                          \
+        void* _last = (void*)&p2 + sizeof(void*);                              \
+        asm("\n" ::"b"(p1), "c"(p2), "d"(_last));                              \
+        ___DOINT33(__SYSCALL_##name, rettype)                                  \
+    }
 #endif
 #endif /* __LUNAIX_SYSCALL_H */
index e5eaa34b940ad7c9ce1295250858918639bca89d..24d088fbd3f6665580e53fe8c4e32112292b319c 100644 (file)
@@ -9,8 +9,8 @@ struct console
     struct lx_timer* flush_timer;
     struct fifo_buf output;
     struct fifo_buf input;
-    unsigned int erd_pos;
-    unsigned int lines;
+    size_t wnd_start;
+    size_t lines;
 };
 
 #endif /* __LUNAIX_CONSOLE_H */
index 518d3760a8def0797976d627417ddeb38b60400d..96fe4859c5a1fe3ece1c6579bbc9025b98f8133b 100644 (file)
@@ -1,5 +1,8 @@
 #ifndef __LUNAIX_TTY_H
 #define __LUNAIX_TTY_H
+
+#include <lunaix/ds/fifo.h>
+
 typedef unsigned short vga_attribute;
 
 #define VGA_COLOR_BLACK 0
@@ -31,8 +34,8 @@ tty_set_theme(vga_attribute fg, vga_attribute bg);
 vga_attribute
 tty_get_theme();
 
-size_t
-tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size);
+void
+tty_flush_buffer(struct fifo_buf* buf);
 
 void
 tty_clear_line(int line_num);
index 3069a833bdb9b78d9eb20889fa012a8ffcbf17b7..fbe7e1e33880dd539f92c8ccb576214478bb7417 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef __LUNAIX_TYPES_H
 #define __LUNAIX_TYPES_H
 
+#include <stdarg.h>
 #include <stddef.h>
 #include <stdint.h>
 
diff --git a/lunaix-os/includes/ulibc/stdio.h b/lunaix-os/includes/ulibc/stdio.h
new file mode 100644 (file)
index 0000000..e9496a8
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef __LUNAIX_USTDIO_H
+#define __LUNAIX_USTDIO_H
+
+#define stdout 0
+#define stdin 1
+
+void
+printf(const char* fmt, ...);
+
+#endif /* __LUNAIX_USTDIO_H */
index 813490c2fe84363b9f49c6cadb3eafe444505c01..402ceeaf2648090ef030d6542538d81504f7abb8 100644 (file)
@@ -79,7 +79,7 @@ intr_routine_apic_error(const isr_param* param)
 {
     uint32_t error_reg = apic_read_reg(APIC_ESR);
     char buf[32];
-    sprintf(buf, "APIC error, ESR=0x%x", error_reg);
+    ksprintf(buf, "APIC error, ESR=0x%x", error_reg);
     console_flush();
     __print_panic_msg(buf, param);
     spin();
index 6df3182622bce973794b360cb01cb91f5e138843..fcd52cc26480058f3a83b2144e8b46ee0b2c949a 100644 (file)
@@ -108,14 +108,8 @@ int
 do_kernel(v_mapping* mapping)
 {
     uintptr_t addr = mapping->va;
-    if (addr >= KHEAP_START && addr < PROC_START) {
-        // This is kernel heap page
-        uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
-        *mapping->pte = (*mapping->pte & 0xfff) | pa | PG_PRESENT;
-        cpu_invplg(mapping->pte);
-        cpu_invplg(addr);
-        goto done;
-    }
+
+    // TODO
 
     return 0;
 done:
index b8d021973cbec4eda95d8daf7c78d6c53a86ad36..34b4330fbfdcf6bffbcad956584793f3e1f09fa8 100644 (file)
@@ -55,6 +55,9 @@
         .long __lxsys_setxattr      /* 45 */
         .long __lxsys_fgetxattr
         .long __lxsys_fsetxattr
+        .long __lxsys_ioctl
+        .long __lxsys_getpgid
+        .long __lxsys_setpgid       /* 50 */
         2:
         .rept __SYSCALL_MAX - (2b - 1b)/4
             .long 0
diff --git a/lunaix-os/kernel/block/blk_mapping.c b/lunaix-os/kernel/block/blk_mapping.c
new file mode 100644 (file)
index 0000000..f6d1346
--- /dev/null
@@ -0,0 +1,111 @@
+#include <lunaix/block.h>
+#include <lunaix/fs/twifs.h>
+
+static struct twifs_node* blk_root;
+
+void
+blk_mapping_init()
+{
+    blk_root = twifs_dir_node(NULL, "block");
+}
+
+void
+__blk_rd_size(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    size_t secsize = bdev->hd_dev->block_size;
+    twimap_printf(map, "%u", (bdev->end_lba - bdev->base_lba) * secsize);
+}
+
+void
+__blk_rd_secsize(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    size_t secsize = bdev->hd_dev->block_size;
+    twimap_printf(map, "%u", secsize);
+}
+
+void
+__blk_rd_range(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    twimap_printf(
+      map, "%u,%u", (uint32_t)bdev->base_lba, (uint32_t)bdev->end_lba);
+}
+
+void
+__blk_rd_model(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    twimap_printf(map, "%s", bdev->hd_dev->model);
+}
+
+void
+__blk_rd_serial(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    twimap_printf(map, "%s", bdev->hd_dev->serial_num);
+}
+
+void
+__blk_rd_status(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    twimap_printf(map, "%p", bdev->hd_dev->last_result.status);
+}
+
+void
+__blk_rd_error(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    twimap_printf(map, "%p", bdev->hd_dev->last_result.error);
+}
+
+void
+__blk_rd_sense_key(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    twimap_printf(map, "%p", bdev->hd_dev->last_result.sense_key);
+}
+
+void
+__blk_rd_wwid(struct twimap* map)
+{
+    struct block_dev* bdev = twimap_data(map, struct block_dev*);
+    uint32_t h = bdev->hd_dev->wwn >> 32;
+    uint32_t l = (uint32_t)bdev->hd_dev->wwn;
+    twimap_printf(map, "%x%x", h, l);
+}
+
+void
+blk_set_blkmapping(struct block_dev* bdev)
+{
+    struct twifs_node* dev_root = twifs_dir_node(blk_root, bdev->bdev_id);
+
+    struct twimap* map = twifs_mapping(dev_root, bdev, "size");
+    map->read = __blk_rd_size;
+
+    map = twifs_mapping(dev_root, bdev, "secsize");
+    map->read = __blk_rd_secsize;
+
+    map = twifs_mapping(dev_root, bdev, "range");
+    map->read = __blk_rd_range;
+
+    map = twifs_mapping(dev_root, bdev, "model");
+    map->read = __blk_rd_model;
+
+    map = twifs_mapping(dev_root, bdev, "serial");
+    map->read = __blk_rd_serial;
+
+    map = twifs_mapping(dev_root, bdev, "status");
+    map->read = __blk_rd_status;
+
+    map = twifs_mapping(dev_root, bdev, "error");
+    map->read = __blk_rd_error;
+
+    map = twifs_mapping(dev_root, bdev, "sense-key");
+    map->read = __blk_rd_sense_key;
+
+    map = twifs_mapping(dev_root, bdev, "wwid");
+    map->read = __blk_rd_wwid;
+}
\ No newline at end of file
similarity index 89%
rename from lunaix-os/kernel/block.c
rename to lunaix-os/kernel/block/block.c
index b855910ffc18fc12a1506e105540dda74fc62964..936ce2a7644a67dd3ed666d066fd3d0907df390a 100644 (file)
@@ -36,6 +36,8 @@ block_init()
     lbd_pile = cake_new_pile("block_dev", sizeof(struct block_dev), 1, 0);
     dev_registry = vcalloc(sizeof(struct block_dev*), MAX_DEV);
     free_slot = 0;
+
+    blk_mapping_init();
 }
 
 int
@@ -44,13 +46,14 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len)
     int errno;
     struct block_dev* bdev = (struct block_dev*)dev->underlay;
     size_t acc_size = 0, rd_size = 0, bsize = bdev->hd_dev->block_size,
-           rd_block = offset / bsize, r = offset % bsize;
+           rd_block = offset / bsize, r = offset % bsize,
+           max_blk = (size_t)bdev->hd_dev->max_lba;
     void* block = vzalloc(bsize);
 
-    while (acc_size < len) {
+    while (acc_size < len && rd_block < max_blk) {
         if (!bdev->hd_dev->ops.read_buffer(
               bdev->hd_dev, rd_block, block, bsize)) {
-            errno = ENXIO;
+            errno = EIO;
             goto error;
         }
         rd_size = MIN(len - acc_size, bsize - r);
@@ -61,7 +64,7 @@ __block_read(struct device* dev, void* buf, size_t offset, size_t len)
     }
 
     vfree(block);
-    return rd_block;
+    return acc_size;
 
 error:
     vfree(block);
@@ -82,7 +85,7 @@ __block_write(struct device* dev, void* buf, size_t offset, size_t len)
         memcpy(block + r, buf + acc_size, wr_size);
         if (!bdev->hd_dev->ops.write_buffer(
               bdev->hd_dev, wr_block, block, bsize)) {
-            errno = ENXIO;
+            errno = EIO;
             break;
         }
         acc_size += wr_size;
@@ -112,6 +115,7 @@ block_mount_disk(struct hba_device* hd_dev)
         goto error;
     }
 
+    blk_set_blkmapping(bdev);
     return errno;
 
 error:
@@ -119,6 +123,7 @@ error:
             hd_dev->model,
             hd_dev->serial_num,
             -errno);
+    return errno;
 }
 
 int
@@ -133,6 +138,7 @@ __block_register(struct block_dev* bdev)
     dev->read = __block_read;
 
     bdev->dev = dev;
+    strcpy(bdev->bdev_id, dev->name_val);
     dev_registry[free_slot++] = bdev;
     return 1;
 }
\ No newline at end of file
index 0d62a79b38e36bd6887621e8af6d20c328d007ca..54ffd97b20147425350d7ed44ac4028cf4955e6f 100644 (file)
@@ -2,32 +2,29 @@
 #include <lunaix/fctrl.h>
 #include <lunaix/lunistd.h>
 #include <lunaix/proc.h>
-#include <lunaix/syslog.h>
-
-LOG_MODULE("RDDIR")
 
 void
 _readdir_main()
 {
     int fd = open("/dev/./../dev/.", 0);
     if (fd == -1) {
-        kprintf(KERROR "fail to open (%d)\n", geterrno());
+        printf("fail to open (%d)\n", geterrno());
         return;
     }
 
     char path[129];
     int len = realpathat(fd, path, 128);
     if (len < 0) {
-        kprintf(KERROR "fail to read (%d)\n", geterrno());
+        printf("fail to read (%d)\n", geterrno());
     } else {
         path[len] = 0;
-        kprintf("%s\n", path);
+        printf("%s\n", path);
     }
 
     struct dirent ent = { .d_offset = 0 };
 
     while (readdir(fd, &ent) == 1) {
-        kprintf(KINFO "%s\n", ent.d_name);
+        printf("%s\n", ent.d_name);
     }
 
     close(fd);
diff --git a/lunaix-os/kernel/demos/input_test.c b/lunaix-os/kernel/demos/input_test.c
new file mode 100644 (file)
index 0000000..5f2a904
--- /dev/null
@@ -0,0 +1,39 @@
+#include <lunaix/fctrl.h>
+#include <lunaix/foptions.h>
+#include <lunaix/input.h>
+#include <lunaix/lunistd.h>
+#include <lunaix/proc.h>
+#include <ulibc/stdio.h>
+
+#define STDIN 1
+#define STDOUT 0
+
+void
+input_test()
+{
+    int fd = open("/dev/input/i8042-kbd", 0);
+
+    if (fd < 0) {
+        printf("fail to open (%d)", geterrno());
+        return;
+    }
+
+    struct input_evt_pkt event;
+
+    while (read(fd, &event, sizeof(event)) > 0) {
+        char* action;
+        if (event.pkt_type == PKT_PRESS) {
+            action = "pressed";
+        } else {
+            action = "release";
+        }
+
+        printf("%u: %s '%c', class=0x%x, scan=%x\n",
+               event.timestamp,
+               action,
+               event.sys_code & 0xff,
+               (event.sys_code & 0xff00) >> 8,
+               event.scan_code);
+    }
+    return;
+}
\ No newline at end of file
index 0ebe696eb48c5e1cc79fcb5c018945a5a8f61683..643452c81f58b0a145c5457f428311c7d9ae89f6 100644 (file)
@@ -2,12 +2,7 @@
 #include <lunaix/foptions.h>
 #include <lunaix/lunistd.h>
 #include <lunaix/proc.h>
-#include <lunaix/syslog.h>
-
-LOG_MODULE("IOTEST")
-
-#define STDIN 1
-#define STDOUT 0
+#include <ulibc/stdio.h>
 
 void
 _iotest_main()
@@ -20,14 +15,12 @@ _iotest_main()
     // 切换工作目录至 /dev
     int errno = chdir("/dev");
     if (errno) {
-        write(STDOUT, "fail to chdir", 15);
+        write(stdout, "fail to chdir", 15);
         return;
     }
 
     if (getcwd(read_out, sizeof(read_out))) {
-        write(STDOUT, "current working dir: ", 22);
-        write(STDOUT, read_out, 256);
-        write(STDOUT, "\n", 2);
+        printf("current working dir: %s\n", read_out);
     }
 
     // sda 设备 - 硬盘
@@ -36,7 +29,7 @@ _iotest_main()
     int fd = open("./sda", 0);
 
     if (fd < 0) {
-        kprintf(KERROR "fail to open (%d)\n", geterrno());
+        printf("fail to open (%d)\n", geterrno());
         return;
     }
 
@@ -52,24 +45,21 @@ _iotest_main()
     lseek(fd, 4 * 4096, FSEEK_SET);
     write(fd, test_sequence, sizeof(test_sequence));
 
-    write(STDOUT, "input: ", 8);
-    int size = read(STDIN, read_out, 256);
+    printf("input: ");
+    int size = read(stdin, read_out, 256);
+
+    printf("your said: %s\n", read_out);
 
-    write(STDOUT, "your input: ", 13);
-    write(STDOUT, read_out, size);
     write(fd, read_out, size);
-    write(STDOUT, "\n", 1);
 
     // 读出我们写的内容
     lseek(fd, 512, FSEEK_SET);
     read(fd, read_out, sizeof(read_out));
 
     // 将读出的内容直接写入tty设备
-    write(STDOUT, read_out, sizeof(read_out));
-    write(STDOUT, "\n", 1);
+    write(stdout, read_out, sizeof(read_out));
+    write(stdout, "\n", 1);
 
     // 关闭文件,这同时会将页缓存中的数据下发到底层驱动
     close(fd);
-
-    kprint_hex(read_out, sizeof(read_out));
 }
\ No newline at end of file
index 616a38e9e090773b1b39fba1038dd0eb3d37ad6d..27d78142ef0129b8d806eb5e6d066c8469061cad 100644 (file)
@@ -2,22 +2,20 @@
 #include <lunaix/proc.h>
 #include <lunaix/signal.h>
 #include <lunaix/spike.h>
-#include <lunaix/syslog.h>
 #include <lunaix/types.h>
-
-LOG_MODULE("SIGDEMO")
+#include <ulibc/stdio.h>
 
 void __USER__
 sigchild_handler(int signum)
 {
-    kprintf(KINFO "SIGCHLD received\n");
+    printf("SIGCHLD received\n");
 }
 
 void __USER__
 sigsegv_handler(int signum)
 {
     pid_t pid = getpid();
-    kprintf(KWARN "SIGSEGV received on process %d\n", pid);
+    printf("SIGSEGV received on process %d\n", pid);
     _exit(signum);
 }
 
@@ -25,7 +23,7 @@ void __USER__
 sigalrm_handler(int signum)
 {
     pid_t pid = getpid();
-    kprintf(KWARN "I, pid %d, have received an alarm!\n", pid);
+    printf("I, pid %d, have received an alarm!\n", pid);
 }
 
 void __USER__
@@ -40,7 +38,7 @@ _signal_demo_main()
     int status;
     pid_t p = 0;
 
-    kprintf(KINFO "Child sleep 3s, parent pause.\n");
+    printf("Child sleep 3s, parent pause.\n");
     if (!fork()) {
         sleep(3);
         _exit(0);
@@ -48,7 +46,7 @@ _signal_demo_main()
 
     pause();
 
-    kprintf("Parent resumed on SIGCHILD\n");
+    printf("Parent resumed on SIGCHILD\n");
 
     for (int i = 0; i < 5; i++) {
         pid_t pid = 0;
@@ -58,26 +56,22 @@ _signal_demo_main()
             if (i == 3) {
                 i = *(int*)0xdeadc0de; // seg fault!
             }
-            kprintf(KINFO "%d\n", i);
+            printf("%d\n", i);
             _exit(0);
         }
-        kprintf(KINFO "Forked %d\n", pid);
+        printf("Forked %d\n", pid);
     }
 
     while ((p = wait(&status)) >= 0) {
         short code = WEXITSTATUS(status);
         if (WIFSIGNALED(status)) {
-            kprintf(KINFO "Process %d terminated by signal, exit_code: %d\n",
-                    p,
-                    code);
+            printf("Process %d terminated by signal, exit_code: %d\n", p, code);
         } else if (WIFEXITED(status)) {
-            kprintf(KINFO "Process %d exited with code %d\n", p, code);
+            printf("Process %d exited with code %d\n", p, code);
         } else {
-            kprintf(KWARN "Process %d aborted with code %d\n", p, code);
+            printf("Process %d aborted with code %d\n", p, code);
         }
     }
 
-    kprintf("done\n");
-
-    _exit(0);
+    printf("done\n");
 }
\ No newline at end of file
diff --git a/lunaix-os/kernel/demos/simple_sh.c b/lunaix-os/kernel/demos/simple_sh.c
new file mode 100644 (file)
index 0000000..3a1e1bb
--- /dev/null
@@ -0,0 +1,184 @@
+#include <lunaix/fctrl.h>
+#include <lunaix/foptions.h>
+#include <lunaix/ioctl.h>
+#include <lunaix/lunistd.h>
+#include <lunaix/proc.h>
+#include <lunaix/signal.h>
+#include <lunaix/status.h>
+
+#include <klibc/string.h>
+#include <ulibc/stdio.h>
+
+char pwd[512];
+char cat_buf[1024];
+
+/*
+    Simple shell - (actually this is not even a shell)
+    It just to make the testing more easy.
+*/
+
+void
+parse_cmdline(char* line, char** cmd, char** arg_part)
+{
+    strrtrim(line);
+    line = strltrim_safe(line);
+    int l = 0;
+    char c = 0;
+    while ((c = line[l])) {
+        if (c == ' ') {
+            line[l++] = 0;
+            break;
+        }
+        l++;
+    }
+    *cmd = line;
+    *arg_part = strltrim_safe(line + l);
+}
+
+void
+sh_printerr()
+{
+    int errno = geterrno();
+    switch (errno) {
+        case ENOTDIR:
+            printf("Error: Not a directory\n");
+            break;
+        case ENOENT:
+            printf("Error: No such file or directory\n");
+            break;
+        case EINVAL:
+            printf("Error: Invalid parameter or operation\n");
+            break;
+        case ENOTSUP:
+            printf("Error: Not supported\n");
+            break;
+        case EROFS:
+            printf("Error: File system is read only\n");
+            break;
+        case ENOMEM:
+            printf("Error: Out of memory\n");
+            break;
+        case EISDIR:
+            printf("Error: This is a directory\n");
+            break;
+        default:
+            printf("Error: (%d)\n", errno);
+            break;
+    }
+}
+
+void
+sigint_handle(int signum)
+{
+    return;
+}
+
+void
+do_cat(const char* file)
+{
+    int fd = open(file, 0);
+    if (fd < 0) {
+        sh_printerr();
+    } else {
+        int sz;
+        while ((sz = read(fd, cat_buf, 1024)) > 0) {
+            write(stdout, cat_buf, sz);
+        }
+        if (sz < 0) {
+            sh_printerr();
+        }
+        close(fd);
+        printf("\n");
+    }
+}
+
+void
+do_ls(const char* path)
+{
+    int fd = open(path, 0);
+    if (fd < 0) {
+        sh_printerr();
+    } else {
+        struct dirent ent = { .d_offset = 0 };
+        int status;
+        while ((status = readdir(fd, &ent)) == 1) {
+            if (ent.d_type == DT_DIR) {
+                printf(" \033[3m%s\033[39;49m\n", ent.d_name);
+            } else {
+                printf(" %s\n", ent.d_name);
+            }
+        }
+
+        if (status < 0)
+            sh_printerr();
+
+        close(fd);
+    }
+}
+
+void
+sh_loop()
+{
+    char buf[512];
+    char *cmd, *argpart;
+    pid_t p;
+    signal(_SIGINT, sigint_handle);
+
+    // set our shell as foreground process
+    // (unistd.h:tcsetpgrp is essentially a wrapper of this)
+    // stdout (by default, unless user did smth) is the tty we are currently at
+    ioctl(stdout, TIOCSPGRP, getpgid());
+
+    while (1) {
+        getcwd(pwd, 512);
+        printf("[\033[2m%s\033[39;49m]$ ", pwd);
+        size_t sz = read(stdin, buf, 511);
+        if (sz < 0) {
+            printf("fail to read user input (%d)\n", geterrno());
+            return;
+        }
+        buf[sz] = '\0';
+        parse_cmdline(buf, &cmd, &argpart);
+        if (cmd[0] == 0) {
+            printf("\n");
+            goto cont;
+        }
+        if (streq(cmd, "cd")) {
+            if (chdir(argpart) < 0) {
+                sh_printerr();
+            }
+            goto cont;
+        } else if (streq(cmd, "clear")) {
+            ioctl(stdout, TIOCCLSBUF);
+            goto cont;
+        } else if (streq(cmd, "ls")) {
+            if (!(p = fork())) {
+                do_ls(argpart);
+                _exit(0);
+            }
+        } else if (streq(cmd, "cat")) {
+            if (!(p = fork())) {
+                do_cat(argpart);
+                _exit(0);
+            }
+        } else {
+            printf("unknow command\n");
+            goto cont;
+        }
+        setpgid(p, getpgid());
+        waitpid(p, NULL, 0);
+    cont:
+        printf("\n");
+    }
+}
+
+void
+sh_main()
+{
+    printf("\n Simple shell. Use <PG_UP> or <PG_DOWN> to scroll.\n\n");
+    if (!fork()) {
+        sh_loop();
+        _exit(0);
+    }
+    wait(NULL);
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/device.c b/lunaix-os/kernel/device.c
deleted file mode 100644 (file)
index 017f3b3..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-#include <klibc/stdio.h>
-#include <lunaix/device.h>
-#include <lunaix/fs/twifs.h>
-#include <lunaix/mm/valloc.h>
-
-struct llist_header dev_list;
-
-static struct twifs_node* dev_root;
-
-int
-__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
-
-int
-__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos);
-
-void
-device_init()
-{
-    dev_root = twifs_toplevel_node("dev", 3, 0);
-
-    llist_init_head(&dev_list);
-}
-
-struct device*
-__device_add(struct device* parent,
-             void* underlay,
-             char* name_fmt,
-             uint32_t type,
-             va_list args)
-{
-    struct device* dev = vzalloc(sizeof(struct device));
-
-    size_t strlen =
-      __sprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
-
-    dev->name = HSTR(dev->name_val, strlen);
-    dev->parent = parent;
-    dev->underlay = underlay;
-
-    hstr_rehash(&dev->name, HSTR_FULL_HASH);
-    llist_append(&dev_list, &dev->dev_list);
-
-    struct twifs_node* dev_node =
-      twifs_file_node(dev_root, dev->name_val, strlen, type);
-    dev_node->data = dev;
-    dev_node->ops.read = __dev_read;
-    dev_node->ops.write = __dev_write;
-
-    dev->fs_node = dev_node;
-
-    return dev;
-}
-
-struct device*
-device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
-{
-    va_list args;
-    va_start(args, name_fmt);
-
-    struct device* dev =
-      __device_add(parent, underlay, name_fmt, VFS_IFSEQDEV, args);
-
-    va_end(args);
-    return dev;
-}
-
-struct device*
-device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
-{
-    va_list args;
-    va_start(args, name_fmt);
-
-    struct device* dev =
-      __device_add(parent, underlay, name_fmt, VFS_IFVOLDEV, args);
-
-    va_end(args);
-    return dev;
-}
-
-int
-__dev_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
-{
-    struct twifs_node* dev_node = (struct twifs_node*)inode->data;
-    struct device* dev = (struct device*)dev_node->data;
-
-    if (!dev->read) {
-        return ENOTSUP;
-    }
-    return dev->read(dev, buffer, fpos, len);
-}
-
-int
-__dev_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
-{
-    struct twifs_node* dev_node = (struct twifs_node*)inode->data;
-    struct device* dev = (struct device*)dev_node->data;
-
-    if (!dev->write) {
-        return ENOTSUP;
-    }
-    return dev->write(dev, buffer, fpos, len);
-}
-
-void
-device_remove(struct device* dev)
-{
-    llist_delete(&dev->dev_list);
-    twifs_rm_node((struct twifs_node*)dev->fs_node);
-    vfree(dev);
-}
\ No newline at end of file
diff --git a/lunaix-os/kernel/device/devfs.c b/lunaix-os/kernel/device/devfs.c
new file mode 100644 (file)
index 0000000..012f919
--- /dev/null
@@ -0,0 +1,162 @@
+#include <lunaix/device.h>
+#include <lunaix/dirent.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/devfs.h>
+#include <lunaix/spike.h>
+
+extern struct v_inode_ops devfs_inode_ops;
+extern struct v_file_ops devfs_file_ops;
+
+int
+devfs_read(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+    assert(inode->data);
+
+    struct device* dev = (struct device*)inode->data;
+
+    if (!dev->read) {
+        return ENOTSUP;
+    }
+
+    return dev->read(dev, buffer, fpos, len);
+}
+
+int
+devfs_write(struct v_inode* inode, void* buffer, size_t len, size_t fpos)
+{
+    assert(inode->data);
+
+    struct device* dev = (struct device*)inode->data;
+
+    if (!dev->write) {
+        return ENOTSUP;
+    }
+
+    return dev->write(dev, buffer, fpos, len);
+}
+
+int
+devfs_get_itype(struct device* dev)
+{
+    int itype = VFS_IFFILE;
+    int dev_if = dev->dev_type & DEV_MSKIF;
+    if (dev_if == DEV_IFCAT) {
+        itype = VFS_IFDIR;
+    } else if (dev_if == DEV_IFVOL) {
+        itype |= VFS_IFVOLDEV;
+    } else {
+        itype |= VFS_IFSEQDEV;
+    }
+    return itype;
+}
+
+int
+devfs_get_dtype(struct device* dev)
+{
+    switch (dev->dev_type & DEV_MSKIF) {
+        case DEV_IFCAT:
+            return DT_DIR;
+
+        default:
+            return DT_FILE;
+    }
+}
+
+int
+devfs_mknod(struct v_dnode* dnode, struct device* dev)
+{
+    assert(dev);
+
+    struct v_inode* devnod = vfs_i_find(dnode->super_block, dev->dev_id);
+    if (!devnod) {
+        if ((devnod = vfs_i_alloc(dnode->super_block))) {
+            devnod->id = dev->dev_id;
+            devnod->data = dev;
+            devnod->itype = devfs_get_itype(dev);
+
+            vfs_i_addhash(devnod);
+        } else {
+            return ENOMEM;
+        }
+    }
+
+    vfs_assign_inode(dnode, devnod);
+    return 0;
+}
+
+int
+devfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
+{
+    struct device* dev =
+      device_getbyhname((struct device*)this->data, &dnode->name);
+    if (!dev) {
+        return ENOENT;
+    }
+    return devfs_mknod(dnode, dev);
+}
+
+int
+devfs_readdir(struct v_file* file, struct dir_context* dctx)
+{
+    struct device* dev =
+      device_getbyoffset((struct device*)(file->inode->data), dctx->index);
+    if (!dev) {
+        return 0;
+    }
+    dctx->read_complete_callback(
+      dctx, dev->name.value, dev->name.len, devfs_get_dtype(dev));
+    return 1;
+}
+
+void
+devfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
+{
+    inode->ops = &devfs_inode_ops;
+    inode->default_fops = &devfs_file_ops;
+}
+
+int
+devfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
+{
+    vsb->ops.init_inode = devfs_init_inode;
+
+    struct v_inode* rootnod = vfs_i_alloc(vsb);
+
+    if (!rootnod) {
+        return ENOMEM;
+    }
+
+    rootnod->id = -1;
+    rootnod->itype = VFS_IFDIR;
+
+    vfs_i_addhash(rootnod);
+    vfs_assign_inode(mount_point, rootnod);
+
+    return 0;
+}
+
+int
+devfs_unmount(struct v_superblock* vsb)
+{
+    return 0;
+}
+
+void
+devfs_init()
+{
+    struct filesystem* fs = fsm_new_fs("devfs", 5);
+    fsm_register(fs);
+    fs->mount = devfs_mount;
+    fs->unmount = devfs_unmount;
+}
+
+struct v_inode_ops devfs_inode_ops = { .dir_lookup = devfs_dirlookup,
+                                       .open = default_inode_open,
+                                       .mkdir = default_inode_mkdir,
+                                       .rmdir = default_inode_rmdir };
+
+struct v_file_ops devfs_file_ops = { .close = default_file_close,
+                                     .read = devfs_read,
+                                     .write = devfs_write,
+                                     .seek = default_file_seek,
+                                     .readdir = devfs_readdir };
\ No newline at end of file
diff --git a/lunaix-os/kernel/device/device.c b/lunaix-os/kernel/device/device.c
new file mode 100644 (file)
index 0000000..6b901a6
--- /dev/null
@@ -0,0 +1,168 @@
+#include <klibc/stdio.h>
+#include <lunaix/device.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/twifs.h>
+#include <lunaix/ioctl.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+#include <lunaix/syscall.h>
+
+static DEFINE_LLIST(root_list);
+
+static volatile dev_t devid = 0;
+
+struct device*
+device_add(struct device* parent,
+           void* underlay,
+           char* name_fmt,
+           uint32_t type,
+           va_list args)
+{
+    struct device* dev = vzalloc(sizeof(struct device));
+
+    if (parent) {
+        assert((parent->dev_type & DEV_MSKIF) == DEV_IFCAT);
+        llist_append(&parent->children, &dev->siblings);
+    } else {
+        llist_append(&root_list, &dev->siblings);
+    }
+
+    size_t strlen =
+      __ksprintf_internal(dev->name_val, name_fmt, DEVICE_NAME_SIZE, args);
+
+    dev->magic = DEV_STRUCT_MAGIC;
+    dev->dev_id = devid++;
+    dev->name = HSTR(dev->name_val, strlen);
+    dev->parent = parent;
+    dev->underlay = underlay;
+    dev->dev_type = type;
+
+    hstr_rehash(&dev->name, HSTR_FULL_HASH);
+    llist_init_head(&dev->children);
+
+    return dev;
+}
+
+struct device*
+device_addseq(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      device_add(parent, underlay, name_fmt, DEV_IFSEQ, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_addvol(struct device* parent, void* underlay, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      device_add(parent, underlay, name_fmt, DEV_IFVOL, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_addcat(struct device* parent, char* name_fmt, ...)
+{
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev = device_add(parent, NULL, name_fmt, DEV_IFCAT, args);
+
+    va_end(args);
+    return dev;
+}
+
+struct device*
+device_getbyid(struct llist_header* devlist, dev_t id)
+{
+    devlist = devlist ? devlist : &root_list;
+    struct device *pos, *n;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (pos->dev_id == id) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+struct device*
+device_getbyhname(struct device* root_dev, struct hstr* name)
+{
+    struct llist_header* devlist = root_dev ? &root_dev->children : &root_list;
+    struct device *pos, *n;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (HSTR_EQ(&pos->name, name)) {
+            return pos;
+        }
+    }
+
+    return NULL;
+}
+
+struct device*
+device_getbyname(struct device* root_dev, const char* name, size_t len)
+{
+    struct hstr hname = HSTR(name, len);
+    hstr_rehash(&hname, HSTR_FULL_HASH);
+
+    return device_getbyhname(root_dev, &hname);
+}
+
+void
+device_remove(struct device* dev)
+{
+    llist_delete(&dev->siblings);
+    vfree(dev);
+}
+
+struct device*
+device_getbyoffset(struct device* root_dev, int offset)
+{
+    struct llist_header* devlist = root_dev ? &root_dev->children : &root_list;
+    struct device *pos, *n;
+    int off = 0;
+    llist_for_each(pos, n, devlist, siblings)
+    {
+        if (off++ >= offset) {
+            return pos;
+        }
+    }
+    return NULL;
+}
+
+__DEFINE_LXSYSCALL3(int, ioctl, int, fd, int, req, va_list, args)
+{
+    int errno;
+    struct v_fd* fd_s;
+    if ((errno = vfs_getfd(fd, &fd_s))) {
+        goto done;
+    }
+
+    struct device* dev = (struct device*)fd_s->file->inode->data;
+    if (dev->magic != DEV_STRUCT_MAGIC) {
+        errno = ENODEV;
+        goto done;
+    }
+
+    if (!dev->exec_cmd) {
+        errno = EINVAL;
+        goto done;
+    }
+
+    errno = dev->exec_cmd(dev, req, args);
+
+done:
+    return DO_STATUS_OR_RETURN(errno);
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/device/input.c b/lunaix-os/kernel/device/input.c
new file mode 100644 (file)
index 0000000..5ddf6a4
--- /dev/null
@@ -0,0 +1,85 @@
+#include <lunaix/clock.h>
+#include <lunaix/input.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+#include <lunaix/status.h>
+
+#include <klibc/string.h>
+
+static DEFINE_LLIST(listener_chain);
+
+static struct device* input_devcat = NULL;
+
+void
+input_init()
+{
+    input_devcat = device_addcat(NULL, "input");
+}
+
+void
+input_fire_event(struct input_device* idev, struct input_evt_pkt* pkt)
+{
+    pkt->timestamp = clock_systime();
+    idev->current_pkt = *pkt;
+
+    struct input_evt_chain *pos, *n;
+    llist_for_each(pos, n, &listener_chain, chain)
+    {
+        if (pos->evt_cb(idev) == INPUT_EVT_CATCH) {
+            break;
+        }
+    }
+
+    // wake up all pending readers
+    pwake_all(&idev->readers);
+}
+
+void
+input_add_listener(input_evt_cb listener)
+{
+    assert(listener);
+
+    struct input_evt_chain* chain = vzalloc(sizeof(*chain));
+    llist_append(&listener_chain, &chain->chain);
+
+    chain->evt_cb = listener;
+}
+
+int
+__input_dev_read(struct device* dev, void* buf, size_t offset, size_t len)
+{
+    struct input_device* idev = dev->underlay;
+
+    if (len < sizeof(struct input_evt_pkt)) {
+        return ERANGE;
+    }
+
+    // wait for new event
+    pwait(&idev->readers);
+
+    memcpy(buf, &idev->current_pkt, sizeof(struct input_evt_pkt));
+
+    return sizeof(struct input_evt_pkt);
+}
+
+struct input_device*
+input_add_device(char* name_fmt, ...)
+{
+    assert(input_devcat);
+
+    struct input_device* idev = vzalloc(sizeof(*idev));
+    waitq_init(&idev->readers);
+
+    va_list args;
+    va_start(args, name_fmt);
+
+    struct device* dev =
+      device_add(input_devcat, idev, name_fmt, DEV_IFSEQ, args);
+
+    idev->dev_if = dev;
+    dev->read = __input_dev_read;
+
+    va_end(args);
+
+    return idev;
+}
index 1e72e8da4b7d401d94812596da15f8447e12a3bf..252cd2dd7df55d290aa8270b588145a13eb50273 100644 (file)
@@ -15,6 +15,16 @@ fifo_init(struct fifo_buf* buf, void* data_buffer, size_t buf_size, int flags)
     mutex_init(&buf->lock);
 }
 
+void
+fifo_clear(struct fifo_buf* fbuf)
+{
+    mutex_lock(&fbuf->lock);
+    fbuf->rd_pos = 0;
+    fbuf->wr_pos = 0;
+    fbuf->free_len = fbuf->size;
+    mutex_unlock(&fbuf->lock);
+}
+
 int
 fifo_backone(struct fifo_buf* fbuf)
 {
@@ -53,6 +63,43 @@ fifo_putone(struct fifo_buf* fbuf, uint8_t data)
     return 1;
 }
 
+size_t
+fifo_readone_async(struct fifo_buf* fbuf, uint8_t* data)
+{
+    if (fbuf->free_len == fbuf->size) {
+        return 0;
+    }
+
+    uint8_t* dest = fbuf->data;
+    *data = dest[fbuf->rd_pos];
+    fbuf->rd_pos = (fbuf->rd_pos + 1) % fbuf->size;
+    fbuf->free_len++;
+
+    return 1;
+}
+
+void
+fifo_set_rdptr(struct fifo_buf* fbuf, size_t rdptr)
+{
+    fbuf->rd_pos = rdptr;
+    if (rdptr <= fbuf->wr_pos) {
+        fbuf->free_len = fbuf->size - fbuf->wr_pos + rdptr;
+    } else {
+        fbuf->free_len = rdptr - fbuf->wr_pos;
+    }
+}
+
+void
+fifo_set_wrptr(struct fifo_buf* fbuf, size_t wrptr)
+{
+    fbuf->wr_pos = wrptr;
+    if (wrptr <= fbuf->rd_pos) {
+        fbuf->free_len = fbuf->size - fbuf->rd_pos + wrptr;
+    } else {
+        fbuf->free_len = wrptr - fbuf->rd_pos;
+    }
+}
+
 size_t
 fifo_write(struct fifo_buf* fbuf, void* data, size_t count)
 {
diff --git a/lunaix-os/kernel/ds/mutex.c b/lunaix-os/kernel/ds/mutex.c
new file mode 100644 (file)
index 0000000..7bfbf10
--- /dev/null
@@ -0,0 +1,24 @@
+#include <lunaix/ds/mutex.h>
+#include <lunaix/process.h>
+
+void
+mutex_lock(mutex_t* mutex)
+{
+    sem_wait(&mutex->sem);
+    mutex->owner = __current->pid;
+}
+
+void
+mutex_unlock(mutex_t* mutex)
+{
+    mutex_unlock_for(mutex, __current->pid);
+}
+
+void
+mutex_unlock_for(mutex_t* mutex, pid_t pid)
+{
+    if (mutex->owner != pid) {
+        return;
+    }
+    sem_post(&mutex->sem);
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/ds/rwlock.c b/lunaix-os/kernel/ds/rwlock.c
new file mode 100644 (file)
index 0000000..383e4c4
--- /dev/null
@@ -0,0 +1,58 @@
+#include <lunaix/ds/rwlock.h>
+#include <lunaix/spike.h>
+
+void
+rwlock_init(rwlock_t* rwlock)
+{
+    waitq_init(&rwlock->waiting_readers);
+    waitq_init(&rwlock->waiting_writers);
+    atomic_init(&rwlock->readers, 0);
+    atomic_flag_clear(&rwlock->writer);
+}
+
+void
+rwlock_begin_read(rwlock_t* rwlock)
+{
+    while (atomic_flag_test_and_set(&rwlock->writer)) {
+        pwait(&rwlock->waiting_readers);
+    }
+    atomic_fetch_add(&rwlock->readers, 1);
+    atomic_flag_clear(&rwlock->writer);
+    pwake_all(&rwlock->waiting_readers);
+}
+
+void
+rwlock_end_read(rwlock_t* rwlock)
+{
+    assert(atomic_load(&rwlock->readers) > 0);
+    atomic_fetch_sub(&rwlock->readers, 1);
+
+    if (!atomic_load(&rwlock->readers)) {
+        pwake_one(&rwlock->waiting_writers);
+    }
+}
+
+void
+rwlock_begin_write(rwlock_t* rwlock)
+{
+    // first, acquire writer lock, prevent any incoming readers
+    while (atomic_flag_test_and_set(&rwlock->writer)) {
+        pwait(&rwlock->waiting_writers);
+    }
+
+    // then, wait for reader finish the read.
+    while (atomic_load(&rwlock->readers)) {
+        pwait(&rwlock->waiting_writers);
+    }
+}
+
+void
+rwlock_end_write(rwlock_t* rwlock)
+{
+    atomic_flag_clear(&rwlock->writer);
+    if (waitq_empty(&rwlock->waiting_writers)) {
+        pwake_all(&rwlock->waiting_readers);
+    } else {
+        pwake_one(&rwlock->waiting_writers);
+    }
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/ds/waitq.c b/lunaix-os/kernel/ds/waitq.c
new file mode 100644 (file)
index 0000000..5241a4e
--- /dev/null
@@ -0,0 +1,50 @@
+#include <lunaix/ds/waitq.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+#include <lunaix/spike.h>
+
+void
+pwait(waitq_t* queue)
+{
+    waitq_t* current_wq = &__current->waitqueue;
+    assert(llist_empty(&current_wq->waiters));
+
+    llist_append(&queue->waiters, &current_wq->waiters);
+
+    // FIXME centralize the state change.
+    __current->state = PS_BLOCKED;
+    sched_yieldk();
+}
+
+void
+pwake_one(waitq_t* queue)
+{
+    if (llist_empty(&queue->waiters)) {
+        return;
+    }
+
+    waitq_t* wq = list_entry(queue->waiters.next, waitq_t, waiters);
+    struct proc_info* proc = container_of(wq, struct proc_info, waitqueue);
+
+    assert(proc->state == PS_BLOCKED);
+    proc->state = PS_READY;
+    llist_delete(&wq->waiters);
+}
+
+void
+pwake_all(waitq_t* queue)
+{
+    if (llist_empty(&queue->waiters)) {
+        return;
+    }
+
+    struct proc_info* proc;
+    waitq_t *pos, *n;
+    llist_for_each(pos, n, &queue->waiters, waiters)
+    {
+        proc = container_of(pos, struct proc_info, waitqueue);
+
+        proc->state = PS_READY;
+        llist_delete(&pos->waiters);
+    }
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/fs/fs_export.c b/lunaix-os/kernel/fs/fs_export.c
new file mode 100644 (file)
index 0000000..13d6557
--- /dev/null
@@ -0,0 +1,47 @@
+#include <lunaix/foptions.h>
+#include <lunaix/fs.h>
+#include <lunaix/fs/twifs.h>
+
+extern struct llist_header all_mnts;
+
+void
+__mount_read(struct twimap* map)
+{
+    char path[512];
+    struct v_mount* mnt = twimap_index(map, struct v_mount*);
+    size_t len = vfs_get_path(mnt->mnt_point, path, 511, 0);
+    path[len] = '\0';
+    twimap_printf(map, "%s at %s", mnt->super_block->fs->fs_name.value, path);
+    if ((mnt->flags & MNT_RO)) {
+        twimap_printf(map, ", ro");
+    } else {
+        twimap_printf(map, ", rw");
+    }
+    twimap_printf(map, "\n");
+}
+
+int
+__mount_next(struct twimap* map)
+{
+    struct v_mount* mnt = twimap_index(map, struct v_mount*);
+    if (mnt->list.next == &all_mnts) {
+        return 0;
+    }
+    map->index = container_of(mnt->list.next, struct v_mount, list);
+    return 1;
+}
+
+void
+__mount_reset(struct twimap* map)
+{
+    map->index = container_of(all_mnts.next, struct v_mount, list);
+}
+
+void
+vfs_export_attributes()
+{
+    struct twimap* map = twifs_mapping(NULL, NULL, "mounts");
+    map->read = __mount_read;
+    map->go_next = __mount_next;
+    map->reset = __mount_reset;
+}
\ No newline at end of file
index 74fdef7baa3e929702e9d444893a66b822b3ab1a..5b3a35d040ac9f3a7bea4f92c8f878fd98e98132 100644 (file)
@@ -1,5 +1,7 @@
 #include <lunaix/fs.h>
+#include <lunaix/fs/devfs.h>
 #include <lunaix/fs/ramfs.h>
+#include <lunaix/fs/taskfs.h>
 #include <lunaix/fs/twifs.h>
 
 void
@@ -7,5 +9,8 @@ fsm_register_all()
 {
     ramfs_init();
     twifs_init();
-    // Add more fs implementation
+    devfs_init();
+    taskfs_init();
+
+    // ... more fs implementation
 }
\ No newline at end of file
index 7b83757e91b26740ac43426bbda421934a226750..ff8d46b5bb91a3a1ca8e32e9bdf28a7c26087592 100644 (file)
@@ -4,7 +4,7 @@
 #include <lunaix/process.h>
 #include <lunaix/types.h>
 
-static struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts };
+struct llist_header all_mnts = { .next = &all_mnts, .prev = &all_mnts };
 
 struct v_mount*
 vfs_create_mount(struct v_mount* parent, struct v_dnode* mnt_point)
@@ -145,12 +145,12 @@ vfs_mount_at(const char* fs_name,
     }
 
     struct v_mount* parent_mnt = mnt_point->mnt;
-    struct v_superblock* sb = vfs_sb_alloc();
+    struct v_superblock *sb = vfs_sb_alloc(), *old_sb = mnt_point->super_block;
     sb->dev = device;
+    mnt_point->super_block = sb;
 
     int errno = 0;
     if (!(errno = fs->mount(sb, mnt_point))) {
-        mnt_point->super_block = sb;
         sb->fs = fs;
         sb->root = mnt_point;
 
@@ -167,6 +167,7 @@ vfs_mount_at(const char* fs_name,
     return errno;
 
 cleanup:
+    mnt_point->super_block = old_sb;
     vfs_sb_free(sb);
     return errno;
 }
@@ -233,7 +234,7 @@ __DEFINE_LXSYSCALL4(int,
 
     // By our convention.
     // XXX could we do better?
-    struct device* device = (struct device*)dev->data;
+    struct device* device = (struct device*)dev->inode->data;
 
     if (!(dev->inode->itype & VFS_IFVOLDEV) || !device) {
         errno = ENOTDEV;
index ea5b1c59b4aa5da7e54d59d467d8875025ac632c..c80d7134d22596d89a7f53addcfb59929c3da8a5 100644 (file)
@@ -33,7 +33,10 @@ __vfs_walk(struct v_dnode* start,
                 panick("vfs: no root");
             }
         }
-        i++;
+
+        if (path[0] == VFS_PATH_DELIM) {
+            i++;
+        }
     }
 
     assert(start);
@@ -71,9 +74,7 @@ __vfs_walk(struct v_dnode* start,
 
         if (!lookahead && (walk_options & VFS_WALK_PARENT)) {
             if (component) {
-                component->hash = name.hash;
-                component->len = j;
-                strcpy(component->value, fname_buffer);
+                hstrcpy(component, &name);
             }
             break;
         }
index 0094ec4bc0c7fde1e67f2a799e180ff302f67c1e..c27f78ba6bf8282139c0f487eb761acb4e456f9d 100644 (file)
@@ -76,7 +76,7 @@ pcache_set_dirty(struct pcache* pcache, struct pcache_pg* pg)
     }
 }
 
-struct pcache_pg*
+int
 pcache_get_page(struct pcache* pcache,
                 uint32_t index,
                 uint32_t* offset,
@@ -140,7 +140,7 @@ pcache_read(struct v_inode* inode, void* data, uint32_t len, uint32_t fpos)
             errno = inode->default_fops->read(inode, pg->pg, PG_SIZE, pg->fpos);
             if (errno >= 0 && errno < PG_SIZE) {
                 // EOF
-                len = buf_off + errno;
+                len = MIN(len, buf_off + errno);
             } else if (errno < 0) {
                 break;
             }
index 3dcbd5908882243fcdd49ee19afa3a1c9d585d1c..a1018daa7fcd22dd04503d5a39b490d31dd7fdb7 100644 (file)
@@ -42,6 +42,7 @@
 volatile static inode_t ino = 0;
 
 extern const struct v_inode_ops ramfs_inode_ops;
+extern const struct v_file_ops ramfs_file_ops;
 
 int
 ramfs_readdir(struct v_file* file, struct dir_context* dctx)
@@ -51,8 +52,10 @@ ramfs_readdir(struct v_file* file, struct dir_context* dctx)
     llist_for_each(pos, n, &file->dnode->children, siblings)
     {
         if (i++ >= dctx->index) {
-            dctx->read_complete_callback(
-              dctx, pos->name.value, pos->name.len, 0);
+            dctx->read_complete_callback(dctx,
+                                         pos->name.value,
+                                         pos->name.len,
+                                         vfs_get_dtype(pos->inode->itype));
             return 1;
         }
     }
@@ -88,7 +91,7 @@ ramfs_inode_init(struct v_superblock* vsb, struct v_inode* inode)
 {
     inode->id = ino++;
     inode->ops = &ramfs_inode_ops;
-    inode->default_fops = &default_file_ops;
+    inode->default_fops = &ramfs_file_ops;
 }
 
 int
@@ -127,4 +130,10 @@ const struct v_inode_ops ramfs_inode_ops = { .mkdir = ramfs_mkdir,
                                                default_inode_dirlookup,
                                              .create = ramfs_create,
                                              .open = default_inode_open,
-                                             .rename = default_inode_rename };
\ No newline at end of file
+                                             .rename = default_inode_rename };
+
+const struct v_file_ops ramfs_file_ops = { .readdir = ramfs_readdir,
+                                           .close = default_file_close,
+                                           .read = default_file_read,
+                                           .write = default_file_write,
+                                           .seek = default_file_seek };
\ No newline at end of file
index d452d0b876606363388884d3fdac96413cbfdb09..437ab0ba541560d81b1d12aeb495818e499ed995 100644 (file)
@@ -8,12 +8,15 @@
  * @copyright Copyright (c) 2022
  *
  */
+#include <klibc/stdio.h>
 #include <klibc/string.h>
 #include <lunaix/clock.h>
 #include <lunaix/fs.h>
 #include <lunaix/fs/twifs.h>
+#include <lunaix/fs/twimap.h>
 #include <lunaix/mm/cake.h>
 #include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
 
 static struct twifs_node* fs_root;
 
@@ -33,7 +36,9 @@ __twifs_new_node(struct twifs_node* parent,
     struct twifs_node* node = cake_grab(twi_pile);
     memset(node, 0, sizeof(*node));
 
-    node->name = HSTR(name, name_len);
+    strncpy(node->name_val, name, VFS_NAME_MAXLEN);
+
+    node->name = HSTR(node->name_val, MIN(name_len, VFS_NAME_MAXLEN));
     node->itype = itype;
     node->ino_id = inode_id++;
     hstr_rehash(&node->name, HSTR_FULL_HASH);
@@ -120,24 +125,24 @@ __twifs_dirlookup(struct v_inode* inode, struct v_dnode* dnode)
 
     struct twifs_node* child_node = __twifs_get_node(twi_node, &dnode->name);
     if (child_node) {
-        struct v_inode* inode = vfs_i_find(inode->sb, child_node->ino_id);
-        if (inode) {
+        struct v_inode* child_inode = vfs_i_find(inode->sb, child_node->ino_id);
+        if (child_inode) {
             goto done;
         }
 
-        if (!(inode = vfs_i_alloc(inode->sb))) {
+        if (!(child_inode = vfs_i_alloc(inode->sb))) {
             return ENOENT;
         }
 
-        inode->id = child_node->ino_id;
-        inode->itype = child_node->itype;
-        inode->data = child_node;
+        child_inode->id = child_node->ino_id;
+        child_inode->itype = child_node->itype;
+        child_inode->data = child_node;
 
-        vfs_i_addhash(inode);
+        vfs_i_addhash(child_inode);
 
     done:
         dnode->data = child_node->data;
-        vfs_assign_inode(dnode, inode);
+        vfs_assign_inode(dnode, child_inode);
         return 0;
     }
     return ENOENT;
@@ -155,7 +160,7 @@ __twifs_iterate_dir(struct v_file* file, struct dir_context* dctx)
         if (counter++ >= dctx->index) {
             dctx->index = counter;
             dctx->read_complete_callback(
-              dctx, pos->name.value, pos->name.len, pos->itype);
+              dctx, pos->name.value, pos->name.len, vfs_get_dtype(pos->itype));
             return 1;
         }
     }
@@ -185,40 +190,41 @@ twifs_rm_node(struct twifs_node* node)
 }
 
 struct twifs_node*
-twifs_file_node(struct twifs_node* parent,
-                const char* name,
-                int name_len,
-                uint32_t itype)
+twifs_file_node_vargs(struct twifs_node* parent, const char* fmt, va_list args)
 {
-    struct twifs_node* twi_node =
-      __twifs_new_node(parent, name, name_len, VFS_IFFILE | itype);
+    char buf[VFS_NAME_MAXLEN];
+    size_t len = __ksprintf_internal(buf, fmt, VFS_NAME_MAXLEN, args);
 
-    return twi_node;
+    return __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFSEQDEV);
 }
 
 struct twifs_node*
-twifs_dir_node(struct twifs_node* parent,
-               const char* name,
-               int name_len,
-               uint32_t itype)
-{
-    struct hstr hname = HSTR(name, name_len);
-    hstr_rehash(&hname, HSTR_FULL_HASH);
-    struct twifs_node* node = __twifs_get_node(parent, &hname);
-    if (node) {
-        return node;
-    }
+twifs_file_node(struct twifs_node* parent, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
 
-    struct twifs_node* twi_node =
-      __twifs_new_node(parent, name, name_len, VFS_IFDIR | itype);
+    struct twifs_node* twi_node = twifs_file_node_vargs(parent, fmt, args);
+
+    va_end(args);
 
     return twi_node;
 }
 
 struct twifs_node*
-twifs_toplevel_node(const char* name, int name_len, uint32_t itype)
+twifs_dir_node(struct twifs_node* parent, const char* fmt, ...)
 {
-    return twifs_dir_node(fs_root, name, name_len, itype);
+    va_list args;
+    va_start(args, fmt);
+
+    char buf[VFS_NAME_MAXLEN];
+    size_t len = __ksprintf_internal(buf, fmt, VFS_NAME_MAXLEN, args);
+    struct twifs_node* twi_node =
+      __twifs_new_node(parent ? parent : fs_root, buf, len, VFS_IFDIR);
+
+    va_end(args);
+
+    return twi_node;
 }
 
 void
@@ -237,6 +243,30 @@ twifs_init()
     fs_root = twifs_dir_node(NULL, NULL, 0, 0);
 }
 
+int
+__twifs_twimap_file_read(struct v_inode* inode,
+                         void* buf,
+                         size_t len,
+                         size_t fpos)
+{
+    struct twimap* map = twinode_getdata(inode, struct twimap*);
+    return twimap_read(map, buf, len, fpos);
+}
+
+struct twimap*
+twifs_mapping(struct twifs_node* parent, void* data, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    struct twimap* map = twimap_create(data);
+    struct twifs_node* node = twifs_file_node_vargs(parent, fmt, args);
+    node->ops.read = __twifs_twimap_file_read;
+    node->data = map;
+
+    return map;
+}
+
 const struct v_file_ops twifs_file_ops = { .close = default_file_close,
                                            .read = __twifs_fread,
                                            .write = __twifs_fwrite,
diff --git a/lunaix-os/kernel/fs/twimap.c b/lunaix-os/kernel/fs/twimap.c
new file mode 100644 (file)
index 0000000..009cdf3
--- /dev/null
@@ -0,0 +1,117 @@
+#include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/spike.h>
+
+#include <klibc/stdio.h>
+#include <klibc/string.h>
+
+#define TWIMAP_BUFFER_SIZE 1024
+
+void
+__twimap_default_reset(struct twimap* map)
+{
+    map->index = NULL;
+}
+
+int
+__twimap_default_gonext(struct twimap* map)
+{
+    return 0;
+}
+
+int
+__twimap_file_read(struct v_inode* inode, void* buf, size_t len, size_t fpos)
+{
+    struct twimap* map = (struct twimap*)(inode->data);
+    return twimap_read(map, buf, len, fpos);
+}
+
+int
+twimap_read(struct twimap* map, void* buffer, size_t len, size_t fpos)
+{
+    map->buffer = valloc(TWIMAP_BUFFER_SIZE);
+    map->reset(map);
+
+    // FIXME what if TWIMAP_BUFFER_SIZE is not big enough?
+
+    size_t pos = 0;
+    do {
+        map->size_acc = 0;
+        map->read(map);
+        pos += map->size_acc;
+    } while (pos <= fpos && map->go_next(map));
+
+    if (pos <= fpos) {
+        vfree(map->buffer);
+        return 0;
+    }
+
+    if (!fpos) {
+        pos = 0;
+    }
+
+    size_t acc_size = MIN(len, map->size_acc - (pos - fpos)), rdlen = acc_size;
+    memcpy(buffer, map->buffer + (pos - fpos), acc_size);
+
+    while (acc_size < len && map->go_next(map)) {
+        map->size_acc = 0;
+        map->read(map);
+        rdlen = MIN(len - acc_size, map->size_acc);
+        memcpy(buffer + acc_size, map->buffer, rdlen);
+        acc_size += rdlen;
+    }
+
+    vfree(map->buffer);
+    return acc_size;
+}
+
+void
+twimap_printf(struct twimap* mapping, const char* fmt, ...)
+{
+    va_list args;
+    va_start(args, fmt);
+
+    char* buf = mapping->buffer + mapping->size_acc;
+
+    mapping->size_acc +=
+      __ksprintf_internal(buf, fmt, TWIMAP_BUFFER_SIZE, args);
+
+    va_end(args);
+}
+
+int
+twimap_memcpy(struct twimap* mapping, const void* src, const size_t len)
+{
+    mapping->size_acc = MIN(TWIMAP_BUFFER_SIZE, len);
+    memcpy(mapping->buffer, src, mapping->size_acc);
+
+    return mapping->size_acc;
+}
+
+int
+twimap_memappend(struct twimap* mapping, const void* src, const size_t len)
+{
+    size_t cpy_len = MIN(TWIMAP_BUFFER_SIZE - mapping->size_acc, len);
+    memcpy(mapping->buffer + mapping->size_acc, src, cpy_len);
+    mapping->size_acc += cpy_len;
+
+    return cpy_len;
+}
+
+struct twimap*
+twimap_create(void* data)
+{
+    struct twimap* map = vzalloc(sizeof(struct twimap));
+    map->reset = __twimap_default_reset;
+    map->go_next = __twimap_default_gonext;
+    map->data = data;
+
+    return map;
+}
+
+struct v_file_ops twimap_file_ops = { .close = default_file_close,
+                                      .read = __twimap_file_read,
+                                      .readdir = default_file_readdir,
+                                      .seek = default_file_seek,
+                                      .write = default_file_write };
\ No newline at end of file
index 83bd0bd26a3271e6d2719e591d8ee9caa48a36e0..df374cdf41ad41fcf3cd15592a8419c1f22c4c3d 100644 (file)
@@ -163,6 +163,7 @@ vfs_dcache_remove(struct v_dnode* dnode)
     assert(dnode->ref_count == 1);
 
     llist_delete(&dnode->siblings);
+    llist_delete(&dnode->aka_list);
     hlist_delete(&dnode->hash_list);
 
     dnode->parent = NULL;
@@ -225,8 +226,10 @@ void
 vfs_assign_inode(struct v_dnode* assign_to, struct v_inode* inode)
 {
     if (assign_to->inode) {
+        llist_delete(&assign_to->aka_list);
         assign_to->inode->link_count--;
     }
+    llist_append(&inode->aka_dnodes, &assign_to->aka_list);
     assign_to->inode = inode;
     inode->link_count++;
 }
@@ -254,12 +257,35 @@ vfs_link(struct v_dnode* to_link, struct v_dnode* name)
 }
 
 int
-vfs_close(struct v_file* file)
+vfs_pclose(struct v_file* file, pid_t pid)
 {
     int errno = 0;
-    if (!(errno = file->ops->close(file))) {
+    if (file->ref_count > 1) {
+        atomic_fetch_sub(&file->ref_count, 1);
+    } else if (!(errno = file->ops->close(file))) {
         atomic_fetch_sub(&file->dnode->ref_count, 1);
         file->inode->open_count--;
+
+        // Prevent dead lock.
+        // This happened when process is terminated while blocking on read.
+        // In that case, the process is still holding the inode lock and it will
+        // never get released.
+        /*
+         * The unlocking should also include ownership check.
+         *
+         * To see why, consider two process both open the same file both with
+         * fd=x.
+         *      Process A: busy on reading x
+         *      Process B: do nothing with x
+         * Assuming that, after a very short time, process B get terminated
+         * while process A is still busy in it's reading business. By this
+         * design, the inode lock of this file x is get released by B rather
+         * than A. And this will cause a probable race condition on A if other
+         * process is writing to this file later after B exit.
+         */
+        if (mutex_on_hold(&file->inode->lock)) {
+            mutex_unlock_for(&file->inode->lock, pid);
+        }
         mnt_chillax(file->dnode->mnt);
 
         pcache_commit_all(file->inode);
@@ -268,6 +294,12 @@ vfs_close(struct v_file* file)
     return errno;
 }
 
+int
+vfs_close(struct v_file* file)
+{
+    return vfs_pclose(file, __current->pid);
+}
+
 int
 vfs_fsync(struct v_file* file)
 {
@@ -358,6 +390,7 @@ vfs_d_alloc(struct v_dnode* parent, struct hstr* name)
     memset(dnode, 0, sizeof(*dnode));
     llist_init_head(&dnode->children);
     llist_init_head(&dnode->siblings);
+    llist_init_head(&dnode->aka_list);
     mutex_init(&dnode->lock);
 
     dnode->ref_count = ATOMIC_VAR_INIT(0);
@@ -367,6 +400,7 @@ vfs_d_alloc(struct v_dnode* parent, struct hstr* name)
 
     if (parent) {
         dnode->super_block = parent->super_block;
+        dnode->mnt = parent->mnt;
     }
 
     lru_use_one(dnode_lru, &dnode->lru);
@@ -439,6 +473,7 @@ vfs_i_alloc(struct v_superblock* sb)
     memset(inode, 0, sizeof(*inode));
     mutex_init(&inode->lock);
     llist_init_head(&inode->xattrs);
+    llist_init_head(&inode->aka_dnodes);
 
     sb->ops.init_inode(sb, inode);
 
@@ -486,6 +521,8 @@ __vfs_try_locate_file(const char* path,
     char name_str[VFS_NAME_MAXLEN];
     struct hstr name = HSTR(name_str, 0);
     int errno;
+
+    name_str[0] = 0;
     if ((errno = vfs_walk_proc(path, fdir, &name, VFS_WALK_PARENT))) {
         return errno;
     }
@@ -558,9 +595,7 @@ __DEFINE_LXSYSCALL1(int, close, int, fd)
         goto done_err;
     }
 
-    if (fd_s->file->ref_count > 1) {
-        fd_s->file->ref_count--;
-    } else if ((errno = vfs_close(fd_s->file))) {
+    if ((errno = vfs_close(fd_s->file))) {
         goto done_err;
     }
 
@@ -606,9 +641,9 @@ __DEFINE_LXSYSCALL2(int, readdir, int, fd, struct dirent*, dent)
                                   __vfs_readdir_callback };
         errno = 1;
         if (dent->d_offset == 0) {
-            __vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, 0);
+            __vfs_readdir_callback(&dctx, vfs_dot.value, vfs_dot.len, DT_DIR);
         } else if (dent->d_offset == 1) {
-            __vfs_readdir_callback(&dctx, vfs_ddot.value, vfs_ddot.len, 0);
+            __vfs_readdir_callback(&dctx, vfs_ddot.value, vfs_ddot.len, DT_DIR);
         } else {
             dctx.index -= 2;
             if ((errno = fd_s->file->ops->readdir(fd_s->file, &dctx)) != 1) {
@@ -643,13 +678,11 @@ __DEFINE_LXSYSCALL3(int, read, int, fd, void*, buf, size_t, count)
 
     file->inode->atime = clock_unixtime();
 
-    __SYSCALL_INTERRUPTIBLE({
-        if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) {
-            errno = file->ops->read(file->inode, buf, count, file->f_pos);
-        } else {
-            errno = pcache_read(file->inode, buf, count, file->f_pos);
-        }
-    })
+    if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) {
+        errno = file->ops->read(file->inode, buf, count, file->f_pos);
+    } else {
+        errno = pcache_read(file->inode, buf, count, file->f_pos);
+    }
 
     if (errno > 0) {
         file->f_pos += errno;
@@ -686,13 +719,11 @@ __DEFINE_LXSYSCALL3(int, write, int, fd, void*, buf, size_t, count)
 
     file->inode->mtime = clock_unixtime();
 
-    __SYSCALL_INTERRUPTIBLE({
-        if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) {
-            errno = file->ops->write(file->inode, buf, count, file->f_pos);
-        } else {
-            errno = pcache_write(file->inode, buf, count, file->f_pos);
-        }
-    })
+    if ((file->inode->itype & VFS_IFSEQDEV) || (fd_s->flags & FO_DIRECT)) {
+        errno = file->ops->write(file->inode, buf, count, file->f_pos);
+    } else {
+        errno = pcache_write(file->inode, buf, count, file->f_pos);
+    }
 
     if (errno > 0) {
         file->f_pos += errno;
@@ -752,7 +783,7 @@ done:
 int
 vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
 {
-    if (!dnode || dnode->parent == dnode) {
+    if (!dnode) {
         return 0;
     }
 
@@ -760,13 +791,19 @@ vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
         return ENAMETOOLONG;
     }
 
-    size_t len = vfs_get_path(dnode->parent, buf, size, depth + 1);
+    size_t len = 0;
+
+    if (dnode->parent != dnode) {
+        len = vfs_get_path(dnode->parent, buf, size, depth + 1);
+    }
 
     if (len >= size) {
         return len;
     }
 
-    buf[len++] = VFS_PATH_DELIM;
+    if (!len || buf[len - 1] != VFS_PATH_DELIM) {
+        buf[len++] = VFS_PATH_DELIM;
+    }
 
     size_t cpy_size = MIN(dnode->name.len, size - len);
     strncpy(buf + len, dnode->name.value, cpy_size);
@@ -792,6 +829,19 @@ vfs_readlink(struct v_dnode* dnode, char* buf, size_t size)
     return 0;
 }
 
+int
+vfs_get_dtype(int itype)
+{
+    switch (itype) {
+        case VFS_IFDIR:
+            return DT_DIR;
+        case VFS_IFSYMLINK:
+            return DT_SYMLINK;
+        default:
+            return DT_PIPE;
+    }
+}
+
 __DEFINE_LXSYSCALL3(int, realpathat, int, fd, char*, buf, size_t, size)
 {
     int errno;
@@ -1161,8 +1211,22 @@ done:
     return DO_STATUS(errno);
 }
 
+void
+vfs_ref_dnode(struct v_dnode* dnode)
+{
+    atomic_fetch_add(&dnode->ref_count, 1);
+    mnt_mkbusy(dnode->mnt);
+}
+
+void
+vfs_unref_dnode(struct v_dnode* dnode)
+{
+    atomic_fetch_sub(&dnode->ref_count, 1);
+    mnt_chillax(dnode->mnt);
+}
+
 int
-__vfs_do_chdir(struct v_dnode* dnode)
+vfs_do_chdir(struct proc_info* proc, struct v_dnode* dnode)
 {
     int errno = 0;
 
@@ -1173,14 +1237,12 @@ __vfs_do_chdir(struct v_dnode* dnode)
         goto done;
     }
 
-    if (__current->cwd) {
-        atomic_fetch_sub(&__current->cwd->ref_count, 1);
-        mnt_chillax(__current->cwd->mnt);
+    if (proc->cwd) {
+        vfs_unref_dnode(proc->cwd);
     }
 
-    atomic_fetch_add(&dnode->ref_count, 1);
-    mnt_mkbusy(dnode->mnt);
-    __current->cwd = dnode;
+    vfs_ref_dnode(dnode);
+    proc->cwd = dnode;
 
     unlock_dnode(dnode);
 
@@ -1197,7 +1259,7 @@ __DEFINE_LXSYSCALL1(int, chdir, const char*, path)
         goto done;
     }
 
-    errno = __vfs_do_chdir(dnode);
+    errno = vfs_do_chdir(__current, dnode);
 
 done:
     return DO_STATUS(errno);
@@ -1212,7 +1274,7 @@ __DEFINE_LXSYSCALL1(int, fchdir, int, fd)
         goto done;
     }
 
-    errno = __vfs_do_chdir(fd_s->file->dnode);
+    errno = vfs_do_chdir(__current, fd_s->file->dnode);
 
 done:
     return DO_STATUS(errno);
index 30e06ca731f1d8ee96d2c413c3a8894a852e0303..fe9cf90a7393ff8347d9f516faea1f0e1f500f64 100644 (file)
@@ -3,7 +3,9 @@
 
 #include <lunaix/device.h>
 #include <lunaix/foptions.h>
+#include <lunaix/input.h>
 #include <lunaix/lxconsole.h>
+#include <lunaix/mm/mmio.h>
 #include <lunaix/mm/page.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/vmm.h>
@@ -55,9 +57,6 @@ _kernel_pre_init()
 
     setup_memory((multiboot_memory_map_t*)_k_init_mb_info->mmap_addr, map_size);
 
-    tty_init((void*)VGA_BUFFER_VADDR);
-    tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
-
     __kernel_ptd = cpu_rcr3();
 
     tmp = (struct proc_info){ .page_table = __kernel_ptd };
@@ -72,17 +71,22 @@ _kernel_init()
     cake_init();
     valloc_init();
 
+    tty_init(ioremap(VGA_FRAMEBUFFER, PG_SIZE));
+    tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_BLACK);
+
     vfs_init();
     fsm_init();
+    input_init();
 
-    device_init();
+    vfs_export_attributes();
 
     if ((errno = vfs_mount_root("ramfs", NULL))) {
         panickf("Fail to mount root. (errno=%d)", errno);
     }
 
-    // FIXME replace with more specific fs for device.
-    vfs_mount("/dev", "twifs", NULL, MNT_RO);
+    vfs_mount("/dev", "devfs", NULL, 0);
+    vfs_mount("/sys", "twifs", NULL, MNT_RO);
+    vfs_mount("/task", "taskfs", NULL, MNT_RO);
 
     lxconsole_init();
 
@@ -193,22 +197,7 @@ setup_memory(multiboot_memory_map_t* map, size_t map_size)
 
     // 将内核占据的页,包括前1MB,hhk_init 设为已占用
     size_t pg_count = V2P(&__kernel_end) >> PG_SIZE_BITS;
-    pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, 0);
-
-    size_t vga_buf_pgs = VGA_BUFFER_SIZE >> PG_SIZE_BITS;
-
-    // 首先,标记VGA部分为已占用,并且锁定
-    pmm_mark_chunk_occupied(
-      KERNEL_PID, VGA_BUFFER_PADDR >> PG_SIZE_BITS, vga_buf_pgs, PP_FGLOCKED);
-
-    // 重映射VGA文本缓冲区(以后会变成显存,i.e., framebuffer)
-    for (size_t i = 0; i < vga_buf_pgs; i++) {
-        vmm_set_mapping(PD_REFERENCED,
-                        VGA_BUFFER_VADDR + (i << PG_SIZE_BITS),
-                        VGA_BUFFER_PADDR + (i << PG_SIZE_BITS),
-                        PG_PREM_URW,
-                        VMAP_NULL);
-    }
+    pmm_mark_chunk_occupied(KERNEL_PID, 0, pg_count, PP_FGLOCKED);
 
     for (uintptr_t i = &__usrtext_start; i < &__usrtext_end; i += PG_SIZE) {
         vmm_set_mapping(PD_REFERENCED, i, V2P(i), PG_PREM_UR, VMAP_NULL);
index d18691ac2fd1fa6d9ccd3389dcb7058c5710408d..fd005c09b9295f23b33ea737df3dc4612af118fc 100644 (file)
@@ -22,51 +22,51 @@ __kprintf(const char* component, const char* fmt, va_list args)
 
     switch (log_level) {
         case '0':
-            snprintf(expanded_fmt,
-                     MAX_XFMT_SIZE,
-                     "[%s] (%s) %s",
-                     "INFO",
-                     component,
-                     fmt);
+            ksnprintf(expanded_fmt,
+                      MAX_XFMT_SIZE,
+                      "[%s] (%s) %s",
+                      "INFO",
+                      component,
+                      fmt);
             break;
         case '1':
             // tty_set_theme(VGA_COLOR_BROWN, current_theme >> 12);
-            snprintf(expanded_fmt,
-                     MAX_XFMT_SIZE,
-                     "\033[6;0m[%s] (%s) %s\033[39;49m",
-                     "WARN",
-                     component,
-                     fmt);
+            ksnprintf(expanded_fmt,
+                      MAX_XFMT_SIZE,
+                      "\033[6;0m[%s] (%s) %s\033[39;49m",
+                      "WARN",
+                      component,
+                      fmt);
             break;
         case '2':
             // tty_set_theme(VGA_COLOR_LIGHT_RED, current_theme >> 12);
-            snprintf(expanded_fmt,
-                     MAX_XFMT_SIZE,
-                     "\033[12;0m[%s] (%s) %s\033[39;49m",
-                     "EROR",
-                     component,
-                     fmt);
+            ksnprintf(expanded_fmt,
+                      MAX_XFMT_SIZE,
+                      "\033[12;0m[%s] (%s) %s\033[39;49m",
+                      "EROR",
+                      component,
+                      fmt);
             break;
         case '3':
             // tty_set_theme(VGA_COLOR_LIGHT_BLUE, current_theme >> 12);
-            snprintf(expanded_fmt,
-                     MAX_XFMT_SIZE,
-                     "\033[9;0m[%s] (%s) %s\033[39;49m",
-                     "DEBG",
-                     component,
-                     fmt);
+            ksnprintf(expanded_fmt,
+                      MAX_XFMT_SIZE,
+                      "\033[9;0m[%s] (%s) %s\033[39;49m",
+                      "DEBG",
+                      component,
+                      fmt);
             break;
         default:
-            snprintf(expanded_fmt,
-                     MAX_XFMT_SIZE,
-                     "[%s] (%s) %s",
-                     "LOG",
-                     component,
-                     fmt);
+            ksnprintf(expanded_fmt,
+                      MAX_XFMT_SIZE,
+                      "[%s] (%s) %s",
+                      "LOG",
+                      component,
+                      fmt);
             break;
     }
 
-    __sprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args);
+    __ksprintf_internal(buf, expanded_fmt, MAX_KPRINTF_BUF_SIZE, args);
     console_write_str(buf);
 }
 
@@ -80,7 +80,7 @@ kprint_panic(const char* fmt, ...)
     tty_set_theme(VGA_COLOR_WHITE, VGA_COLOR_RED);
     tty_clear_line(24);
 
-    __sprintf_internal(buf, fmt, MAX_KPRINTF_BUF_SIZE, args);
+    __ksprintf_internal(buf, fmt, MAX_KPRINTF_BUF_SIZE, args);
     tty_put_str_at(buf, 0, 24);
 
     va_end(args);
@@ -98,12 +98,12 @@ kprint_hex(const void* buffer, unsigned int size)
     ch_cache[0] = '|';
     ch_cache[1] = ' ';
     while (size) {
-        snprintf(buf, 64, " %.4p: ", ptr);
+        ksnprintf(buf, 64, " %.4p: ", ptr);
         console_write_str(buf);
         for (i = 0; i < 8 && size; i++, size--, ptr++) {
             unsigned char c = *(data + ptr) & 0xff;
             ch_cache[2 + i] = (32 <= c && c < 127) ? c : '.';
-            snprintf(buf, 64, "%.2x  ", c);
+            ksnprintf(buf, 64, "%.2x  ", c);
             console_write_str(buf);
         }
         ch_cache[2 + i] = '\0';
diff --git a/lunaix-os/kernel/lxconsole.c b/lunaix-os/kernel/lxconsole.c
deleted file mode 100644 (file)
index 785330a..0000000
+++ /dev/null
@@ -1,222 +0,0 @@
-#include <klibc/string.h>
-#include <lunaix/device.h>
-#include <lunaix/keyboard.h>
-#include <lunaix/lxconsole.h>
-#include <lunaix/mm/pmm.h>
-#include <lunaix/mm/valloc.h>
-#include <lunaix/mm/vmm.h>
-#include <lunaix/sched.h>
-#include <lunaix/tty/console.h>
-#include <lunaix/tty/tty.h>
-
-static struct console lx_console;
-
-int
-__tty_write(struct device* dev, void* buf, size_t offset, size_t len);
-
-int
-__tty_read(struct device* dev, void* buf, size_t offset, size_t len);
-
-void
-lxconsole_init()
-{
-    memset(&lx_console, 0, sizeof(lx_console));
-    fifo_init(&lx_console.output, VGA_BUFFER_VADDR + 0x1000, 8192, 0);
-    fifo_init(&lx_console.input, valloc(4096), 4096, 0);
-
-    // FIXME use valloc to allocate console buffer.
-    // In doing this, the console buffer can only be accessed from kernel mode
-    //  any direct write to this buffer from user land should be purged!
-
-    // 分配控制台缓存
-    for (size_t i = 0; i < PG_ALIGN(lx_console.output.size); i += PG_SIZE) {
-        uintptr_t pa = pmm_alloc_page(KERNEL_PID, 0);
-        vmm_set_mapping(PD_REFERENCED,
-                        (uintptr_t)lx_console.output.data + i,
-                        pa,
-                        PG_PREM_URW,
-                        0);
-    }
-
-    lx_console.flush_timer = NULL;
-
-    struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
-    tty_dev->write = __tty_write;
-    tty_dev->read = __tty_read;
-}
-
-int
-__tty_write(struct device* dev, void* buf, size_t offset, size_t len)
-{
-    struct console* console = (struct console*)dev->underlay;
-    console_write(console, buf, len);
-}
-
-int
-__tty_read(struct device* dev, void* buf, size_t offset, size_t len)
-{
-    struct kdb_keyinfo_pkt keyevent;
-    struct console* console = (struct console*)dev->underlay;
-
-    size_t count = fifo_read(&console->input, buf, len);
-    if (count > 0 && ((char*)buf)[count - 1] == '\n') {
-        return count;
-    }
-
-    while (count < len) {
-        // FIXME RACE!
-        //  Consider two process that is polling the input key simultaneously.
-        //  When a key is arrived, one of the processes will win the race and
-        //  swallow it (advancing the key buffer pointer)
-        if (!kbd_recv_key(&keyevent)) {
-            sched_yieldk();
-            continue;
-        }
-        if (!(keyevent.state & KBD_KEY_FPRESSED)) {
-            continue;
-        }
-        if ((keyevent.keycode & 0xff00) > KEYPAD) {
-            continue;
-        }
-
-        char c = (char)(keyevent.keycode & 0x00ff);
-        if (c == 0x08) {
-            if (fifo_backone(&console->input)) {
-                console_write_char(c);
-            }
-            continue;
-        }
-        console_write_char(c);
-        if (!fifo_putone(&console->input, c) || c == '\n') {
-            break;
-        }
-    }
-    return count + fifo_read(&console->input, buf + count, len - count);
-}
-
-void
-console_schedule_flush()
-{
-    // TODO make the flush on-demand rather than periodic
-}
-
-void
-console_view_up()
-{
-    struct fifo_buf* buffer = &lx_console.output;
-    mutex_lock(&buffer->lock);
-    size_t p = lx_console.erd_pos - 2;
-    while (p < lx_console.erd_pos && p != buffer->wr_pos &&
-           ((char*)buffer->data)[p] != '\n') {
-        p--;
-    }
-    p++;
-
-    if (p > lx_console.erd_pos) {
-        p = 0;
-    }
-
-    buffer->flags |= FIFO_DIRTY;
-    lx_console.erd_pos = p;
-    mutex_unlock(&buffer->lock);
-}
-
-size_t
-__find_next_line(size_t start)
-{
-    size_t p = start;
-    while (p != lx_console.output.wr_pos &&
-           ((char*)lx_console.output.data)[p] != '\n') {
-        p = (p + 1) % lx_console.output.size;
-    }
-    return p + 1;
-}
-
-void
-console_view_down()
-{
-    struct fifo_buf* buffer = &lx_console.output;
-    mutex_lock(&buffer->lock);
-
-    lx_console.erd_pos = __find_next_line(lx_console.erd_pos);
-    buffer->flags |= FIFO_DIRTY;
-    mutex_unlock(&buffer->lock);
-}
-
-void
-console_flush()
-{
-    if (mutex_on_hold(&lx_console.output.lock)) {
-        return;
-    }
-    if (!(lx_console.output.flags & FIFO_DIRTY)) {
-        return;
-    }
-
-    tty_flush_buffer(lx_console.output.data,
-                     lx_console.erd_pos,
-                     lx_console.output.wr_pos,
-                     lx_console.output.size);
-    lx_console.output.flags &= ~FIFO_DIRTY;
-}
-
-void
-console_write(struct console* console, uint8_t* data, size_t size)
-{
-    mutex_lock(&console->output.lock);
-    uint8_t* buffer = console->output.data;
-    uintptr_t ptr = console->output.wr_pos;
-    uintptr_t rd_ptr = console->output.rd_pos;
-
-    char c;
-    int lines = 0;
-    int j = 0;
-    for (size_t i = 0; i < size; i++) {
-        c = data[i];
-        if (!c) {
-            continue;
-        }
-        buffer[(ptr + j) % console->output.size] = c;
-        lines += (c == '\n');
-        j++;
-    }
-
-    size = j;
-
-    uintptr_t new_ptr = (ptr + size) % console->output.size;
-    console->output.wr_pos = new_ptr;
-
-    if (console->lines > TTY_HEIGHT && lines > 0) {
-        console->output.rd_pos =
-          __find_next_line((size + rd_ptr) % console->output.size);
-    }
-
-    if (new_ptr < ptr + size && new_ptr > rd_ptr) {
-        console->output.rd_pos = new_ptr;
-    }
-
-    console->lines += lines;
-    console->erd_pos = console->output.rd_pos;
-    console->output.flags |= FIFO_DIRTY;
-    mutex_unlock(&console->output.lock);
-}
-
-void
-console_write_str(char* str)
-{
-    console_write(&lx_console, str, strlen(str));
-}
-
-void
-console_write_char(char str)
-{
-    console_write(&lx_console, &str, 1);
-}
-
-void
-console_start_flushing()
-{
-    struct lx_timer* timer =
-      timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC);
-    lx_console.flush_timer = timer;
-}
\ No newline at end of file
index c3cee83d7153b23a7df3f96ff9ce213ce489f126..5e03d347706c8943b08c9f2792aecb9d7765aad7 100644 (file)
@@ -48,6 +48,7 @@ __new_cake(struct cake_pile* pile)
 
     cake->first_piece = (void*)((uintptr_t)cake + pile->offset);
     cake->next_free = 0;
+    pile->cakes_count++;
 
     piece_index_t* free_list = cake->free_list;
     for (size_t i = 0; i < max_piece - 1; i++) {
@@ -119,6 +120,12 @@ cake_new_pile(char* name,
     return pile;
 }
 
+void
+cake_set_constructor(struct cake_pile* pile, pile_cb ctor)
+{
+    pile->ctor = ctor;
+}
+
 void*
 cake_grab(struct cake_pile* pile)
 {
@@ -146,8 +153,14 @@ cake_grab(struct cake_pile* pile)
         llist_append(&pile->partial, &pos->cakes);
     }
 
-    return (void*)((uintptr_t)pos->first_piece +
-                   found_index * pile->piece_size);
+    void* ptr =
+      (void*)((uintptr_t)pos->first_piece + found_index * pile->piece_size);
+
+    if (pile->ctor) {
+        pile->ctor(pile, ptr);
+    }
+
+    return ptr;
 }
 
 int
@@ -190,18 +203,7 @@ found:
 }
 
 void
-cake_stats()
+cake_ctor_zeroing(struct cake_pile* pile, void* piece)
 {
-    kprintf(KDEBUG "<name> <cake> <pg/c> <p/c> <alloced>\n");
-
-    struct cake_pile *pos, *n;
-    llist_for_each(pos, n, &piles, piles)
-    {
-        kprintf("%s %d %d %d %d\n",
-                pos->pile_name,
-                pos->cakes_count,
-                pos->pg_per_cake,
-                pos->pieces_per_cake,
-                pos->alloced_pieces);
-    }
+    memset(piece, 0, pile->piece_size);
 }
\ No newline at end of file
diff --git a/lunaix-os/kernel/mm/cake_export.c b/lunaix-os/kernel/mm/cake_export.c
new file mode 100644 (file)
index 0000000..276e823
--- /dev/null
@@ -0,0 +1,108 @@
+#include <lunaix/fs/twifs.h>
+#include <lunaix/mm/cake.h>
+
+extern struct llist_header piles;
+
+int
+__cake_stat_gonext(struct twimap* map)
+{
+    struct cake_pile* pile = twimap_index(map, struct cake_pile*);
+    if (pile->piles.next == &piles) {
+        return 0;
+    }
+    map->index = list_entry(pile->piles.next, struct cake_pile, piles);
+    return 1;
+}
+
+void
+__cake_stat_reset(struct twimap* map)
+{
+    map->index = container_of(piles.next, struct cake_pile, piles);
+}
+
+void
+__cake_rd_stat(struct twimap* map)
+{
+    struct cake_pile* pos = twimap_index(map, struct cake_pile*);
+    twimap_printf(map,
+                  "%s %d %d %d %d\n",
+                  pos->pile_name,
+                  pos->cakes_count,
+                  pos->pg_per_cake,
+                  pos->pieces_per_cake,
+                  pos->alloced_pieces);
+}
+
+void
+__cake_rd_psize(struct twimap* map)
+{
+    struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+    twimap_printf(map, "%u", pile->piece_size);
+}
+
+void
+__cake_rd_ccount(struct twimap* map)
+{
+    struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+    twimap_printf(map, "%u", pile->cakes_count);
+}
+
+void
+__cake_rd_alloced(struct twimap* map)
+{
+    struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+    twimap_printf(map, "%u", pile->alloced_pieces);
+}
+
+void
+__cake_rd_ppc(struct twimap* map)
+{
+    struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+    twimap_printf(map, "%u", pile->pieces_per_cake);
+}
+
+void
+__cake_rd_ppg(struct twimap* map)
+{
+    struct cake_pile* pile = twimap_data(map, struct cake_pile*);
+    twimap_printf(map, "%u", pile->pg_per_cake);
+}
+
+void
+cake_export_pile(struct twifs_node* root, struct cake_pile* pile)
+{
+    struct twifs_node* pile_rt = twifs_dir_node(root, pile->pile_name);
+
+    struct twimap* map = twifs_mapping(pile_rt, pile, "piece_size");
+    map->read = __cake_rd_psize;
+
+    map = twifs_mapping(pile_rt, pile, "cake_count");
+    map->read = __cake_rd_ccount;
+
+    map = twifs_mapping(pile_rt, pile, "grabbed");
+    map->read = __cake_rd_alloced;
+
+    map = twifs_mapping(pile_rt, pile, "pieces_per_cake");
+    map->read = __cake_rd_ppc;
+
+    map = twifs_mapping(pile_rt, pile, "page_per_cake");
+    map->read = __cake_rd_ppg;
+}
+
+void
+cake_export()
+{
+    struct twifs_node* cake_root = twifs_dir_node(NULL, "cake");
+
+    struct twimap* map = twifs_mapping(cake_root, NULL, "pinkiepie");
+    map->reset = __cake_stat_reset;
+    map->go_next = __cake_stat_gonext;
+    map->read = __cake_rd_stat;
+    __cake_stat_reset(map);
+
+    struct cake_pile *pos, *n;
+    llist_for_each(pos, n, &piles, piles)
+    {
+        cake_export_pile(cake_root, pos);
+    }
+}
\ No newline at end of file
index 651c6fce6c8852229e256e1dc0300b0a3c841ca2..edc28efadeb77ec6f7c16b2a16a038849f9ef84d 100644 (file)
@@ -50,13 +50,11 @@ dmm_init(heap_context_t* heap)
     heap->brk = heap->start;
     mutex_init(&heap->lock);
 
-    int perm = PG_ALLOW_USER;
-    if (heap->brk >= KHEAP_START) {
-        perm = 0;
-    }
-
-    return vmm_set_mapping(
-             PD_REFERENCED, heap->brk, 0, PG_WRITE | perm, VMAP_NULL) != NULL;
+    return vmm_set_mapping(PD_REFERENCED,
+                           heap->brk,
+                           0,
+                           PG_WRITE | PG_ALLOW_USER,
+                           VMAP_NULL) != NULL;
 }
 
 int
index 6b5b878d12a5b188270af05f0fa096de78a3a79e..aec1001a6cf3bde3e7974aeb109bf4ce4bfaf62e 100644 (file)
@@ -1,3 +1,6 @@
+
+/**** DO NOT USE ****/
+
 /**
  * @file kalloc.c
  * @author Lunaixsky
  * @copyright Copyright (c) 2022
  *
  */
-#include <lunaix/mm/dmm.h>
-#include <lunaix/mm/kalloc.h>
-#include <lunaix/mm/vmm.h>
-
-#include <lunaix/common.h>
-#include <lunaix/spike.h>
-
-#include <klibc/string.h>
+// #include <lunaix/mm/dmm.h>
+// #include <lunaix/mm/kalloc.h>
+// #include <lunaix/mm/vmm.h>
 
-#include <stdint.h>
+// #include <lunaix/common.h>
+// #include <lunaix/spike.h>
 
-extern uint8_t __kernel_heap_start;
+// #include <klibc/string.h>
 
-void*
-lx_malloc_internal(heap_context_t* heap, size_t size);
-
-void
-place_chunk(uint8_t* ptr, size_t size);
+// #include <stdint.h>
 
-void
-lx_free_internal(void* ptr);
+// extern uint8_t __kernel_heap_start;
+
+// void*
+// lx_malloc_internal(heap_context_t* heap, size_t size);
+
+// void
+// place_chunk(uint8_t* ptr, size_t size);
 
-void*
-coalesce(uint8_t* chunk_ptr);
+// void
+// lx_free_internal(void* ptr);
 
-void*
-lx_grow_heap(heap_context_t* heap, size_t sz);
+// void*
+// coalesce(uint8_t* chunk_ptr);
+
+// void*
+// lx_grow_heap(heap_context_t* heap, size_t sz);
 
-/*
-    At the beginning, we allocate an empty page and put our initial marker
+// /*
+//     At the beginning, we allocate an empty page and put our initial marker
 
-    | 4/1 | 0/1 |
-    ^     ^ brk
-    start
+//     | 4/1 | 0/1 |
+//     ^     ^ brk
+//     start
 
-    Then, expand the heap further, with HEAP_INIT_SIZE (evaluated to 4096, i.e.,
-   1 pg size) This will allocate as much pages and override old epilogue marker
-   with a free region hdr and put new epilogue marker. These are handled by
-   lx_grow_heap which is internally used by alloc to expand the heap at many
-   moment when needed.
+//     Then, expand the heap further, with HEAP_INIT_SIZE (evaluated to 4096,
+//     i.e.,
+//    1 pg size) This will allocate as much pages and override old epilogue
+//    marker with a free region hdr and put new epilogue marker. These are
+//    handled by lx_grow_heap which is internally used by alloc to expand the
+//    heap at many moment when needed.
 
-    | 4/1 | 4096/0 |   .......   | 4096/0 | 0/1 |
-    ^     ^ brk_old                       ^
-    start                                 brk
+//     | 4/1 | 4096/0 |   .......   | 4096/0 | 0/1 |
+//     ^     ^ brk_old                       ^
+//     start                                 brk
 
-    Note: the brk always point to the beginning of epilogue.
-*/
+//     Note: the brk always point to the beginning of epilogue.
+// */
 
-static heap_context_t kheap;
+// static heap_context_t kheap;
 
-int
-kalloc_init()
-{
-    kheap.start = KHEAP_START;
-    kheap.brk = NULL;
-    kheap.max_addr =
-      (void*)PROC_START; // 在新的布局中,堆结束的地方即为进程表开始的地方
-
-    for (size_t i = 0; i < KHEAP_SIZE_MB >> 2; i++) {
-        vmm_set_mapping(PD_REFERENCED,
-                        (uintptr_t)kheap.start + (i << 22),
-                        0,
-                        PG_PREM_RW,
-                        VMAP_NOMAP);
-    }
-
-    if (!dmm_init(&kheap)) {
-        return 0;
-    }
-
-    SW(kheap.start, PACK(4, M_ALLOCATED));
-    SW(kheap.start + WSIZE, PACK(0, M_ALLOCATED));
-    kheap.brk += WSIZE;
-
-    return lx_grow_heap(&kheap, HEAP_INIT_SIZE) != NULL;
-}
-
-void*
-lxmalloc(size_t size)
-{
-    mutex_lock(&kheap.lock);
-    void* r = lx_malloc_internal(&kheap, size);
-    mutex_unlock(&kheap.lock);
-
-    return r;
-}
-
-void*
-lxcalloc(size_t n, size_t elem)
-{
-    size_t pd = n * elem;
-
-    // overflow detection
-    if (pd < elem || pd < n) {
-        return NULL;
-    }
-
-    void* ptr = lxmalloc(pd);
-    if (!ptr) {
-        return NULL;
-    }
-
-    return memset(ptr, 0, pd);
-}
-
-void
-lxfree(void* ptr)
-{
-    if (!ptr) {
-        return;
-    }
-    mutex_lock(&kheap.lock);
-
-    uint8_t* chunk_ptr = (uint8_t*)ptr - WSIZE;
-    uint32_t hdr = LW(chunk_ptr);
-    size_t sz = CHUNK_S(hdr);
-    uint8_t* next_hdr = chunk_ptr + sz;
-
-    // make sure the ptr we are 'bout to free makes sense
-    //   the size trick is stolen from glibc's malloc/malloc.c:4437 ;P
-
-    assert_msg(((uintptr_t)ptr < (uintptr_t)(-sz)) && !((uintptr_t)ptr & 0x3),
-               "free(): invalid pointer");
-
-    assert_msg(sz > WSIZE, "free(): invalid size");
-
-    SW(chunk_ptr, hdr & ~M_ALLOCATED);
-    SW(FPTR(chunk_ptr, sz), hdr & ~M_ALLOCATED);
-    SW(next_hdr, LW(next_hdr) | M_PREV_FREE);
-
-    coalesce(chunk_ptr);
-
-    mutex_unlock(&kheap.lock);
-}
-
-void*
-lx_malloc_internal(heap_context_t* heap, size_t size)
-{
-    // Simplest first fit approach.
-
-    if (!size) {
-        return NULL;
-    }
-
-    uint8_t* ptr = heap->start;
-    // round to largest 4B aligned value
-    //  and space for header
-    size = ROUNDUP(size + WSIZE, BOUNDARY);
-    while (ptr < (uint8_t*)heap->brk) {
-        uint32_t header = *((uint32_t*)ptr);
-        size_t chunk_size = CHUNK_S(header);
-        if (!chunk_size && CHUNK_A(header)) {
-            break;
-        }
-        if (chunk_size >= size && !CHUNK_A(header)) {
-            // found!
-            place_chunk(ptr, size);
-            return BPTR(ptr);
-        }
-        ptr += chunk_size;
-    }
-
-    // if heap is full (seems to be!), then allocate more space (if it's
-    // okay...)
-    if ((ptr = lx_grow_heap(heap, size))) {
-        place_chunk(ptr, size);
-        return BPTR(ptr);
-    }
-
-    // Well, we are officially OOM!
-    return NULL;
-}
-
-void
-place_chunk(uint8_t* ptr, size_t size)
-{
-    uint32_t header = *((uint32_t*)ptr);
-    size_t chunk_size = CHUNK_S(header);
-    *((uint32_t*)ptr) = PACK(size, CHUNK_PF(header) | M_ALLOCATED);
-    uint8_t* n_hdrptr = (uint8_t*)(ptr + size);
-    uint32_t diff = chunk_size - size;
-
-    if (!diff) {
-        // if the current free block is fully occupied
-        uint32_t n_hdr = LW(n_hdrptr);
-        // notify the next block about our avaliability
-        SW(n_hdrptr, n_hdr & ~0x2);
-    } else {
-        // if there is remaining free space left
-        uint32_t remainder_hdr = PACK(diff, M_NOT_ALLOCATED | M_PREV_ALLOCATED);
-        SW(n_hdrptr, remainder_hdr);
-        SW(FPTR(n_hdrptr, diff), remainder_hdr);
-
-        /*
-            | xxxx |      |         |
-
-                        |
-                        v
-
-            | xxxx |                |
-        */
-        coalesce(n_hdrptr);
-    }
-}
-
-void*
-coalesce(uint8_t* chunk_ptr)
-{
-    uint32_t hdr = LW(chunk_ptr);
-    uint32_t pf = CHUNK_PF(hdr);
-    uint32_t sz = CHUNK_S(hdr);
-
-    uint32_t n_hdr = LW(chunk_ptr + sz);
-
-    if (CHUNK_A(n_hdr) && pf) {
-        // case 1: prev is free
-        uint32_t prev_ftr = LW(chunk_ptr - WSIZE);
-        size_t prev_chunk_sz = CHUNK_S(prev_ftr);
-        uint32_t new_hdr = PACK(prev_chunk_sz + sz, CHUNK_PF(prev_ftr));
-        SW(chunk_ptr - prev_chunk_sz, new_hdr);
-        SW(FPTR(chunk_ptr, sz), new_hdr);
-        chunk_ptr -= prev_chunk_sz;
-    } else if (!CHUNK_A(n_hdr) && !pf) {
-        // case 2: next is free
-        size_t next_chunk_sz = CHUNK_S(n_hdr);
-        uint32_t new_hdr = PACK(next_chunk_sz + sz, pf);
-        SW(chunk_ptr, new_hdr);
-        SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr);
-    } else if (!CHUNK_A(n_hdr) && pf) {
-        // case 3: both free
-        uint32_t prev_ftr = LW(chunk_ptr - WSIZE);
-        size_t next_chunk_sz = CHUNK_S(n_hdr);
-        size_t prev_chunk_sz = CHUNK_S(prev_ftr);
-        uint32_t new_hdr =
-          PACK(next_chunk_sz + prev_chunk_sz + sz, CHUNK_PF(prev_ftr));
-        SW(chunk_ptr - prev_chunk_sz, new_hdr);
-        SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr);
-        chunk_ptr -= prev_chunk_sz;
-    }
-
-    // (fall through) case 4: prev and next are not free
-    return chunk_ptr;
-}
-
-void*
-lx_grow_heap(heap_context_t* heap, size_t sz)
-{
-    void* start;
-
-    // The "+ WSIZE" capture the overhead for epilogue marker
-    if (!(start = lxsbrk(heap, sz + WSIZE, 0))) {
-        return NULL;
-    }
-    sz = ROUNDUP(sz, BOUNDARY);
-
-    // minus the overhead for epilogue, keep the invariant.
-    heap->brk -= WSIZE;
-
-    uint32_t old_marker = *((uint32_t*)start);
-    uint32_t free_hdr = PACK(sz, CHUNK_PF(old_marker));
-    SW(start, free_hdr);
-    SW(FPTR(start, sz), free_hdr);
-    SW(NEXT_CHK(start), PACK(0, M_ALLOCATED | M_PREV_FREE));
-
-    return coalesce(start);
-}
\ No newline at end of file
+// int
+// kalloc_init()
+// {
+//     kheap.start = KHEAP_START;
+//     kheap.brk = NULL;
+//     kheap.max_addr =
+//       (void*)PROC_START; // 在新的布局中,堆结束的地方即为进程表开始的地方
+
+//     for (size_t i = 0; i < KHEAP_SIZE_MB >> 2; i++) {
+//         vmm_set_mapping(PD_REFERENCED,
+//                         (uintptr_t)kheap.start + (i << 22),
+//                         0,
+//                         PG_PREM_RW,
+//                         VMAP_NOMAP);
+//     }
+
+//     if (!dmm_init(&kheap)) {
+//         return 0;
+//     }
+
+//     SW(kheap.start, PACK(4, M_ALLOCATED));
+//     SW(kheap.start + WSIZE, PACK(0, M_ALLOCATED));
+//     kheap.brk += WSIZE;
+
+//     return lx_grow_heap(&kheap, HEAP_INIT_SIZE) != NULL;
+// }
+
+// void*
+// lxmalloc(size_t size)
+// {
+//     mutex_lock(&kheap.lock);
+//     void* r = lx_malloc_internal(&kheap, size);
+//     mutex_unlock(&kheap.lock);
+
+//     return r;
+// }
+
+// void*
+// lxcalloc(size_t n, size_t elem)
+// {
+//     size_t pd = n * elem;
+
+//     // overflow detection
+//     if (pd < elem || pd < n) {
+//         return NULL;
+//     }
+
+//     void* ptr = lxmalloc(pd);
+//     if (!ptr) {
+//         return NULL;
+//     }
+
+//     return memset(ptr, 0, pd);
+// }
+
+// void
+// lxfree(void* ptr)
+// {
+//     if (!ptr) {
+//         return;
+//     }
+//     mutex_lock(&kheap.lock);
+
+//     uint8_t* chunk_ptr = (uint8_t*)ptr - WSIZE;
+//     uint32_t hdr = LW(chunk_ptr);
+//     size_t sz = CHUNK_S(hdr);
+//     uint8_t* next_hdr = chunk_ptr + sz;
+
+//     // make sure the ptr we are 'bout to free makes sense
+//     //   the size trick is stolen from glibc's malloc/malloc.c:4437 ;P
+
+//     assert_msg(((uintptr_t)ptr < (uintptr_t)(-sz)) && !((uintptr_t)ptr &
+//     0x3),
+//                "free(): invalid pointer");
+
+//     assert_msg(sz > WSIZE, "free(): invalid size");
+
+//     SW(chunk_ptr, hdr & ~M_ALLOCATED);
+//     SW(FPTR(chunk_ptr, sz), hdr & ~M_ALLOCATED);
+//     SW(next_hdr, LW(next_hdr) | M_PREV_FREE);
+
+//     coalesce(chunk_ptr);
+
+//     mutex_unlock(&kheap.lock);
+// }
+
+// void*
+// lx_malloc_internal(heap_context_t* heap, size_t size)
+// {
+//     // Simplest first fit approach.
+
+//     if (!size) {
+//         return NULL;
+//     }
+
+//     uint8_t* ptr = heap->start;
+//     // round to largest 4B aligned value
+//     //  and space for header
+//     size = ROUNDUP(size + WSIZE, BOUNDARY);
+//     while (ptr < (uint8_t*)heap->brk) {
+//         uint32_t header = *((uint32_t*)ptr);
+//         size_t chunk_size = CHUNK_S(header);
+//         if (!chunk_size && CHUNK_A(header)) {
+//             break;
+//         }
+//         if (chunk_size >= size && !CHUNK_A(header)) {
+//             // found!
+//             place_chunk(ptr, size);
+//             return BPTR(ptr);
+//         }
+//         ptr += chunk_size;
+//     }
+
+//     // if heap is full (seems to be!), then allocate more space (if it's
+//     // okay...)
+//     if ((ptr = lx_grow_heap(heap, size))) {
+//         place_chunk(ptr, size);
+//         return BPTR(ptr);
+//     }
+
+//     // Well, we are officially OOM!
+//     return NULL;
+// }
+
+// void
+// place_chunk(uint8_t* ptr, size_t size)
+// {
+//     uint32_t header = *((uint32_t*)ptr);
+//     size_t chunk_size = CHUNK_S(header);
+//     *((uint32_t*)ptr) = PACK(size, CHUNK_PF(header) | M_ALLOCATED);
+//     uint8_t* n_hdrptr = (uint8_t*)(ptr + size);
+//     uint32_t diff = chunk_size - size;
+
+//     if (!diff) {
+//         // if the current free block is fully occupied
+//         uint32_t n_hdr = LW(n_hdrptr);
+//         // notify the next block about our avaliability
+//         SW(n_hdrptr, n_hdr & ~0x2);
+//     } else {
+//         // if there is remaining free space left
+//         uint32_t remainder_hdr = PACK(diff, M_NOT_ALLOCATED |
+//         M_PREV_ALLOCATED); SW(n_hdrptr, remainder_hdr); SW(FPTR(n_hdrptr,
+//         diff), remainder_hdr);
+
+//         /*
+//             | xxxx |      |         |
+
+//                         |
+//                         v
+
+//             | xxxx |                |
+//         */
+//         coalesce(n_hdrptr);
+//     }
+// }
+
+// void*
+// coalesce(uint8_t* chunk_ptr)
+// {
+//     uint32_t hdr = LW(chunk_ptr);
+//     uint32_t pf = CHUNK_PF(hdr);
+//     uint32_t sz = CHUNK_S(hdr);
+
+//     uint32_t n_hdr = LW(chunk_ptr + sz);
+
+//     if (CHUNK_A(n_hdr) && pf) {
+//         // case 1: prev is free
+//         uint32_t prev_ftr = LW(chunk_ptr - WSIZE);
+//         size_t prev_chunk_sz = CHUNK_S(prev_ftr);
+//         uint32_t new_hdr = PACK(prev_chunk_sz + sz, CHUNK_PF(prev_ftr));
+//         SW(chunk_ptr - prev_chunk_sz, new_hdr);
+//         SW(FPTR(chunk_ptr, sz), new_hdr);
+//         chunk_ptr -= prev_chunk_sz;
+//     } else if (!CHUNK_A(n_hdr) && !pf) {
+//         // case 2: next is free
+//         size_t next_chunk_sz = CHUNK_S(n_hdr);
+//         uint32_t new_hdr = PACK(next_chunk_sz + sz, pf);
+//         SW(chunk_ptr, new_hdr);
+//         SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr);
+//     } else if (!CHUNK_A(n_hdr) && pf) {
+//         // case 3: both free
+//         uint32_t prev_ftr = LW(chunk_ptr - WSIZE);
+//         size_t next_chunk_sz = CHUNK_S(n_hdr);
+//         size_t prev_chunk_sz = CHUNK_S(prev_ftr);
+//         uint32_t new_hdr =
+//           PACK(next_chunk_sz + prev_chunk_sz + sz, CHUNK_PF(prev_ftr));
+//         SW(chunk_ptr - prev_chunk_sz, new_hdr);
+//         SW(FPTR(chunk_ptr, sz + next_chunk_sz), new_hdr);
+//         chunk_ptr -= prev_chunk_sz;
+//     }
+
+//     // (fall through) case 4: prev and next are not free
+//     return chunk_ptr;
+// }
+
+// void*
+// lx_grow_heap(heap_context_t* heap, size_t sz)
+// {
+//     void* start;
+
+//     // The "+ WSIZE" capture the overhead for epilogue marker
+//     if (!(start = lxsbrk(heap, sz + WSIZE, 0))) {
+//         return NULL;
+//     }
+//     sz = ROUNDUP(sz, BOUNDARY);
+
+//     // minus the overhead for epilogue, keep the invariant.
+//     heap->brk -= WSIZE;
+
+//     uint32_t old_marker = *((uint32_t*)start);
+//     uint32_t free_hdr = PACK(sz, CHUNK_PF(old_marker));
+//     SW(start, free_hdr);
+//     SW(FPTR(start, sz), free_hdr);
+//     SW(NEXT_CHK(start), PACK(0, M_ALLOCATED | M_PREV_FREE));
+
+//     return coalesce(start);
+// }
\ No newline at end of file
index 5e0d01e28601b321c94d62914e0d26b006715655..a52dc1bf93251138ccde1670aad6058765dd5d54 100644 (file)
@@ -1,11 +1,19 @@
 #include <lunaix/mm/mmio.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/vmm.h>
+#include <lunaix/spike.h>
 
 void*
 ioremap(uintptr_t paddr, uint32_t size)
 {
-    return vmm_vmap(paddr, size, PG_PREM_RW | PG_DISABLE_CACHE);
+    void* ptr = vmm_vmap(paddr, size, PG_PREM_RW | PG_DISABLE_CACHE);
+    if (ptr) {
+        pmm_mark_chunk_occupied(KERNEL_PID,
+                                paddr >> PG_SIZE_BITS,
+                                CEIL(size, PG_SIZE_BITS),
+                                PP_FGLOCKED);
+    }
+    return ptr;
 }
 
 void*
index 920c35bbb86a3ea26cf04c247bce0b317128c5e1..bd3b26ec0d5fc1009b0e9cf424869934816d2c03 100644 (file)
@@ -21,7 +21,7 @@ region_release_all(struct mm_region* regions)
 
     llist_for_each(pos, n, &regions->head, head)
     {
-        lxfree(pos);
+        vfree(pos);
     }
 }
 
index 2fc129841513dfcf3dbe0431e4068bc3c27bdfbc..7507b1a86113a5364d6e6020d6e5a4724ca239a7 100644 (file)
@@ -26,18 +26,18 @@ vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr)
             current_addr = (current_addr & 0xffc00000) + MEM_4MB;
         } else {
             x86_page_table* ptd = (x86_page_table*)(L2_VADDR(l1inx));
-            size_t i = L2_INDEX(current_addr);
-            for (; i < PG_MAX_ENTRIES && examed_size < size; i++) {
+            size_t i = L2_INDEX(current_addr), j = 0;
+            for (; i < PG_MAX_ENTRIES && examed_size < size; i++, j++) {
                 if (!ptd->entry[i]) {
                     examed_size += PG_SIZE;
                 } else if (examed_size) {
                     // found a discontinuity, start from beginning
                     examed_size = 0;
-                    i++;
+                    j++;
                     break;
                 }
             }
-            current_addr += i << 12;
+            current_addr += j << 12;
         }
 
         if (examed_size >= size) {
@@ -46,6 +46,7 @@ vmm_vmap(uintptr_t paddr, size_t size, pt_attr attr)
 
         if (current_addr >= VMAP_END) {
             wrapped = 1;
+            examed_size = 0;
             current_addr = VMAP_START;
         }
     }
index 6905b1eb059fc8995aeaf3c2cbb5c13a007967b8..6f17176c422a0f27c4b92b81b15f64997bd15f02 100644 (file)
@@ -2,6 +2,7 @@
 #include <hal/ioapic.h>
 #include <lunaix/clock.h>
 #include <lunaix/common.h>
+#include <lunaix/input.h>
 #include <lunaix/peripheral/ps2kbd.h>
 #include <lunaix/syslog.h>
 #include <lunaix/timer.h>
@@ -17,7 +18,6 @@
 LOG_MODULE("PS2KBD");
 
 static struct ps2_cmd_queue cmd_q;
-static struct ps2_key_buffer key_buf;
 static struct ps2_kbd_state kbd_state;
 
 #define KEY_NUM(x) (x + 0x30)
@@ -69,18 +69,21 @@ static kbd_keycode_t scancode_set2_shift[] = {
 
 // clang-format on
 
+static struct input_device* kbd_idev;
+
 #define KBD_STATE_KWAIT 0x00
 #define KBD_STATE_KSPECIAL 0x01
 #define KBD_STATE_KRELEASED 0x02
+#define KBD_STATE_E012 0x03
+#define KBD_STATE_KRELEASED_E0 0x04
 #define KBD_STATE_CMDPROCS 0x40
 
-#define KBD_ENABLE_SPIRQ_FIX
+// #define KBD_ENABLE_SPIRQ_FIX
+#define KBD_ENABLE_SPIRQ_FIX2
 // #define KBD_DBGLOG
 
 void
 intr_ps2_kbd_handler(const isr_param* param);
-static struct kdb_keyinfo_pkt*
-ps2_keybuffer_next_write();
 
 void
 ps2_device_post_cmd(char cmd, char arg)
@@ -107,15 +110,15 @@ ps2_kbd_init()
 {
 
     memset(&cmd_q, 0, sizeof(cmd_q));
-    memset(&key_buf, 0, sizeof(key_buf));
     memset(&kbd_state, 0, sizeof(kbd_state));
 
     mutex_init(&cmd_q.mutex);
-    mutex_init(&key_buf.mutex);
 
     kbd_state.translation_table = scancode_set2;
     kbd_state.state = KBD_STATE_KWAIT;
 
+    kbd_idev = input_add_device("i8042-kbd");
+
     acpi_context* acpi_ctx = acpi_get_context();
     if (acpi_ctx->fadt.header.rev > 1) {
         /*
@@ -132,13 +135,13 @@ ps2_kbd_init()
          *      https://bochs.sourceforge.io/cgi-bin/lxr/source/bios/rombios32.c#L1314
          */
         if (!(acpi_ctx->fadt.boot_arch & IAPC_ARCH_8042)) {
-            kprintf(KERROR "No PS/2 controller detected.\n");
+            kprintf(KERROR "i8042: not found\n");
             // FUTURE: Some alternative fallback on this? Check PCI bus for USB
             // controller instead?
             return;
         }
     } else {
-        kprintf(KWARN "Outdated FADT used, assuming 8042 always exist.\n");
+        kprintf(KWARN "i8042: outdated FADT used, assuming exists.\n");
     }
 
     char result;
@@ -271,14 +274,13 @@ kbd_buffer_key_event(kbd_keycode_t key, uint8_t scancode, kbd_kstate_t state)
         key = key & (0xffdf |
                      -('a' > key || key > 'z' || !(state & KBD_KEY_FCAPSLKED)));
 
-        if (!mutex_on_hold(&key_buf.mutex)) {
-            struct kdb_keyinfo_pkt* keyevent_pkt = ps2_keybuffer_next_write();
-            *keyevent_pkt =
-              (struct kdb_keyinfo_pkt){ .keycode = key,
-                                        .scancode = scancode,
-                                        .state = state,
-                                        .timestamp = clock_systime() };
-        }
+        struct input_evt_pkt ipkt = { .pkt_type = (state & KBD_KEY_FPRESSED)
+                                                    ? PKT_PRESS
+                                                    : PKT_RELEASE,
+                                      .scan_code = scancode,
+                                      .sys_code = (state << 16) | key };
+
+        input_fire_event(kbd_idev, &ipkt);
 
         return;
     }
@@ -337,6 +339,12 @@ intr_ps2_kbd_handler(const isr_param* param)
     }
 #endif
 
+#ifdef KBD_ENABLE_SPIRQ_FIX2
+    if (scancode == PS2_RESULT_ACK || scancode == PS2_RESULT_NAK) {
+        return;
+    }
+#endif
+
 #ifdef KBD_DBGLOG
     kprintf(KDEBUG "%x\n", scancode & 0xff);
 #endif
@@ -354,8 +362,10 @@ intr_ps2_kbd_handler(const isr_param* param)
             }
             break;
         case KBD_STATE_KSPECIAL:
-            if (scancode == 0xf0) { // release code
-                kbd_state.state = KBD_STATE_KRELEASED;
+            if (scancode == 0x12) {
+                kbd_state.state = KBD_STATE_E012;
+            } else if (scancode == 0xf0) { // release code
+                kbd_state.state = KBD_STATE_KRELEASED_E0;
             } else {
                 key = kbd_state.translation_table[scancode];
                 kbd_buffer_key_event(key, scancode, KBD_KEY_FPRESSED);
@@ -364,10 +374,23 @@ intr_ps2_kbd_handler(const isr_param* param)
                 kbd_state.translation_table = scancode_set2;
             }
             break;
+        // handle the '0xE0, 0x12, 0xE0, xx' sequence
+        case KBD_STATE_E012:
+            if (scancode == 0xe0) {
+                kbd_state.state = KBD_STATE_KSPECIAL;
+                kbd_state.translation_table = scancode_set2_ex;
+            }
+            break;
+        case KBD_STATE_KRELEASED_E0:
+            if (scancode == 0x12) {
+                goto escape_release;
+            }
+            // fall through
         case KBD_STATE_KRELEASED:
             key = kbd_state.translation_table[scancode];
             kbd_buffer_key_event(key, scancode, KBD_KEY_FRELEASED);
 
+        escape_release:
             // reset the translation table to scancode_set2
             kbd_state.state = KBD_STATE_KWAIT;
             kbd_state.translation_table = scancode_set2;
@@ -419,37 +442,4 @@ ps2_issue_dev_cmd(char cmd, uint16_t arg)
         ;
 
     return io_inb(PS2_PORT_ENC_CMDREG);
-}
-
-int
-kbd_recv_key(struct kdb_keyinfo_pkt* key_event)
-{
-    if (!key_buf.buffered_len) {
-        return 0;
-    }
-
-    mutex_lock(&key_buf.mutex);
-    *key_event = key_buf.buffer[key_buf.read_ptr];
-    key_buf.buffered_len--;
-    key_buf.read_ptr = (key_buf.read_ptr + 1) % PS2_KBD_RECV_BUFFER_SIZE;
-
-    mutex_unlock(&key_buf.mutex);
-    return 1;
-}
-
-static struct kdb_keyinfo_pkt*
-ps2_keybuffer_next_write()
-{
-    int index =
-      (key_buf.read_ptr + key_buf.buffered_len) % PS2_KBD_RECV_BUFFER_SIZE;
-    if (index == key_buf.read_ptr && key_buf.buffered_len) {
-        // the reader is lagged so much such that the buffer is full.
-        // It is suggested to read from beginning for nearly up-to-date
-        // readings.
-        key_buf.read_ptr = 0;
-        key_buf.buffered_len = index;
-    } else {
-        key_buf.buffered_len++;
-    }
-    return &key_buf.buffer[index];
 }
\ No newline at end of file
index e137b8e28009dd89d477242a3fd99871c7fa5492..e242196f0b969255bbf848b3b723baf2d3ceb599 100644 (file)
@@ -27,6 +27,8 @@
 
 #include <klibc/string.h>
 
+#include <ulibc/stdio.h>
+
 LOG_MODULE("PROC0")
 
 extern void
@@ -46,8 +48,10 @@ __do_reserved_memory(int unlock);
 
 #define USE_DEMO
 // #define DEMO_SIGNAL
-#define DEMO_READDIR
-//#define DEMO_IOTEST
+// #define DEMO_READDIR
+// #define DEMO_IOTEST
+// #define DEMO_INPUT_TEST
+#define DEMO_SIMPLE_SH
 
 extern void
 _pconsole_main();
@@ -64,19 +68,25 @@ _readdir_main();
 extern void
 _iotest_main();
 
+extern void
+input_test();
+
+extern void
+sh_main();
+
 void __USER__
 __proc0_usr()
 {
     // 打开tty设备(控制台),作为标准输入输出。
     //  tty设备属于序列设备(Sequential Device),该类型设备的上层读写
     //  无须经过Lunaix的缓存层,而是直接下发到底层驱动。(不受FO_DIRECT的影响)
-    int stdout = open("/dev/tty", 0);
-    int stdin = dup2(stdout, 1);
+    int fdstdout = open("/dev/tty", 0);
+    int fdstdin = dup2(stdout, 1);
 
     pid_t p;
-    if (!fork()) {
-        _pconsole_main();
-    }
+    // if (!fork()) {
+    //     _pconsole_main();
+    // }
 
     if (!(p = fork())) {
 #ifndef USE_DEMO
@@ -87,9 +97,15 @@ __proc0_usr()
         _readdir_main();
 #elif defined DEMO_IOTEST
         _iotest_main();
+#elif defined DEMO_INPUT_TEST
+        input_test();
+#elif defined DEMO_SIMPLE_SH
+        sh_main();
 #else
         _lxinit_main();
 #endif
+        printf("==== test end ====\n");
+        _exit(0);
     }
 
     waitpid(p, 0, 0);
@@ -141,9 +157,6 @@ init_platform()
     // 锁定所有系统预留页(内存映射IO,ACPI之类的),并且进行1:1映射
     lock_reserved_memory();
 
-    // we are using no kalloc!
-    // assert_msg(kalloc_init(), "Fail to initialize heap");
-
     rtc_init();
     acpi_init(_k_init_mb_info);
     apic_init();
@@ -154,20 +167,23 @@ init_platform()
     pci_init();
     block_init();
     ahci_init();
-    // ahci_list_device();
-    // cake_stats();
 
     syscall_install();
 
     console_start_flushing();
     console_flush();
 
+    cake_export();
     unlock_reserved_memory();
 
     for (size_t i = 0; i < (uintptr_t)(&__init_hhk_end); i += PG_SIZE) {
         vmm_del_mapping(PD_REFERENCED, (void*)i);
         pmm_free_page(KERNEL_PID, (void*)i);
     }
+
+    for (size_t i = L1_INDEX(KERNEL_MM_BASE); i < 1023; i++) {
+        vmm_set_mapping(PD_REFERENCED, i << 22, 0, 0, VMAP_NOMAP);
+    }
 }
 
 void
similarity index 97%
rename from lunaix-os/kernel/process.c
rename to lunaix-os/kernel/process/process.c
index 086a5e3105a184ca3ccf784f3f8fb7cba46445f9..82f1ffa7dcec24bd10e15f09bae93f3e66b0d899 100644 (file)
@@ -123,7 +123,7 @@ __DEFINE_LXSYSCALL2(int, setpgid, pid_t, pid, pid_t, pgid)
 
     struct proc_info* gruppenfuhrer = get_process(pgid);
 
-    if (!gruppenfuhrer || proc->pgid == proc->pid) {
+    if (!gruppenfuhrer || proc->pgid == gruppenfuhrer->pid) {
         __current->k_status = EINVAL;
         return -1;
     }
@@ -151,7 +151,7 @@ init_proc_user_space(struct proc_info* pcb)
         vmm_set_mapping(PD_MOUNT_1, i, 0, PG_ALLOW_USER | PG_WRITE, VMAP_NULL);
     }
 
-    // todo: other uspace initialization stuff
+    // TODO other uspace initialization stuff
 
     vmm_unmount_pd(PD_MOUNT_1);
 }
@@ -196,6 +196,11 @@ dup_proc()
     pcb->intr_ctx = __current->intr_ctx;
     pcb->parent = __current;
 
+    if (__current->cwd) {
+        pcb->cwd = __current->cwd;
+        vfs_ref_dnode(pcb->cwd);
+    }
+
     __copy_fdtable(pcb);
     region_copy(&__current->mm.regions, &pcb->mm.regions);
 
similarity index 79%
rename from lunaix-os/kernel/sched.c
rename to lunaix-os/kernel/process/sched.c
index f8f00d40a094d62c31976cd4d54ef577673ba6de..3ee0e7666c32eafe97c3436ac1c2a9ccc103f64b 100644 (file)
@@ -4,6 +4,8 @@
 #include <hal/apic.h>
 #include <hal/cpu.h>
 
+#include <lunaix/fs/taskfs.h>
+#include <lunaix/mm/cake.h>
 #include <lunaix/mm/kalloc.h>
 #include <lunaix/mm/pmm.h>
 #include <lunaix/mm/valloc.h>
 #include <lunaix/syscall.h>
 #include <lunaix/syslog.h>
 
-#define MAX_PROCESS 512
-
 volatile struct proc_info* __current;
 
 struct proc_info dummy;
 
 struct scheduler sched_ctx;
 
+struct cake_pile* proc_pile;
+
 LOG_MODULE("SCHED")
 
 void
 sched_init()
 {
-    size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000);
+    // size_t pg_size = ROUNDUP(sizeof(struct proc_info) * MAX_PROCESS, 0x1000);
 
-    for (size_t i = 0; i <= pg_size; i += 4096) {
-        uintptr_t pa = pmm_alloc_page(KERNEL_PID, PP_FGPERSIST);
-        vmm_set_mapping(
-          PD_REFERENCED, PROC_START + i, pa, PG_PREM_RW, VMAP_NULL);
-    }
+    // for (size_t i = 0; i <= pg_size; i += 4096) {
+    //     uintptr_t pa = pmm_alloc_page(KERNEL_PID, PP_FGPERSIST);
+    //     vmm_set_mapping(
+    //       PD_REFERENCED, PROC_START + i, pa, PG_PREM_RW, VMAP_NULL);
+    // }
 
-    sched_ctx = (struct scheduler){ ._procs = (struct proc_info*)PROC_START,
+    proc_pile = cake_new_pile("proc", sizeof(struct proc_info), 1, 0);
+    cake_set_constructor(proc_pile, cake_ctor_zeroing);
+
+    sched_ctx = (struct scheduler){ ._procs = vzalloc(PROC_TABLE_SIZE),
                                     .ptable_len = 0,
                                     .procs_index = 0 };
 }
@@ -80,7 +85,7 @@ can_schedule(struct proc_info* proc)
 void
 check_sleepers()
 {
-    struct proc_info* leader = &sched_ctx._procs[0];
+    struct proc_info* leader = sched_ctx._procs[0];
     struct proc_info *pos, *n;
     time_t now = clock_systime();
     llist_for_each(pos, n, &leader->sleep.sleepers, sleep.sleepers)
@@ -94,7 +99,7 @@ check_sleepers()
 
         if (wtime && now >= wtime) {
             pos->sleep.wakeup_time = 0;
-            pos->state = PS_STOPPED;
+            pos->state = PS_READY;
         }
 
         if (atime && now >= atime) {
@@ -123,7 +128,7 @@ schedule()
     int ptr = prev_ptr;
 
     if (!(__current->state & ~PS_RUNNING)) {
-        __current->state = PS_STOPPED;
+        __current->state = PS_READY;
     }
 
     check_sleepers();
@@ -132,8 +137,8 @@ schedule()
 redo:
     do {
         ptr = (ptr + 1) % sched_ctx.ptable_len;
-        next = &sched_ctx._procs[ptr];
-    } while (next->state != PS_STOPPED && ptr != prev_ptr);
+        next = sched_ctx._procs[ptr];
+    } while (!next || (next->state != PS_READY && ptr != prev_ptr));
 
     sched_ctx.procs_index = ptr;
 
@@ -148,6 +153,7 @@ redo:
 void
 sched_yieldk()
 {
+    cpu_enable_interrupt();
     cpu_int(LUNAIX_SCHED);
 }
 
@@ -161,9 +167,9 @@ __DEFINE_LXSYSCALL1(unsigned int, sleep, unsigned int, seconds)
         return (__current->sleep.wakeup_time - clock_systime()) / 1000U;
     }
 
+    struct proc_info* root_proc = sched_ctx._procs[0];
     __current->sleep.wakeup_time = clock_systime() + seconds * 1000;
-    llist_append(&sched_ctx._procs[0].sleep.sleepers,
-                 &__current->sleep.sleepers);
+    llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers);
 
     __current->intr_ctx.registers.eax = seconds;
     __current->state = PS_BLOCKED;
@@ -177,9 +183,9 @@ __DEFINE_LXSYSCALL1(unsigned int, alarm, unsigned int, seconds)
 
     __current->sleep.alarm_time = seconds ? now + seconds * 1000 : 0;
 
+    struct proc_info* root_proc = sched_ctx._procs[0];
     if (llist_empty(&__current->sleep.sleepers)) {
-        llist_append(&sched_ctx._procs[0].sleep.sleepers,
-                     &__current->sleep.sleepers);
+        llist_append(&root_proc->sleep.sleepers, &__current->sleep.sleepers);
     }
 
     return prev_ddl ? (prev_ddl - now) / 1000 : 0;
@@ -233,7 +239,7 @@ repeat:
                 status_flags |= PEXITTERM;
                 goto done;
             }
-            if (proc->state == PS_STOPPED && (options & WUNTRACED)) {
+            if (proc->state == PS_READY && (options & WUNTRACED)) {
                 status_flags |= PEXITSTOP;
                 goto done;
             }
@@ -258,8 +264,7 @@ struct proc_info*
 alloc_process()
 {
     pid_t i = 0;
-    for (; i < sched_ctx.ptable_len && sched_ctx._procs[i].state != PS_DESTROY;
-         i++)
+    for (; i < sched_ctx.ptable_len && sched_ctx._procs[i]; i++)
         ;
 
     if (i == MAX_PROCESS) {
@@ -270,8 +275,7 @@ alloc_process()
         sched_ctx.ptable_len++;
     }
 
-    struct proc_info* proc = &sched_ctx._procs[i];
-    memset(proc, 0, sizeof(*proc));
+    struct proc_info* proc = cake_grab(proc_pile);
 
     proc->state = PS_CREATED;
     proc->pid = i;
@@ -280,9 +284,13 @@ alloc_process()
     proc->fdtable = vzalloc(sizeof(struct v_fdtable));
 
     llist_init_head(&proc->mm.regions.head);
+    llist_init_head(&proc->tasks);
     llist_init_head(&proc->children);
     llist_init_head(&proc->grp_member);
     llist_init_head(&proc->sleep.sleepers);
+    waitq_init(&proc->waitqueue);
+
+    sched_ctx._procs[i] = proc;
 
     return proc;
 }
@@ -290,7 +298,7 @@ alloc_process()
 void
 commit_process(struct proc_info* process)
 {
-    assert(process == &sched_ctx._procs[process->pid]);
+    assert(process == sched_ctx._procs[process->pid]);
 
     if (process->state != PS_CREATED) {
         __current->k_status = EINVAL;
@@ -299,12 +307,13 @@ commit_process(struct proc_info* process)
 
     // every process is the child of first process (pid=1)
     if (!process->parent) {
-        process->parent = &sched_ctx._procs[1];
+        process->parent = sched_ctx._procs[1];
     }
 
     llist_append(&process->parent->children, &process->siblings);
+    llist_append(&sched_ctx._procs[0]->tasks, &process->tasks);
 
-    process->state = PS_STOPPED;
+    process->state = PS_READY;
 }
 
 // from <kernel/process.c>
@@ -319,14 +328,24 @@ destroy_process(pid_t pid)
         __current->k_status = EINVAL;
         return;
     }
-    struct proc_info* proc = &sched_ctx._procs[index];
-    proc->state = PS_DESTROY;
+    struct proc_info* proc = sched_ctx._procs[index];
+    sched_ctx._procs[index] = 0;
+
     llist_delete(&proc->siblings);
+    llist_delete(&proc->grp_member);
+    llist_delete(&proc->tasks);
+    llist_delete(&proc->sleep.sleepers);
+
+    taskfs_invalidate(pid);
+
+    if (proc->cwd) {
+        vfs_unref_dnode(proc->cwd);
+    }
 
     for (size_t i = 0; i < VFS_MAX_FD; i++) {
         struct v_fd* fd = proc->fdtable->fds[i];
         if (fd)
-            vfs_close(fd->file);
+            vfs_pclose(fd->file, pid);
     }
 
     vfree(proc->fdtable);
@@ -343,6 +362,8 @@ destroy_process(pid_t pid)
 
     vmm_unmount_pd(PD_MOUNT_1);
 
+    cake_release(proc_pile, proc);
+
     return pid;
 }
 
@@ -362,7 +383,7 @@ get_process(pid_t pid)
     if (index < 0 || index > sched_ctx.ptable_len) {
         return NULL;
     }
-    return &sched_ctx._procs[index];
+    return sched_ctx._procs[index];
 }
 
 int
@@ -372,7 +393,7 @@ orphaned_proc(pid_t pid)
         return 0;
     if (pid >= sched_ctx.ptable_len)
         return 0;
-    struct proc_info* proc = &sched_ctx._procs[pid];
+    struct proc_info* proc = sched_ctx._procs[pid];
     struct proc_info* parent = proc->parent;
 
     // 如果其父进程的状态是terminated 或 destroy中的一种
similarity index 99%
rename from lunaix-os/kernel/signal.c
rename to lunaix-os/kernel/process/signal.c
index 5f0c868789d9af36d6286dfae989b9a385e28546..5d09d9b6efa59bb02df9faabb3d0c7111d5ce9d2 100644 (file)
@@ -126,7 +126,6 @@ send_grp:
     {
         __SIGSET(pos->sig_pending, signum);
     }
-    return 0;
 
 send_single:
     if (PROC_TERMINATED(proc->state)) {
diff --git a/lunaix-os/kernel/process/task_attr.c b/lunaix-os/kernel/process/task_attr.c
new file mode 100644 (file)
index 0000000..4610acf
--- /dev/null
@@ -0,0 +1,103 @@
+#include <lunaix/fs/taskfs.h>
+
+void
+__read_pending_sig(struct twimap* map)
+{
+    struct proc_info* proc = twimap_data(map, struct proc_info*);
+    twimap_printf(map, "%bb", proc->sig_pending);
+}
+
+void
+__read_masked_sig(struct twimap* map)
+{
+    struct proc_info* proc = twimap_data(map, struct proc_info*);
+    twimap_printf(map, "%bb", proc->sig_mask);
+}
+
+void
+__read_parent(struct twimap* map)
+{
+    struct proc_info* proc = twimap_data(map, struct proc_info*);
+    twimap_printf(map, "%d", proc->parent->pid);
+}
+
+void
+__read_ctimestamp(struct twimap* map)
+{
+    struct proc_info* proc = twimap_data(map, struct proc_info*);
+    twimap_printf(map, "%d", proc->created);
+}
+
+void
+__read_pgid(struct twimap* map)
+{
+    struct proc_info* proc = twimap_data(map, struct proc_info*);
+    twimap_printf(map, "%d", proc->pgid);
+}
+
+void
+__read_children(struct twimap* map)
+{
+    struct llist_header* proc_list = twimap_index(map, struct llist_header*);
+    struct proc_info* proc =
+      container_of(proc_list, struct proc_info, siblings);
+    if (!proc)
+        return;
+    twimap_printf(map, "%d ", proc->pid);
+}
+
+int
+__next_children(struct twimap* map)
+{
+    struct llist_header* proc = twimap_index(map, struct llist_header*);
+    struct proc_info* current = twimap_data(map, struct proc_info*);
+    if (!proc)
+        return 0;
+    map->index = proc->next;
+    if (map->index == &current->children) {
+        return 0;
+    }
+    return 1;
+}
+
+void
+__reset_children(struct twimap* map)
+{
+    struct proc_info* proc = twimap_data(map, struct proc_info*);
+    if (llist_empty(&proc->children)) {
+        map->index = 0;
+        return;
+    }
+    map->index = proc->children.next;
+}
+
+void
+export_task_attr()
+{
+    struct twimap* map;
+    map = twimap_create(NULL);
+    map->read = __read_pending_sig;
+    taskfs_export_attr("sig_pending", map);
+
+    map = twimap_create(NULL);
+    map->read = __read_masked_sig;
+    taskfs_export_attr("sig_masked", map);
+
+    map = twimap_create(NULL);
+    map->read = __read_parent;
+    taskfs_export_attr("parent", map);
+
+    map = twimap_create(NULL);
+    map->read = __read_ctimestamp;
+    taskfs_export_attr("created", map);
+
+    map = twimap_create(NULL);
+    map->read = __read_pgid;
+    taskfs_export_attr("pgid", map);
+
+    map = twimap_create(NULL);
+    map->read = __read_children;
+    map->go_next = __next_children;
+    map->reset = __reset_children;
+    taskfs_export_attr("children", map);
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/process/taskfs.c b/lunaix-os/kernel/process/taskfs.c
new file mode 100644 (file)
index 0000000..28c3713
--- /dev/null
@@ -0,0 +1,226 @@
+#include <lunaix/dirent.h>
+#include <lunaix/fs/taskfs.h>
+#include <lunaix/fs/twimap.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/process.h>
+#include <lunaix/sched.h>
+
+#include <klibc/stdio.h>
+#include <klibc/string.h>
+
+#define COUNTER_MASK ((1 << 16) - 1)
+
+static struct hbucket* attr_export_table;
+static DEFINE_LLIST(attributes);
+static volatile int ino_cnt = 1;
+
+int
+taskfs_next_counter()
+{
+    return (ino_cnt = ((ino_cnt + 1) & COUNTER_MASK) + 1);
+}
+
+inode_t
+taskfs_inode_id(pid_t pid, int sub_counter)
+{
+    return ((pid & (MAX_PROCESS - 1)) << 16) | (sub_counter & COUNTER_MASK);
+}
+
+int
+taskfs_mknod(struct v_dnode* dnode, pid_t pid, int sub_counter, int itype)
+{
+    inode_t ino = taskfs_inode_id(pid, sub_counter);
+
+    struct v_superblock* vsb = dnode->super_block;
+    struct v_inode* inode = vfs_i_find(vsb, ino);
+    if (!inode) {
+        if (!(inode = vfs_i_alloc(vsb))) {
+            return ENOMEM;
+        }
+        inode->id = ino;
+        inode->itype = itype;
+        vfs_i_addhash(inode);
+    }
+
+    vfs_assign_inode(dnode, inode);
+    return 0;
+}
+
+int
+taskfs_readdir(struct v_file* file, struct dir_context* dctx)
+{
+    struct v_inode* inode = file->inode;
+    pid_t pid = inode->id >> 16;
+    int counter = 0;
+
+    if ((inode->id & COUNTER_MASK)) {
+        return ENOTDIR;
+    }
+
+    if (pid) {
+        struct task_attribute *pos, *n;
+        llist_for_each(pos, n, &attributes, siblings)
+        {
+            if (counter == dctx->index) {
+                dctx->read_complete_callback(
+                  dctx, pos->key_val, VFS_NAME_MAXLEN, DT_FILE);
+                return 1;
+            }
+            counter++;
+        }
+        return 0;
+    }
+
+    char name[VFS_NAME_MAXLEN];
+    struct proc_info *root = get_process(pid), *pos, *n;
+    llist_for_each(pos, n, &root->tasks, tasks)
+    {
+        if (counter == dctx->index) {
+            ksnprintf(name, VFS_NAME_MAXLEN, "%d", pos->pid);
+            dctx->read_complete_callback(dctx, name, VFS_NAME_MAXLEN, DT_DIR);
+            return 1;
+        }
+        counter++;
+    }
+    return 0;
+}
+
+// ascii to pid
+pid_t
+taskfs_atop(const char* str)
+{
+    pid_t t = 0;
+    int i = 0;
+    char c;
+    while ((c = str[i++])) {
+        if ('0' > c || c > '9') {
+            return -1;
+        }
+        t = t * 10 + (c - '0');
+    }
+    return t;
+}
+
+int
+taskfs_dirlookup(struct v_inode* this, struct v_dnode* dnode)
+{
+    pid_t pid = this->id >> 16;
+    struct proc_info* proc;
+
+    if (pid) {
+        struct task_attribute* tattr = taskfs_get_attr(&dnode->name);
+        if (!tattr || !(proc = get_process(pid)))
+            return ENOENT;
+
+        int errno =
+          taskfs_mknod(dnode, pid, taskfs_next_counter(), VFS_IFSEQDEV);
+        if (!errno) {
+            tattr->map_file->data = proc;
+            dnode->inode->data = tattr->map_file;
+            dnode->inode->default_fops = &twimap_file_ops;
+        }
+        return errno;
+    }
+
+    pid = taskfs_atop(dnode->name.value);
+
+    if (pid <= 0 || !(proc = get_process(pid))) {
+        return ENOENT;
+    }
+
+    return taskfs_mknod(dnode, pid, 0, VFS_IFDIR);
+}
+
+static struct v_file_ops taskfs_file_ops = { .close = default_file_close,
+                                             .read = default_file_read,
+                                             .write = default_file_write,
+                                             .readdir = taskfs_readdir,
+                                             .seek = default_file_seek };
+static struct v_inode_ops taskfs_inode_ops = { .dir_lookup = taskfs_dirlookup,
+                                               .open = default_inode_open,
+                                               .mkdir = default_inode_mkdir,
+                                               .rmdir = default_inode_rmdir,
+                                               .rename = default_inode_rename };
+
+void
+taskfs_init_inode(struct v_superblock* vsb, struct v_inode* inode)
+{
+    inode->default_fops = &taskfs_file_ops;
+    inode->ops = &taskfs_inode_ops;
+}
+
+static volatile struct v_superblock* taskfs_sb;
+
+int
+taskfs_mount(struct v_superblock* vsb, struct v_dnode* mount_point)
+{
+    taskfs_sb = vsb;
+    vsb->ops.init_inode = taskfs_init_inode;
+
+    return taskfs_mknod(mount_point, 0, 0, VFS_IFDIR);
+}
+
+void
+taskfs_invalidate(pid_t pid)
+{
+    struct v_dnode *pos, *n;
+    struct v_inode* inode = vfs_i_find(taskfs_sb, taskfs_inode_id(pid, 0));
+
+    if (!inode)
+        return;
+
+    llist_for_each(pos, n, &inode->aka_dnodes, aka_list)
+    {
+        if (pos->ref_count > 1) {
+            continue;
+        }
+        vfs_d_free(pos);
+    }
+}
+
+#define ATTR_TABLE_LEN 16
+
+void
+taskfs_export_attr(const char* key, struct twimap* attr_map_file)
+{
+    struct task_attribute* tattr = valloc(sizeof(*tattr));
+
+    tattr->map_file = attr_map_file;
+    tattr->key = HSTR(tattr->key_val, 0);
+    strncpy(tattr->key_val, key, 32);
+    hstr_rehash(&tattr->key, HSTR_FULL_HASH);
+
+    struct hbucket* slot = &attr_export_table[tattr->key.hash % ATTR_TABLE_LEN];
+    hlist_add(&slot->head, &tattr->attrs);
+    llist_append(&attributes, &tattr->siblings);
+}
+
+struct task_attribute*
+taskfs_get_attr(struct hstr* key)
+{
+    struct hbucket* slot = &attr_export_table[key->hash % ATTR_TABLE_LEN];
+    struct task_attribute *pos, *n;
+    hashtable_bucket_foreach(slot, pos, n, attrs)
+    {
+        if (HSTR_EQ(&pos->key, key)) {
+            return pos;
+        }
+    }
+    return NULL;
+}
+
+extern void
+export_task_attr();
+
+void
+taskfs_init()
+{
+    struct filesystem* taskfs = fsm_new_fs("taskfs", 5);
+    taskfs->mount = taskfs_mount;
+
+    fsm_register(taskfs);
+
+    attr_export_table = vcalloc(ATTR_TABLE_LEN, sizeof(struct hbucket));
+
+    export_task_attr();
+}
\ No newline at end of file
diff --git a/lunaix-os/kernel/service/pconsole.c b/lunaix-os/kernel/service/pconsole.c
deleted file mode 100644 (file)
index 200303d..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-#include <lunaix/keyboard.h>
-#include <lunaix/lxconsole.h>
-#include <lunaix/proc.h>
-
-void
-_pconsole_main()
-{
-    struct kdb_keyinfo_pkt keyevent;
-    while (1) {
-        if (!kbd_recv_key(&keyevent)) {
-            yield();
-            continue;
-        }
-        if ((keyevent.state & KBD_KEY_FPRESSED)) {
-            if (keyevent.keycode == KEY_UP) {
-                console_view_up();
-            } else if (keyevent.keycode == KEY_DOWN) {
-                console_view_down();
-            }
-        }
-    }
-}
\ No newline at end of file
index 87726b01fce4ab150fbc6f4f82513019577119b1..860b201d8f2b6542b0990f34f0500a3478e64812 100644 (file)
@@ -7,7 +7,7 @@ static char buffer[1024];
 void
 __assert_fail(const char* expr, const char* file, unsigned int line)
 {
-    sprintf(buffer, "%s (%s:%u)", expr, file, line);
+    ksprintf(buffer, "%s (%s:%u)", expr, file, line);
 
     // Here we load the buffer's address into %edi ("D" constraint)
     //  This is a convention we made that the LUNAIX_SYS_PANIC syscall will
@@ -30,7 +30,7 @@ panickf(const char* fmt, ...)
 {
     va_list args;
     va_start(args, fmt);
-    __sprintf_internal(buffer, fmt, 1024, args);
+    __ksprintf_internal(buffer, fmt, 1024, args);
     va_end(args);
 
     asm("int %0" ::"i"(LUNAIX_SYS_PANIC), "D"(buffer));
index 15a6a32aaf5fbf67527457578d30ebf52f46f18c..0f0457530df0f70240de7a6dae5caa8adec0ec5d 100644 (file)
@@ -1,5 +1,6 @@
 #include <hal/rtc.h>
 #include <lunaix/clock.h>
+#include <lunaix/fs/twifs.h>
 #include <lunaix/spike.h>
 #include <lunaix/timer.h>
 
@@ -8,6 +9,52 @@ static volatile time_t sys_time;
 void
 clock_systime_counter(void* arg);
 
+void
+__clock_read_systime(struct twimap* map)
+{
+    time_t save = sys_time;
+    twimap_printf(map, "%u", save);
+}
+
+void
+__clock_read_datetime(struct twimap* map)
+{
+    datetime_t dt;
+    clock_walltime(&dt);
+    twimap_printf(map,
+                  "%.4d-%.2d-%.2d %.2d:%.2d:%.2d",
+                  dt.year,
+                  dt.month,
+                  dt.day,
+                  dt.hour,
+                  dt.minute,
+                  dt.second);
+}
+
+void
+__clock_read_unix(struct twimap* map)
+{
+    datetime_t dt;
+    clock_walltime(&dt);
+    twimap_printf(map, "%u", clock_tounixtime(&dt));
+}
+
+void
+clock_build_mapping()
+{
+    struct twifs_node* root = twifs_dir_node(NULL, "clock");
+    struct twimap* map;
+
+    map = twifs_mapping(root, NULL, "systime");
+    map->read = __clock_read_systime;
+
+    map = twifs_mapping(root, NULL, "unix");
+    map->read = __clock_read_unix;
+
+    map = twifs_mapping(root, NULL, "datetime");
+    map->read = __clock_read_datetime;
+}
+
 void
 clock_init()
 {
@@ -17,6 +64,8 @@ clock_init()
 
     // 系统计时器每毫秒累加。
     timer_run_ms(1, clock_systime_counter, NULL, TIMER_MODE_PERIODIC);
+
+    clock_build_mapping();
 }
 
 void
diff --git a/lunaix-os/kernel/tty/lxconsole.c b/lunaix-os/kernel/tty/lxconsole.c
new file mode 100644 (file)
index 0000000..ad3fc42
--- /dev/null
@@ -0,0 +1,317 @@
+#include <klibc/string.h>
+#include <lunaix/device.h>
+#include <lunaix/input.h>
+#include <lunaix/ioctl.h>
+#include <lunaix/keyboard.h>
+#include <lunaix/lxconsole.h>
+#include <lunaix/mm/pmm.h>
+#include <lunaix/mm/valloc.h>
+#include <lunaix/mm/vmm.h>
+#include <lunaix/sched.h>
+#include <lunaix/tty/console.h>
+#include <lunaix/tty/tty.h>
+
+#include <lunaix/lxsignal.h>
+
+static struct console lx_console;
+
+int
+__tty_write(struct device* dev, void* buf, size_t offset, size_t len);
+
+int
+__tty_read(struct device* dev, void* buf, size_t offset, size_t len);
+
+void
+console_flush();
+
+static waitq_t lx_reader;
+static volatile char ttychr;
+
+static pid_t fg_pgid = 0;
+
+inline void
+print_control_code(const char cntrl)
+{
+    console_write_char('^');
+    console_write_char(cntrl + 64);
+}
+
+int
+__lxconsole_listener(struct input_device* dev)
+{
+    uint32_t key = dev->current_pkt.sys_code;
+    uint32_t type = dev->current_pkt.pkt_type;
+    kbd_kstate_t state = key >> 16;
+    ttychr = key & 0xff;
+    key = key & 0xffff;
+
+    if (type == PKT_RELEASE) {
+        goto done;
+    }
+
+    if ((state & KBD_KEY_FLCTRL_HELD)) {
+        char cntrl = (char)(ttychr | 0x20);
+        if ('a' > cntrl || cntrl > 'z') {
+            goto done;
+        }
+        ttychr = cntrl - 'a' + 1;
+        switch (ttychr) {
+            case TCINTR:
+                signal_send(-fg_pgid, _SIGINT);
+                print_control_code(ttychr);
+                break;
+            case TCSTOP:
+                signal_send(-fg_pgid, _SIGSTOP);
+                print_control_code(ttychr);
+                break;
+            default:
+                break;
+        }
+    } else if (key == KEY_PG_UP) {
+        console_view_up();
+        goto done;
+    } else if (key == KEY_PG_DOWN) {
+        console_view_down();
+        goto done;
+    } else if ((key & 0xff00) <= KEYPAD) {
+        ttychr = key;
+    } else {
+        goto done;
+    }
+
+    pwake_all(&lx_reader);
+
+done:
+    return INPUT_EVT_NEXT;
+}
+
+int
+__tty_exec_cmd(struct device* dev, uint32_t req, va_list args)
+{
+    switch (req) {
+        case TIOCGPGRP:
+            return fg_pgid;
+        case TIOCSPGRP:
+            fg_pgid = va_arg(args, pid_t);
+            break;
+        case TIOCCLSBUF:
+            fifo_clear(&lx_console.output);
+            fifo_clear(&lx_console.input);
+            lx_console.wnd_start = 0;
+            lx_console.lines = 0;
+            lx_console.output.flags |= FIFO_DIRTY;
+            break;
+        case TIOCFLUSH:
+            lx_console.output.flags |= FIFO_DIRTY;
+            console_flush();
+            break;
+        default:
+            return EINVAL;
+    }
+    return 0;
+}
+
+void
+lxconsole_init()
+{
+    memset(&lx_console, 0, sizeof(lx_console));
+    fifo_init(&lx_console.output, valloc(8192), 8192, 0);
+    fifo_init(&lx_console.input, valloc(4096), 4096, 0);
+
+    lx_console.flush_timer = NULL;
+
+    struct device* tty_dev = device_addseq(NULL, &lx_console, "tty");
+    tty_dev->write = __tty_write;
+    tty_dev->read = __tty_read;
+    tty_dev->exec_cmd = __tty_exec_cmd;
+
+    waitq_init(&lx_reader);
+    input_add_listener(__lxconsole_listener);
+}
+
+int
+__tty_write(struct device* dev, void* buf, size_t offset, size_t len)
+{
+    struct console* console = (struct console*)dev->underlay;
+    console_write(console, buf, len);
+}
+
+int
+__tty_read(struct device* dev, void* buf, size_t offset, size_t len)
+{
+    struct console* console = (struct console*)dev->underlay;
+
+    size_t count = fifo_read(&console->input, buf, len);
+    if (count > 0 && ((char*)buf)[count - 1] == '\n') {
+        return count;
+    }
+
+    while (count < len) {
+        pwait(&lx_reader);
+
+        if (ttychr < 0x1B) {
+            // ASCII control codes
+            switch (ttychr) {
+                case TCINTR:
+                    fifo_clear(&console->input);
+                    return 0;
+                case TCBS:
+                    if (fifo_backone(&console->input)) {
+                        console_write_char(ttychr);
+                    }
+                    continue;
+                case TCLF:
+                case TCCR:
+                    goto proceed;
+                default:
+                    break;
+            }
+            print_control_code(ttychr);
+            continue;
+        }
+
+    proceed:
+        console_write_char(ttychr);
+        if (!fifo_putone(&console->input, ttychr) || ttychr == '\n') {
+            break;
+        }
+    }
+    return count + fifo_read(&console->input, buf + count, len - count);
+}
+
+void
+console_schedule_flush()
+{
+    // TODO make the flush on-demand rather than periodic
+}
+
+size_t
+__find_next_line(size_t start)
+{
+    size_t p = start - 1;
+    struct fifo_buf* buffer = &lx_console.output;
+    do {
+        p = (p + 1) % buffer->size;
+    } while (p != buffer->wr_pos && ((char*)buffer->data)[p] != '\n');
+    return p + (((char*)buffer->data)[p] == '\n');
+}
+
+size_t
+__find_prev_line(size_t start)
+{
+    size_t p = start - 1;
+    struct fifo_buf* buffer = &lx_console.output;
+    do {
+        p--;
+    } while (p < lx_console.wnd_start && p != buffer->wr_pos &&
+             ((char*)buffer->data)[p] != '\n');
+
+    if (p > lx_console.wnd_start) {
+        return 0;
+    }
+    return p + 1;
+}
+
+void
+console_view_up()
+{
+    struct fifo_buf* buffer = &lx_console.output;
+    mutex_lock(&buffer->lock);
+    fifo_set_rdptr(buffer, __find_prev_line(buffer->rd_pos));
+    buffer->flags |= FIFO_DIRTY;
+    mutex_unlock(&buffer->lock);
+
+    console_flush();
+}
+
+void
+console_view_down()
+{
+    struct fifo_buf* buffer = &lx_console.output;
+    mutex_lock(&buffer->lock);
+
+    size_t wnd = lx_console.wnd_start;
+    size_t p = __find_next_line(buffer->rd_pos);
+    fifo_set_rdptr(buffer, p > wnd ? wnd : p);
+    buffer->flags |= FIFO_DIRTY;
+    mutex_unlock(&buffer->lock);
+
+    console_flush();
+}
+
+void
+console_flush()
+{
+    if (mutex_on_hold(&lx_console.output.lock)) {
+        return;
+    }
+    if (!(lx_console.output.flags & FIFO_DIRTY)) {
+        return;
+    }
+
+    size_t rdpos_save = lx_console.output.rd_pos;
+    tty_flush_buffer(&lx_console.output);
+    fifo_set_rdptr(&lx_console.output, rdpos_save);
+
+    lx_console.output.flags &= ~FIFO_DIRTY;
+}
+
+void
+console_write(struct console* console, uint8_t* data, size_t size)
+{
+    struct fifo_buf* fbuf = &console->output;
+    mutex_lock(&console->output.lock);
+    fifo_set_rdptr(fbuf, console->wnd_start);
+
+    uint8_t* buffer = fbuf->data;
+    uintptr_t ptr = fbuf->wr_pos;
+    uintptr_t rd_ptr = fbuf->rd_pos;
+
+    char c;
+    for (size_t i = 0; i < size; i++) {
+        c = data[i];
+        if (!c) {
+            continue;
+        }
+        if (c == '\n') {
+            console->lines++;
+        } else if (c == '\x08') {
+            ptr = ptr ? ptr - 1 : fbuf->size - 1;
+            continue;
+        }
+        buffer[ptr] = c;
+        ptr = (ptr + 1) % fbuf->size;
+    }
+
+    fifo_set_wrptr(fbuf, ptr);
+
+    while (console->lines >= TTY_HEIGHT) {
+        rd_ptr = __find_next_line(rd_ptr);
+        console->lines--;
+    }
+
+    fifo_set_rdptr(&lx_console.output, rd_ptr);
+    console->wnd_start = rd_ptr;
+    fbuf->flags |= FIFO_DIRTY;
+    mutex_unlock(&fbuf->lock);
+}
+
+void
+console_write_str(char* str)
+{
+    console_write(&lx_console, str, strlen(str));
+}
+
+void
+console_write_char(char str)
+{
+    console_write(&lx_console, &str, 1);
+}
+
+void
+console_start_flushing()
+{
+    struct lx_timer* timer =
+      timer_run_ms(20, console_flush, NULL, TIMER_MODE_PERIODIC);
+    lx_console.flush_timer = timer;
+}
\ No newline at end of file
index d4ac8d07c4746340846fdb4aefcd318585996938..b8631b6482c935cf313702746ac045033caa87a3 100644 (file)
@@ -6,22 +6,25 @@
 #include <lunaix/tty/tty.h>
 #include <stdint.h>
 
-vga_attribute* tty_vga_buffer = (vga_attribute*)VGA_BUFFER_PADDR;
+vga_attribute* tty_vga_buffer;
 
 vga_attribute tty_theme_color = VGA_COLOR_BLACK;
 
-#define TTY_CLEAR                                                              \
-    asm volatile("rep stosw" ::"D"(tty_vga_buffer),                            \
-                 "c"(TTY_HEIGHT * TTY_WIDTH),                                  \
-                 "a"(tty_theme_color)                                          \
+inline void
+tty_clear()
+{
+    asm volatile("rep stosw" ::"D"(tty_vga_buffer),
+                 "c"(TTY_HEIGHT * TTY_WIDTH),
+                 "a"(tty_theme_color)
                  : "memory");
+}
 
 void
 tty_init(void* vga_buf)
 {
     tty_vga_buffer = (vga_attribute*)vga_buf;
 
-    TTY_CLEAR
+    tty_clear();
 
     io_outb(0x3D4, 0x0A);
     io_outb(0x3D5, (io_inb(0x3D5) & 0xC0) | 13);
@@ -36,23 +39,19 @@ tty_set_theme(vga_attribute fg, vga_attribute bg)
     tty_theme_color = (bg << 4 | fg) << 8;
 }
 
-size_t
-tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size)
+void
+tty_flush_buffer(struct fifo_buf* buf)
 {
     int x = 0, y = 0;
 
     // Clear screen
-    TTY_CLEAR
+    tty_clear();
 
+    char chr;
     int state = 0;
     int g[2] = { 0, 0 };
     vga_attribute current_theme = tty_theme_color;
-    while (1) {
-        size_t ptr = pos % buf_size;
-        if (pos == limit) {
-            break;
-        }
-        char chr = data[pos];
+    while (fifo_readone_async(buf, &chr)) {
         if (state == 0 && chr == '\033') {
             state = 1;
         } else if (state == 1 && chr == '[') {
@@ -84,11 +83,10 @@ tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size)
                 case '\r':
                     x = 0;
                     break;
-                case '\x08':
-                    x = x ? x - 1 : 0;
-                    *(tty_vga_buffer + x + y * TTY_WIDTH) =
-                      (current_theme | 0x20);
-                    break;
+                // case '\x08':
+                //     *(tty_vga_buffer + x + y * TTY_WIDTH) =
+                //       (current_theme | 0x20);
+                //     break;
                 default:
                     *(tty_vga_buffer + x + y * TTY_WIDTH) =
                       (current_theme | chr);
@@ -105,10 +103,8 @@ tty_flush_buffer(char* data, size_t pos, size_t limit, size_t buf_size)
                 break;
             }
         }
-        pos++;
     }
     tty_set_cursor(x, y);
-    return pos;
 }
 
 void
similarity index 94%
rename from lunaix-os/libs/klibc/stdio/sprintf.c
rename to lunaix-os/libs/klibc/stdio/ksprintf.c
index ade37bbf1ea97a723bb1e9e7065ebc0ce26ec655..2497e107b7821eba1ebe3eb7f09d49a2d3ce8b10 100644 (file)
@@ -20,7 +20,7 @@ static const char flag_chars[] = "#0- +";
 #define FLAG_CAPS (1 << 9)
 
 size_t
-__sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
+__ksprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
 {
     // This sprintf just a random implementation I found it on Internet . lol.
     //      Of course, with some modifications for porting to LunaixOS :)
@@ -102,6 +102,9 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
                              : va_arg(vargs, unsigned);
                 flags |= FLAG_NUMERIC;
                 break;
+            case 'b':
+                base = 2;
+                goto format_unsigned;
             case 'x':
                 base = 16;
                 goto format_unsigned;
@@ -196,21 +199,21 @@ __sprintf_internal(char* buffer, char* fmt, size_t max_len, va_list vargs)
 }
 
 size_t
-sprintf(char* buffer, char* fmt, ...)
+ksprintf(char* buffer, char* fmt, ...)
 {
     va_list args;
     va_start(args, fmt);
-    size_t len = __sprintf_internal(buffer, fmt, 0, args);
+    size_t len = __ksprintf_internal(buffer, fmt, 0, args);
     va_end(args);
     return len;
 }
 
 size_t
-snprintf(char* buffer, size_t n, char* fmt, ...)
+ksnprintf(char* buffer, size_t n, char* fmt, ...)
 {
     va_list args;
     va_start(args, fmt);
-    size_t len = __sprintf_internal(buffer, fmt, n, args);
+    size_t len = __ksprintf_internal(buffer, fmt, n, args);
     va_end(args);
     return len;
 }
\ No newline at end of file
index 12586064cd6767fe36abb89139dc4eb2f180a45a..1f7a06d08a928333909ec35d917eeaf08382c42b 100644 (file)
@@ -1,11 +1,11 @@
 #include <klibc/string.h>
 
 char*
-strcpy(char* dest, const char* src) {
+strcpy(char* dest, const char* src)
+{
     char c;
     unsigned int i = 0;
-    while ((c = src[i]))
-    {
+    while ((c = src[i])) {
         dest[i] = c;
         i++;
     }
@@ -14,10 +14,13 @@ strcpy(char* dest, const char* src) {
 }
 
 char*
-strncpy(char* dest, const char* src, size_t n) {
+strncpy(char* dest, const char* src, size_t n)
+{
     char c;
     unsigned int i = 0;
-    while ((c = src[i]) && i < n) dest[i++] = c;
-    while (i < n) dest[i++] = 0;
+    while ((c = src[i]) && i <= n)
+        dest[i++] = c;
+    while (i <= n)
+        dest[i++] = 0;
     return dest;
 }
\ No newline at end of file
index 82f29bd717ead44bcaddd5dd4c9fc6927a211a4c..fb907fa5673585413ac99c421b971d336414e585 100644 (file)
@@ -18,12 +18,16 @@ strrtrim(char* str)
     str[l + 1] = '\0';
 }
 
-void*
+char*
 strltrim_safe(char* str)
 {
     size_t l = 0;
     char c = 0;
-    while ((c = str[l++]) && WS_CHAR(c))
-        ;
+    while ((c = str[l]) && WS_CHAR(c)) {
+        l++;
+    }
+
+    if (!l)
+        return str;
     return strcpy(str, str + l);
 }
\ No newline at end of file
diff --git a/lunaix-os/libs/ulibc/printf.c b/lunaix-os/libs/ulibc/printf.c
new file mode 100644 (file)
index 0000000..18e2387
--- /dev/null
@@ -0,0 +1,23 @@
+#include <klibc/stdio.h>
+#include <lunaix/lunistd.h>
+#include <lunaix/spike.h>
+#include <ulibc/stdio.h>
+
+// This is VERY bad implementation as it mixes both kernel and user space
+// code together. It is here however, just for the convenience of our testing
+// program.
+// FIXME Eliminate this when we're able to load program.
+
+void __USER__
+printf(const char* fmt, ...)
+{
+    const char buf[512];
+    va_list args;
+    va_start(args, fmt);
+
+    size_t sz = __ksprintf_internal(buf, fmt, 512, args);
+
+    write(stdout, buf, sz);
+
+    va_end(args);
+}
\ No newline at end of file