forked from PoliEcho-holding-org/kern
Added IPC skeleton
This commit is contained in:
@@ -25,7 +25,8 @@ TODO
|
|||||||
[x] Scheduler
|
[x] Scheduler
|
||||||
[ ] Priority scheduler
|
[ ] Priority scheduler
|
||||||
[x] Task switching
|
[x] Task switching
|
||||||
[ ] Inter-process communication
|
[ ] Interprocess communication
|
||||||
|
[ ] ALL the message types
|
||||||
[ ] Graphics
|
[ ] Graphics
|
||||||
[ ] Multicore support
|
[ ] Multicore support
|
||||||
[ ] Networking :)
|
[ ] Networking :)
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
Unix-like system calls
|
||||||
|
======================
|
||||||
|
|
||||||
|
pid_t fork(void);
|
||||||
|
Creates a child process.
|
||||||
|
|
||||||
|
void exit(int status);
|
||||||
|
Terminate the calling process.
|
||||||
|
|
||||||
|
pid_t waitpid(pid_t pid);
|
||||||
|
Wait untill a process changes state.
|
||||||
|
|
||||||
|
int kill(pid_t, int sig);
|
||||||
|
Send a signal to a process.
|
||||||
|
|
||||||
|
pid_t getpid(void);
|
||||||
|
Get PID of calling process.
|
||||||
|
|
||||||
|
void sleep(size_t t);
|
||||||
|
Sleep for **t** clock ticks.
|
||||||
|
|
||||||
|
int exec(char* path, char** argv);
|
||||||
|
Execute a program.
|
||||||
|
|
||||||
|
int brk(void* addr);
|
||||||
|
Change data segment size.
|
||||||
|
|
||||||
|
int open(char* path, int flags);
|
||||||
|
Open and possibly create a file.
|
||||||
|
|
||||||
|
int close(int fd);
|
||||||
|
Close a file descriptor.
|
||||||
|
|
||||||
|
ssize_t read(int fd, void* buf, size_t count);
|
||||||
|
Read up to **count** bytes into **buf**.
|
||||||
|
|
||||||
|
ssize_t write(int fd, void* buf, size_t count);
|
||||||
|
Write up to **count** bytes from **buf**.
|
||||||
|
|
||||||
|
int dup(int oldfd);
|
||||||
|
Duplicate a file descriptor.
|
||||||
|
|
||||||
|
int pipe(int pipe[2]);
|
||||||
|
Create a pipe and return it's file descriptors in **pipe**.
|
||||||
|
|
||||||
|
int chdir(char* path);
|
||||||
|
Change the current directory of calling process.
|
||||||
|
|
||||||
|
int mkdir(char* path);
|
||||||
|
Create a new directory.
|
||||||
|
|
||||||
|
int mknod(char* path, int maj, int min);
|
||||||
|
Create a new device file.
|
||||||
|
|
||||||
|
int link(char* f1, char* f2);
|
||||||
|
Creates another filename (**f2**) for **f1**.
|
||||||
|
|
||||||
|
int unlink(char* path);
|
||||||
|
Delete a filename.
|
||||||
|
|
||||||
|
int fstat(int fd, struct stat* statbuf);
|
||||||
|
Return info about a file.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef _IPC_H
|
||||||
|
#define _IPC_H
|
||||||
|
|
||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message contents
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Basic data
|
||||||
|
struct msg_uint8 { uint8_t data[56]; };
|
||||||
|
struct msg_uint16 { uint16_t data[28]; };
|
||||||
|
struct msg_uint32 { uint32_t data[14]; };
|
||||||
|
struct msg_uint64 { uint64_t data[7]; };
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message content types
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
MSG_UINT8,
|
||||||
|
MSG_UINT16,
|
||||||
|
MSG_UINT32,
|
||||||
|
MSG_UINT64,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Message struct
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
pid_t sender;
|
||||||
|
uint32_t type;
|
||||||
|
union {
|
||||||
|
struct msg_uint8 m_uint8;
|
||||||
|
struct msg_uint16 m_uint16;
|
||||||
|
struct msg_uint32 m_uint32;
|
||||||
|
struct msg_uint64 m_uint64;
|
||||||
|
|
||||||
|
// Makes sure that ipc_msg_t is at least 64 bytes
|
||||||
|
uint8_t size[56];
|
||||||
|
};
|
||||||
|
} ipc_msg_t __align(16);
|
||||||
|
// Compile time check that ipc_msg_t is 64 bytes
|
||||||
|
typedef int __ASSERT_ipc_msg_t[(sizeof(ipc_msg_t) == 64) ? 1 : -1];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IPC handlers
|
||||||
|
*/
|
||||||
|
int ipc_send(pid_t dst, ipc_msg_t* msg);
|
||||||
|
int ipc_recv(pid_t src, ipc_msg_t* msg);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -30,6 +30,9 @@ typedef char* va_list;
|
|||||||
/*
|
/*
|
||||||
* Utility macros
|
* Utility macros
|
||||||
*/
|
*/
|
||||||
|
#define STATIC_ASSERT(_cond, _msg)\
|
||||||
|
typedef int static_assert_##_msg[(_cond) ? 1 : -1]
|
||||||
|
|
||||||
#define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
#define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0]))
|
||||||
#define BIT(_n) (1UL << (_n))
|
#define BIT(_n) (1UL << (_n))
|
||||||
#define BIT_MASK(_n) (BIT(_n) - 1)
|
#define BIT_MASK(_n) (BIT(_n) - 1)
|
||||||
@@ -84,6 +87,11 @@ typedef int32_t intptr_t;
|
|||||||
#define true 1
|
#define true 1
|
||||||
#define false 0
|
#define false 0
|
||||||
|
|
||||||
|
/*
|
||||||
|
* System types
|
||||||
|
*/
|
||||||
|
typedef uint32_t pid_t;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Linker defined values
|
* Linker defined values
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -2,14 +2,21 @@
|
|||||||
#define _SYSCALL_H
|
#define _SYSCALL_H
|
||||||
|
|
||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
|
#include <ipc.h>
|
||||||
#include <isr.h>
|
#include <isr.h>
|
||||||
|
|
||||||
#define SYSCALL_MAX 2
|
#define SYSCALL_MAX 16
|
||||||
#define SYS_EXIT 0
|
enum {
|
||||||
#define SYS_TEST 1
|
SYS_SEND,
|
||||||
|
SYS_RECV,
|
||||||
|
};
|
||||||
|
|
||||||
int syscall_init(void);
|
int syscall_init(void);
|
||||||
void syscall_register(size_t idx, void* handler);
|
void syscall_register(size_t idx, void* handler);
|
||||||
void syscall_handler(struct isr_int_frame* iframe);
|
void syscall_handler(struct isr_int_frame* iframe);
|
||||||
|
|
||||||
|
// Syscall handlers
|
||||||
|
int sys_send(pid_t dst, ipc_msg_t* msg);
|
||||||
|
int sys_recv(pid_t src, ipc_msg_t* msg);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ enum {
|
|||||||
TASK_STATE_DEAD,
|
TASK_STATE_DEAD,
|
||||||
TASK_STATE_IDLE,
|
TASK_STATE_IDLE,
|
||||||
TASK_STATE_READY,
|
TASK_STATE_READY,
|
||||||
|
TASK_STATE_RECV,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -30,7 +31,7 @@ enum {
|
|||||||
* task.s which uses hardcoded offsets.
|
* task.s which uses hardcoded offsets.
|
||||||
*/
|
*/
|
||||||
struct task {
|
struct task {
|
||||||
size_t id;
|
pid_t id;
|
||||||
|
|
||||||
size_t kstack_pointer;
|
size_t kstack_pointer;
|
||||||
size_t kstack_bottom;
|
size_t kstack_bottom;
|
||||||
@@ -58,13 +59,13 @@ extern struct task* task_first;
|
|||||||
extern struct task* task_current;
|
extern struct task* task_current;
|
||||||
|
|
||||||
int task_init(void);
|
int task_init(void);
|
||||||
void task_create(size_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv);
|
void task_create(pid_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv);
|
||||||
void task_kill(size_t id);
|
void task_kill(pid_t id);
|
||||||
void task_set_user_heap(struct task* task, size_t heap_end);
|
void task_set_user_heap(pid_t id, size_t heap_end);
|
||||||
struct task* task_get(size_t id);
|
struct task* task_get(pid_t id);
|
||||||
uint8_t task_get_state(size_t id);
|
uint8_t task_get_state(pid_t id);
|
||||||
void task_set_state(size_t id, uint8_t state);
|
void task_set_state(pid_t id, uint8_t state);
|
||||||
size_t task_create_id(void);
|
pid_t task_create_id(void);
|
||||||
|
|
||||||
// Defined in task.s
|
// Defined in task.s
|
||||||
extern void task_switch(struct task* old, struct task* new);
|
extern void task_switch(struct task* old, struct task* new);
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
#include <kernel.h>
|
||||||
|
|
||||||
|
#include <ipc.h>
|
||||||
|
|
||||||
|
int ipc_send(pid_t dst, ipc_msg_t* msg) {
|
||||||
|
(void)dst;
|
||||||
|
(void)msg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipc_recv(pid_t src, ipc_msg_t* msg) {
|
||||||
|
(void)src;
|
||||||
|
(void)msg;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -36,10 +36,6 @@ void kmain(void* ptr, uint32_t magic) {
|
|||||||
if (syscall_init() != 0) panic("Failed to initialize syscalls.");
|
if (syscall_init() != 0) panic("Failed to initialize syscalls.");
|
||||||
if (task_init() != 0) panic("Failed to initialize tasking.");
|
if (task_init() != 0) panic("Failed to initialize tasking.");
|
||||||
|
|
||||||
char* s = "Hello, World!";
|
|
||||||
__asm__ volatile("int $0x80" :: "a"(SYS_TEST), "b"(s));
|
|
||||||
|
|
||||||
// TODO: Interprocess communication
|
|
||||||
// TODO: Load & run /sbin/init
|
// TODO: Load & run /sbin/init
|
||||||
|
|
||||||
// We don't want to halt
|
// We don't want to halt
|
||||||
|
|||||||
+14
-11
@@ -1,5 +1,6 @@
|
|||||||
#include <kernel.h>
|
#include <kernel.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
#include <ipc.h>
|
||||||
#include <tty.h>
|
#include <tty.h>
|
||||||
|
|
||||||
#include <syscall.h>
|
#include <syscall.h>
|
||||||
@@ -7,24 +8,26 @@
|
|||||||
// Syscall table
|
// Syscall table
|
||||||
void* syscalls[SYSCALL_MAX] = { 0 };
|
void* syscalls[SYSCALL_MAX] = { 0 };
|
||||||
|
|
||||||
void sys_exit(int code) {
|
|
||||||
debugf("[syscall] Task #%d exited with code %d.\n", task_current->id, code);
|
|
||||||
task_kill(task_current->id);
|
|
||||||
}
|
|
||||||
|
|
||||||
void sys_test(char* msg) {
|
|
||||||
debugf("[syscall] Test: %s\n", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
int syscall_init(void) {
|
int syscall_init(void) {
|
||||||
syscall_register(SYS_EXIT, (void*)sys_exit);
|
syscall_register(SYS_SEND, (void*)sys_send);
|
||||||
syscall_register(SYS_TEST, (void*)sys_test);
|
syscall_register(SYS_RECV, (void*)sys_recv);
|
||||||
|
|
||||||
debugf("[syscall] Initiated syscalls!\n");
|
debugf("[syscall] Initiated syscalls!\n");
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int sys_send(pid_t dst, ipc_msg_t* msg) {
|
||||||
|
msg->sender = task_current->id;
|
||||||
|
debugf("[syscall] Task #%d sent a message to Task #%d.\n", msg->sender, dst);
|
||||||
|
return ipc_send(dst, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int sys_recv(pid_t src, ipc_msg_t* msg) {
|
||||||
|
debugf("[syscall] Task #%d is receiving a message from Task #%d.\n", task_current->id, src);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void syscall_register(size_t idx, void* handler) {
|
void syscall_register(size_t idx, void* handler) {
|
||||||
if (idx > SYSCALL_MAX) {
|
if (idx > SYSCALL_MAX) {
|
||||||
debugf("[syscall] Failed to register syscall #%d.\n", idx);
|
debugf("[syscall] Failed to register syscall #%d.\n", idx);
|
||||||
|
|||||||
+10
-8
@@ -32,7 +32,7 @@ int task_init(void) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_create(size_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv) {
|
void task_create(pid_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, int argc, char** argv) {
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
uint32_t kstack = (uint32_t)kmalloc(0x1000 - 16) + (0x1000 - 16);
|
uint32_t kstack = (uint32_t)kmalloc(0x1000 - 16) + (0x1000 - 16);
|
||||||
@@ -129,7 +129,7 @@ void task_create(size_t id, uint32_t eip, int kernel_task, uint32_t* pagedir, in
|
|||||||
pag_set_pagedir(old_pagedir);
|
pag_set_pagedir(old_pagedir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_kill(size_t id) {
|
void task_kill(pid_t id) {
|
||||||
cli();
|
cli();
|
||||||
|
|
||||||
struct task* current = task_first;
|
struct task* current = task_first;
|
||||||
@@ -174,7 +174,9 @@ void task_kill(size_t id) {
|
|||||||
sti();
|
sti();
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_set_user_heap(struct task* task, size_t heap_end) {
|
void task_set_user_heap(pid_t id, size_t heap_end) {
|
||||||
|
struct task* task = task_get(id);
|
||||||
|
|
||||||
if (heap_end <= task->heap_start) {
|
if (heap_end <= task->heap_start) {
|
||||||
debugf("[task] Task %d tried to shrink heap bellow 0.\n", task->id);
|
debugf("[task] Task %d tried to shrink heap bellow 0.\n", task->id);
|
||||||
task_kill(task->id);
|
task_kill(task->id);
|
||||||
@@ -212,7 +214,7 @@ void task_set_user_heap(struct task* task, size_t heap_end) {
|
|||||||
task->heap_end = heap_end;
|
task->heap_end = heap_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct task* task_get(size_t id) {
|
struct task* task_get(pid_t id) {
|
||||||
struct task* find = task_first;
|
struct task* find = task_first;
|
||||||
while (find != NULL) {
|
while (find != NULL) {
|
||||||
if (find->id == id) break;
|
if (find->id == id) break;
|
||||||
@@ -222,22 +224,22 @@ struct task* task_get(size_t id) {
|
|||||||
return find;
|
return find;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t task_get_state(size_t id) {
|
uint8_t task_get_state(pid_t id) {
|
||||||
struct task* t = task_get(id);
|
struct task* t = task_get(id);
|
||||||
if (t == NULL) return TASK_STATE_DEAD;
|
if (t == NULL) return TASK_STATE_DEAD;
|
||||||
return t->state;
|
return t->state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void task_set_state(size_t id, uint8_t state) {
|
void task_set_state(pid_t id, uint8_t state) {
|
||||||
struct task* t = task_get(id);
|
struct task* t = task_get(id);
|
||||||
if (t == NULL) return;
|
if (t == NULL) return;
|
||||||
t->state = state;
|
t->state = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t task_create_id(void) {
|
pid_t task_create_id(void) {
|
||||||
struct task* current = task_first;
|
struct task* current = task_first;
|
||||||
|
|
||||||
size_t max = current->id;
|
pid_t max = current->id;
|
||||||
current = current->next;
|
current = current->next;
|
||||||
while (current != NULL) {
|
while (current != NULL) {
|
||||||
if (max < current->id) max = current->id;
|
if (max < current->id) max = current->id;
|
||||||
|
|||||||
Reference in New Issue
Block a user