aboutsummaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorMarvin Borner2021-02-14 17:07:29 +0100
committerMarvin Borner2021-02-14 17:07:29 +0100
commit1287f9dfe987f0456e4fb0741385d5f0278ef53b (patch)
tree64d3da484a4d186a725779f20d339432d51f441a /kernel
parentbc4e62f629a392e1a4cf204665e91c57f4e619b2 (diff)
Message waiting and more!
Diffstat (limited to 'kernel')
-rw-r--r--kernel/drivers/ide.c6
-rw-r--r--kernel/drivers/keyboard.c5
-rw-r--r--kernel/drivers/mouse.c5
-rw-r--r--kernel/features/fs.c36
-rw-r--r--kernel/features/proc.c98
-rw-r--r--kernel/features/syscall.c6
-rw-r--r--kernel/inc/fs.h3
-rw-r--r--kernel/inc/proc.h16
-rw-r--r--kernel/main.c3
9 files changed, 128 insertions, 50 deletions
diff --git a/kernel/drivers/ide.c b/kernel/drivers/ide.c
index 8fc90c9..9be7956 100644
--- a/kernel/drivers/ide.c
+++ b/kernel/drivers/ide.c
@@ -126,7 +126,7 @@ void ata_probe(void)
if (!ide_find(bus, drive))
continue;
- struct device *dev = malloc(sizeof(*dev));
+ struct device *dev = zalloc(sizeof(*dev));
struct ata_data *data = malloc(sizeof(*data));
data->drive = (bus << 1) | drive;
@@ -144,7 +144,7 @@ void ata_probe(void)
continue;
// TODO: Check if ext2 first
- struct vfs *vfs = malloc(sizeof(*vfs));
+ struct vfs *vfs = zalloc(sizeof(*vfs));
vfs->type = VFS_EXT2;
vfs->read = ext2_read;
vfs->stat = ext2_stat;
@@ -158,6 +158,6 @@ void ata_probe(void)
void ata_install(void)
{
- ide_buf = malloc(SECTOR_SIZE);
+ ide_buf = zalloc(SECTOR_SIZE);
ata_probe();
}
diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c
index 1652625..f22af80 100644
--- a/kernel/drivers/keyboard.c
+++ b/kernel/drivers/keyboard.c
@@ -33,8 +33,6 @@ void keyboard_handler()
// TODO: "Merge" scancode to linux keycode?
/* printf("%x %x = %x\n", scancode, state ? 0xe0 : 0, merged); */
- if (event)
- free(event);
event = malloc(sizeof(*event));
event->magic = KEYBOARD_MAGIC;
event->press = (scancode & 0x80) == 0;
@@ -68,6 +66,7 @@ s32 keyboard_read(void *buf, u32 offset, u32 count, struct device *dev)
struct event *e = stack_pop(queue);
memcpy(buf, (u8 *)e + offset, count);
+ free(e);
return count;
}
@@ -87,7 +86,7 @@ void keyboard_install(void)
irq_install_handler(1, keyboard_handler);
queue = stack_new();
- struct device *dev = malloc(sizeof(*dev));
+ struct device *dev = zalloc(sizeof(*dev));
dev->name = strdup("kbd");
dev->type = DEV_CHAR;
dev->read = keyboard_read;
diff --git a/kernel/drivers/mouse.c b/kernel/drivers/mouse.c
index 1e7fd1a..6f329aa 100644
--- a/kernel/drivers/mouse.c
+++ b/kernel/drivers/mouse.c
@@ -35,8 +35,6 @@ void mouse_handler()
case 2:
mouse_byte[2] = (char)inb(0x60);
- if (event)
- free(event);
event = malloc(sizeof(*event));
event->magic = MOUSE_MAGIC;
event->diff_x = mouse_byte[1];
@@ -96,6 +94,7 @@ s32 mouse_read(void *buf, u32 offset, u32 count, struct device *dev)
struct event *e = stack_pop(queue);
memcpy(buf, (u8 *)e + offset, count);
+ free(e);
return count;
}
@@ -181,7 +180,7 @@ void mouse_install(void)
irq_install_handler(12, mouse_handler);
queue = stack_new();
- struct device *dev = malloc(sizeof(*dev));
+ struct device *dev = zalloc(sizeof(*dev));
dev->name = strdup("mouse");
dev->type = DEV_CHAR;
dev->read = mouse_read;
diff --git a/kernel/features/fs.c b/kernel/features/fs.c
index 16a12f7..1744b51 100644
--- a/kernel/features/fs.c
+++ b/kernel/features/fs.c
@@ -120,10 +120,11 @@ s32 vfs_mount(struct device *dev, const char *path)
s32 vfs_read(const char *path, void *buf, u32 offset, u32 count)
{
+ /* printf("%s READ: %s\n", proc_current()->name, path); */
if (!count)
return 0;
- if (offset > count)
+ if (offset > count || !buf)
return -1;
while (*path == ' ')
@@ -144,10 +145,11 @@ s32 vfs_read(const char *path, void *buf, u32 offset, u32 count)
s32 vfs_write(const char *path, void *buf, u32 offset, u32 count)
{
+ /* printf("%s WRITE: %s\n", proc_current()->name, path); */
if (!count)
return 0;
- if (offset > count)
+ if (offset > count || !buf)
return -1;
while (*path == ' ')
@@ -171,6 +173,9 @@ s32 vfs_stat(const char *path, struct stat *buf)
while (*path == ' ')
path++;
+ if (!buf)
+ return -1;
+
struct mount_info *m = vfs_find_mount_info(path);
assert(m && m->dev && m->dev->vfs && m->dev->vfs->stat);
@@ -181,6 +186,27 @@ s32 vfs_stat(const char *path, struct stat *buf)
return m->dev->vfs->stat(path, buf, m->dev);
}
+s32 vfs_wait(const char *path, s32 (*func)())
+{
+ while (*path == ' ')
+ path++;
+
+ struct mount_info *m = vfs_find_mount_info(path);
+ assert(m && m->dev && m->dev->vfs);
+
+ // Default wait
+ if (!m->dev->vfs->wait) {
+ proc_wait_for(vfs_find_dev(path)->id, PROC_WAIT_DEV, func);
+ return 1;
+ }
+
+ u32 len = strlen(m->path);
+ if (len > 1)
+ path += len;
+
+ return m->dev->vfs->wait(path, func, m->dev);
+}
+
s32 vfs_poll(const char **files)
{
if (!files)
@@ -191,7 +217,7 @@ s32 vfs_poll(const char **files)
return p - files;
for (const char **p = files; *p && **p; p++)
- proc_wait_for(vfs_find_dev(*p)->id, PROC_WAIT_DEV, vfs_poll);
+ vfs_wait(*p, vfs_poll);
return PROC_MAX_WAIT_IDS + 1;
}
@@ -280,12 +306,12 @@ void device_install(void)
{
devices = list_new();
- struct vfs *vfs = malloc(sizeof(*vfs));
+ struct vfs *vfs = zalloc(sizeof(*vfs));
vfs->type = VFS_DEVFS;
vfs->read = devfs_read;
vfs->perm = devfs_perm;
vfs->ready = devfs_ready;
- struct device *dev = malloc(sizeof(*dev));
+ struct device *dev = zalloc(sizeof(*dev));
dev->name = "dev";
dev->type = DEV_CHAR;
dev->vfs = vfs;
diff --git a/kernel/features/proc.c b/kernel/features/proc.c
index 9c7fcdc..fdf509c 100644
--- a/kernel/features/proc.c
+++ b/kernel/features/proc.c
@@ -164,30 +164,27 @@ void proc_enable_waiting(u32 id, enum proc_wait_type type)
struct proc *p = iterator->data;
struct proc_wait *w = &p->wait;
- if (!p || !w || w->id_cnt == 0 || w->type != type) {
+ if (!p || !w || w->id_cnt == 0) {
iterator = iterator->next;
continue;
}
- u8 dispatched = 0;
-
current = list_first_data(proc_list, p);
- for (u32 i = 0; i < PROC_MAX_WAIT_IDS; i++) {
- if (w->ids[i] == id) {
+ assert(w->id_cnt < PROC_MAX_WAIT_IDS);
+ for (u32 i = 0; i < w->id_cnt; i++) {
+ if (w->ids[i].magic == PROC_WAIT_MAGIC && w->ids[i].id == id &&
+ w->ids[i].type == type) {
struct regs *r = &p->regs;
- if (w->func)
- r->eax = (u32)w->func((char *)r->ebx, (void *)r->ecx,
- r->edx, r->esi);
- w->ids[i] = 0;
+ if (w->ids[i].func)
+ r->eax = (u32)w->ids[i].func((char *)r->ebx, (void *)r->ecx,
+ r->edx, r->esi);
+ memset(&w->ids[i], 0, sizeof(w->ids[i]));
+ p->wait.id_cnt--;
p->state = PROC_RUNNING;
- dispatched = 1;
break;
}
}
- if (dispatched)
- memset(&p->wait, 0, sizeof(p->wait));
-
iterator = iterator->next;
}
@@ -197,25 +194,45 @@ void proc_enable_waiting(u32 id, enum proc_wait_type type)
void proc_wait_for(u32 id, enum proc_wait_type type, s32 (*func)())
{
+ u8 already_exists = 0;
struct proc *p = proc_current();
- if (p->wait.id_cnt > 0) {
- p->wait.ids[p->wait.id_cnt++] = id;
- assert(func == p->wait.func && type == p->wait.type);
- } else {
- p->wait.type = type;
- p->wait.id_cnt = 1;
- p->wait.ids[0] = id;
- p->wait.func = func;
+ // Check if already exists
+ for (u32 i = 0; i < p->wait.id_cnt; i++) {
+ if (p->wait.ids[i].id == id && p->wait.ids[i].type == type) {
+ assert(p->wait.ids[i].func == func);
+ already_exists = 1;
+ }
+ }
+
+ if (already_exists)
+ goto end;
+
+ assert(p->wait.id_cnt + 1 < PROC_MAX_WAIT_IDS);
+
+ // Find slot
+ struct proc_wait_identifier *slot = NULL;
+ for (u32 i = 0; i < PROC_MAX_WAIT_IDS; i++) {
+ if (p->wait.ids[i].magic != PROC_WAIT_MAGIC) {
+ slot = &p->wait.ids[i];
+ break;
+ }
}
+ assert(slot != NULL);
+
+ slot->magic = PROC_WAIT_MAGIC;
+ slot->id = id;
+ slot->type = type;
+ slot->func = func;
+ p->wait.id_cnt++;
+end:
p->state = PROC_SLEEPING;
}
struct proc *proc_make(void)
{
- struct proc *proc = malloc(sizeof(*proc));
- memset(proc, 0, sizeof(*proc));
+ struct proc *proc = zalloc(sizeof(*proc));
proc->pid = current_pid++;
proc->super = 0;
proc->messages = stack_new();
@@ -274,7 +291,7 @@ s32 procfs_write(const char *path, void *buf, u32 offset, u32 count, struct devi
path++;
if (!memcmp(path, "msg", 4)) {
stack_push_bot(p->messages, buf); // TODO: Use offset and count
- proc_enable_waiting(dev->id, PROC_WAIT_DEV); // TODO: Better wakeup solution
+ proc_enable_waiting(pid, PROC_WAIT_MSG);
return count;
} else if (!memcmp(path, "io/", 3)) {
path += 3;
@@ -324,10 +341,11 @@ s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struct devic
return count;
} else if (!memcmp(path, "msg", 4)) {
if (stack_empty(p->messages)) {
- return 0;
+ return 0; // This shouldn't happen
} else {
u8 *msg = stack_pop(p->messages);
- printf("Pop: %s\n", msg);
+ if (!msg)
+ return -1;
memcpy(buf, msg + offset, count);
return count;
}
@@ -346,6 +364,29 @@ s32 procfs_read(const char *path, void *buf, u32 offset, u32 count, struct devic
return -1;
}
+s32 procfs_wait(const char *path, s32 (*func)(), struct device *dev)
+{
+ u32 pid = 0;
+ procfs_parse_path(&path, &pid);
+
+ if (pid) {
+ struct proc *p = proc_from_pid(pid);
+ if (!p || path[0] != '/')
+ return -1;
+
+ path++;
+ if (!memcmp(path, "msg", 4)) {
+ proc_wait_for(pid, PROC_WAIT_MSG, func);
+ return 1;
+ } else {
+ proc_wait_for(dev->id, PROC_WAIT_DEV, func);
+ return 1;
+ }
+ }
+
+ return -1;
+}
+
u8 procfs_perm(const char *path, enum vfs_perm perm, struct device *dev)
{
(void)path;
@@ -398,14 +439,15 @@ void proc_init(void)
proc_list = list_new();
// Procfs
- struct vfs *vfs = malloc(sizeof(*vfs));
+ struct vfs *vfs = zalloc(sizeof(*vfs));
vfs->type = VFS_PROCFS;
vfs->read = procfs_read;
vfs->write = procfs_write;
+ vfs->wait = procfs_wait;
vfs->perm = procfs_perm;
vfs->ready = procfs_ready;
vfs->data = NULL;
- struct device *dev = malloc(sizeof(*dev));
+ struct device *dev = zalloc(sizeof(*dev));
dev->name = "proc";
dev->type = DEV_CHAR;
dev->vfs = vfs;
diff --git a/kernel/features/syscall.c b/kernel/features/syscall.c
index 80c3e9e..9f05471 100644
--- a/kernel/features/syscall.c
+++ b/kernel/features/syscall.c
@@ -40,8 +40,10 @@ void syscall_handler(struct regs *r)
if (vfs_ready((char *)r->ebx)) {
r->eax = (u32)vfs_read((char *)r->ebx, (void *)r->ecx, r->edx, r->esi);
} else {
- proc_wait_for(vfs_find_dev((char *)r->ebx)->id, PROC_WAIT_DEV, vfs_read);
- proc_yield(r);
+ if (vfs_wait((char *)r->ebx, vfs_read) < 0)
+ r->eax = -1;
+ else
+ proc_yield(r);
}
break;
}
diff --git a/kernel/inc/fs.h b/kernel/inc/fs.h
index 1f46ba3..868cd3e 100644
--- a/kernel/inc/fs.h
+++ b/kernel/inc/fs.h
@@ -41,6 +41,7 @@ struct vfs {
s32 (*read)(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
s32 (*write)(const char *path, void *buf, u32 offset, u32 count, struct device *dev);
s32 (*stat)(const char *path, struct stat *buf, struct device *dev);
+ s32 (*wait)(const char *path, s32 (*func)(), struct device *dev);
u8 (*perm)(const char *path, enum vfs_perm perm, struct device *dev);
u8 (*ready)(const char *path, struct device *dev);
};
@@ -60,10 +61,12 @@ struct device *vfs_find_dev(const char *path);
s32 vfs_read(const char *path, void *buf, u32 offset, u32 count);
s32 vfs_write(const char *path, void *buf, u32 offset, u32 count);
s32 vfs_stat(const char *path, struct stat *buf);
+s32 vfs_wait(const char *path, s32 (*func)());
s32 vfs_poll(const char **files);
u8 vfs_ready(const char *path);
struct device *device_get_by_name(const char *name);
+struct device *device_get_by_id(u32 id);
/**
* EXT2
diff --git a/kernel/inc/proc.h b/kernel/inc/proc.h
index 593141b..cb583d6 100644
--- a/kernel/inc/proc.h
+++ b/kernel/inc/proc.h
@@ -17,21 +17,27 @@
#define GDT_USER_CODE_OFFSET 0x1b // User code segment offset in GDT (with ring3 mask)
#define GDT_USER_DATA_OFFSET 0x23 // User data segment offset in GDT (with ring3 mask)
-#define PROC_MAX_WAIT_IDS 16
+#define PROC_MAX_WAIT_IDS 128
+#define PROC_WAIT_MAGIC 0x00528491
#define STREAM_MAX_SIZE 4096
enum stream_defaults { STREAM_IN, STREAM_OUT, STREAM_ERR, STREAM_LOG, STREAM_UNKNOWN = -1 };
enum proc_state { PROC_RUNNING, PROC_SLEEPING };
-enum proc_wait_type { PROC_WAIT_DEV };
+enum proc_wait_type { PROC_WAIT_DEV, PROC_WAIT_MSG };
-struct proc_wait {
+struct proc_wait_identifier {
+ u32 magic;
+ u32 id;
enum proc_wait_type type;
- u32 ids[PROC_MAX_WAIT_IDS]; // dev_id
- u32 id_cnt;
s32 (*func)();
};
+struct proc_wait {
+ struct proc_wait_identifier ids[PROC_MAX_WAIT_IDS]; // dev_id
+ u32 id_cnt;
+};
+
struct stream {
u32 offset_read;
u32 offset_write;
diff --git a/kernel/main.c b/kernel/main.c
index c20dee4..5216401 100644
--- a/kernel/main.c
+++ b/kernel/main.c
@@ -24,7 +24,8 @@ void kernel_main(struct vid_info *vid_info)
// Serial connection
serial_install();
- serial_print("\nConnected.\n");
+ serial_print("\nKernel was compiled at " __TIME__ " on " __DATE__ "\n");
+ serial_print("Serial connected.\n");
cpu_print();