+ 内存管理与按需分页(Demand Paging)
+ 键盘输入
+ 多进程
-+ 44个常见的Linux/POSIX系统调用([附录1](#appendix1))
++ 47个常见的Linux/POSIX系统调用([附录1](#appendix1))
+ 用户模式
+ 信号机制
+ PCI 3.0
正常,**因为Bochs不支持SATA**。请使用QEMU或VirtualBox。
-#### 问题#4:键盘的上下方向键(用于滚屏)在VirtualBox下有时不好使
-
-可以试试`Shift+<方向键>`,这个问题的解决需要重写键盘驱动的状态机。我会找时间去做,毕竟这不是燃眉之急。
-
## 参考教程
**没有!!** 本教程以及该操作系统均为原创,没有基于任何市面上现行的操作系统开发教程,且并非是基于任何的开源内核的二次开发。
2. `setxattr(2)`※
2. `fgetxattr(2)`※
2. `fsetxattr(2)`※
+2. `ioctl(2)`※
+2. `getpgid(2)`
+2. `setpgid(2)`
**LunaixOS自有**
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);
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
{
// TODO: clear the interrupt status
// TODO: I/O-operation scheduler should be here
- kprintf(KDEBUG "HBA INTR\n");
+ // kprintf(KDEBUG "HBA INTR\n");
}
void
#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>
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);
}
}
}
+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)
{
}
}
-#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;
}
}
}
// Otherwise, fallback to use legacy PCI 3.0 method.
pci_probe();
+
+ pci_build_fsmapping();
}
\ No newline at end of file
// 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;
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:
void
pci_init();
-void
-pci_print_device();
-
/**
* @brief 根据类型代码(Class Code)去在拓扑中寻找一个设备
* 类型代码请参阅: PCI LB Spec. Appendix D.
#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 */
void
strrtrim(char* str);
-void*
+char*
strltrim_safe(char* str);
#endif /* __LUNAIX_STRING_H */
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 */
#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
#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, ...);
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 */
#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;
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);
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 */
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.
#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
#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) \
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;
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;
};
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;
uint32_t flags;
uint32_t fpos;
};
-/* --- file system manager --- */
+
void
fsm_init();
void
vfs_init();
+void
+vfs_export_attributes();
+
struct v_dnode*
vfs_dcache_lookup(struct v_dnode* parent, struct hstr* str);
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);
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);
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,
--- /dev/null
+#ifndef __LUNAIX_DEVFS_H
+#define __LUNAIX_DEVFS_H
+
+void
+devfs_init();
+
+#endif /* __LUNAIX_DEVFS_H */
--- /dev/null
+#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 */
#define __LUNAIX_TWIFS_H
#include <lunaix/fs.h>
+#include <lunaix/fs/twimap.h>
+#include <lunaix/spike.h>
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
} 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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
--- /dev/null
+#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 */
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)
#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
#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 */
__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)
#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();
#define PILE_CACHELINE 1
+struct cake_pile;
+
+typedef void (*pile_cb)(struct cake_pile*, void*);
+
struct cake_pile
{
struct llist_header piles;
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;
unsigned int pg_per_cake,
int options);
+void
+cake_set_constructor(struct cake_pile* pile, pile_cb ctor);
+
/**
* @brief 拿一块儿蛋糕
*
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 */
/* 四个页挂载点,两个页目录挂载点: 用于临时创建&编辑页表 */
#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)
#define PS2_DELAY 1000
#define PS2_CMD_QUEUE_SIZE 8
-#define PS2_KBD_RECV_BUFFER_SIZE 8
#define PS2_NO_ARG 0xff00
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`,否则会造成死锁。
#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>
// 虽然内核不是进程,但为了区分,这里使用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
/* ---- critical section end ---- */
+ struct llist_header tasks;
struct llist_header siblings;
struct llist_header children;
struct llist_header grp_member;
+ waitq_t waitqueue;
struct
{
#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;
};
#define EEXIST -12
#define EBADF -13
#define ENOTSUP -14
-#define ENXIO -15
+#define EIO -15
#define ELOOP -16
#define ENOTEMPTY -17
#define EROFS -18
#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__
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 */
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 */
#ifndef __LUNAIX_TTY_H
#define __LUNAIX_TTY_H
+
+#include <lunaix/ds/fifo.h>
+
typedef unsigned short vga_attribute;
#define VGA_COLOR_BLACK 0
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);
#ifndef __LUNAIX_TYPES_H
#define __LUNAIX_TYPES_H
+#include <stdarg.h>
#include <stddef.h>
#include <stdint.h>
--- /dev/null
+#ifndef __LUNAIX_USTDIO_H
+#define __LUNAIX_USTDIO_H
+
+#define stdout 0
+#define stdin 1
+
+void
+printf(const char* fmt, ...);
+
+#endif /* __LUNAIX_USTDIO_H */
{
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();
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:
.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
--- /dev/null
+#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
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
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);
}
vfree(block);
- return rd_block;
+ return acc_size;
error:
vfree(block);
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;
goto error;
}
+ blk_set_blkmapping(bdev);
return errno;
error:
hd_dev->model,
hd_dev->serial_num,
-errno);
+ return errno;
}
int
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
#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);
--- /dev/null
+#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
#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()
// 切换工作目录至 /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 设备 - 硬盘
int fd = open("./sda", 0);
if (fd < 0) {
- kprintf(KERROR "fail to open (%d)\n", geterrno());
+ printf("fail to open (%d)\n", geterrno());
return;
}
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
#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);
}
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__
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);
pause();
- kprintf("Parent resumed on SIGCHILD\n");
+ printf("Parent resumed on SIGCHILD\n");
for (int i = 0; i < 5; i++) {
pid_t pid = 0;
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
--- /dev/null
+#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
+++ /dev/null
-#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
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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;
+}
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)
{
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)
{
--- /dev/null
+#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
--- /dev/null
+#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
--- /dev/null
+#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(¤t_wq->waiters));
+
+ llist_append(&queue->waiters, ¤t_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
--- /dev/null
+#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
#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
{
ramfs_init();
twifs_init();
- // Add more fs implementation
+ devfs_init();
+ taskfs_init();
+
+ // ... more fs implementation
}
\ No newline at end of file
#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)
}
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;
return errno;
cleanup:
+ mnt_point->super_block = old_sb;
vfs_sb_free(sb);
return errno;
}
// 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;
panick("vfs: no root");
}
}
- i++;
+
+ if (path[0] == VFS_PATH_DELIM) {
+ i++;
+ }
}
assert(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;
}
}
}
-struct pcache_pg*
+int
pcache_get_page(struct pcache* pcache,
uint32_t index,
uint32_t* offset,
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;
}
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)
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;
}
}
{
inode->id = ino++;
inode->ops = &ramfs_inode_ops;
- inode->default_fops = &default_file_ops;
+ inode->default_fops = &ramfs_file_ops;
}
int
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
* @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;
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);
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;
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;
}
}
}
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
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,
--- /dev/null
+#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
assert(dnode->ref_count == 1);
llist_delete(&dnode->siblings);
+ llist_delete(&dnode->aka_list);
hlist_delete(&dnode->hash_list);
dnode->parent = NULL;
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++;
}
}
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);
return errno;
}
+int
+vfs_close(struct v_file* file)
+{
+ return vfs_pclose(file, __current->pid);
+}
+
int
vfs_fsync(struct v_file* file)
{
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);
if (parent) {
dnode->super_block = parent->super_block;
+ dnode->mnt = parent->mnt;
}
lru_use_one(dnode_lru, &dnode->lru);
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);
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;
}
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;
}
__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) {
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;
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;
int
vfs_get_path(struct v_dnode* dnode, char* buf, size_t size, int depth)
{
- if (!dnode || dnode->parent == dnode) {
+ if (!dnode) {
return 0;
}
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);
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;
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;
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);
goto done;
}
- errno = __vfs_do_chdir(dnode);
+ errno = vfs_do_chdir(__current, dnode);
done:
return DO_STATUS(errno);
goto done;
}
- errno = __vfs_do_chdir(fd_s->file->dnode);
+ errno = vfs_do_chdir(__current, fd_s->file->dnode);
done:
return DO_STATUS(errno);
#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>
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 };
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();
// 将内核占据的页,包括前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);
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);
}
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);
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';
+++ /dev/null
-#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
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++) {
return pile;
}
+void
+cake_set_constructor(struct cake_pile* pile, pile_cb ctor)
+{
+ pile->ctor = ctor;
+}
+
void*
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
}
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
--- /dev/null
+#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
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
+
+/**** 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
#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*
llist_for_each(pos, n, ®ions->head, head)
{
- lxfree(pos);
+ vfree(pos);
}
}
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) {
if (current_addr >= VMAP_END) {
wrapped = 1;
+ examed_size = 0;
current_addr = VMAP_START;
}
}
#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>
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)
// 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)
{
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) {
/*
* 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;
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;
}
}
#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
}
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);
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;
;
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
#include <klibc/string.h>
+#include <ulibc/stdio.h>
+
LOG_MODULE("PROC0")
extern void
#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();
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
_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);
// 锁定所有系统预留页(内存映射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();
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
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;
}
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);
}
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);
#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 };
}
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)
if (wtime && now >= wtime) {
pos->sleep.wakeup_time = 0;
- pos->state = PS_STOPPED;
+ pos->state = PS_READY;
}
if (atime && now >= atime) {
int ptr = prev_ptr;
if (!(__current->state & ~PS_RUNNING)) {
- __current->state = PS_STOPPED;
+ __current->state = PS_READY;
}
check_sleepers();
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;
void
sched_yieldk()
{
+ cpu_enable_interrupt();
cpu_int(LUNAIX_SCHED);
}
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;
__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;
status_flags |= PEXITTERM;
goto done;
}
- if (proc->state == PS_STOPPED && (options & WUNTRACED)) {
+ if (proc->state == PS_READY && (options & WUNTRACED)) {
status_flags |= PEXITSTOP;
goto done;
}
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) {
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;
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;
}
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;
// 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>
__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);
vmm_unmount_pd(PD_MOUNT_1);
+ cake_release(proc_pile, proc);
+
return pid;
}
if (index < 0 || index > sched_ctx.ptable_len) {
return NULL;
}
- return &sched_ctx._procs[index];
+ return sched_ctx._procs[index];
}
int
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中的一种
{
__SIGSET(pos->sig_pending, signum);
}
- return 0;
send_single:
if (PROC_TERMINATED(proc->state)) {
--- /dev/null
+#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 == ¤t->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
--- /dev/null
+#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
+++ /dev/null
-#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
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
{
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));
#include <hal/rtc.h>
#include <lunaix/clock.h>
+#include <lunaix/fs/twifs.h>
#include <lunaix/spike.h>
#include <lunaix/timer.h>
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()
{
// 系统计时器每毫秒累加。
timer_run_ms(1, clock_systime_counter, NULL, TIMER_MODE_PERIODIC);
+
+ clock_build_mapping();
}
void
--- /dev/null
+#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
#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);
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 == '[') {
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);
break;
}
}
- pos++;
}
tty_set_cursor(x, y);
- return pos;
}
void
#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 :)
: va_arg(vargs, unsigned);
flags |= FLAG_NUMERIC;
break;
+ case 'b':
+ base = 2;
+ goto format_unsigned;
case 'x':
base = 16;
goto format_unsigned;
}
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
#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++;
}
}
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
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
--- /dev/null
+#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