commit - 7abd0aa7f90dfa1a7147252f69971b23d6a119c9
commit + 7b1f1314a4618908b79db56b86bae5c9306dc65f
blob - 3d351992d333c0c5df49bc4885d6bcd0b4f97c92
blob + 6574b6b771e87848e935b310dd24595b5227bcd1
--- alpha/libc.c
+++ alpha/libc.c
void
output(const u8 *msg)
{
- struct sysc_echo echo;
- echo.sysc.type = SYSC_ECHO;
- echo.type = SYSC_ECHO_STRING;
- echo.msg = msg;
- sys_send((struct sysc *)&echo);
+ struct sysc sysc;
+ sysc.type = SYSC_ECHO;
+ sysc.echo.cmd = SYSC_ECHO_STRING;
+ for (int i = 0; i < SYSC_ECHO_MSG_LEN; i++) {
+ sysc.echo.msg[i] = msg[i];
+ if (msg[i] == '\0')
+ break;
+
+ if (i == SYSC_ECHO_MSG_LEN - 1)
+ sysc.echo.msg[i] = '\0';
+ }
+ sys_send(&sysc);
}
void
outputi(u64 i)
{
- struct sysc_echo echo;
- echo.sysc.type = SYSC_ECHO;
- echo.type = SYSC_ECHO_INTEGER;
- echo.number = i;
- sys_send((struct sysc *)&echo);
+ struct sysc sysc;
+ sysc.type = SYSC_ECHO;
+ sysc.echo.cmd = SYSC_ECHO_INTEGER;
+ sysc.echo.number = i;
+ sys_send(&sysc);
}
void
outputh(u64 i)
{
- struct sysc_echo echo;
- echo.sysc.type = SYSC_ECHO;
- echo.type = SYSC_ECHO_HEXADECIMAL;
- echo.number = i;
- sys_send((struct sysc *)&echo);
+ struct sysc sysc;
+ sysc.type = SYSC_ECHO;
+ sysc.echo.cmd = SYSC_ECHO_HEXADECIMAL;
+ sysc.echo.number = i;
+ sys_send(&sysc);
}
blob - aa80895e24f1195b07f322154bb5f0f0912a0cb0
blob + e3c44299d8e2701bebb331312b659d8ccf0b5a63
--- alpha/libc.h
+++ alpha/libc.h
#include "types.h"
+// Resources given to a thread on initialization
+struct contract {
+ u8 *memBlock; // This is guaranteed to be zero'd at entry point
+ u64 memSize;
+
+ u8 *sharedBlock; // Guaranteed to be zero'd at entry point as well
+ u64 sharedCount;
+};
+
// If you come from Unix-like this is kinda
// like print.
void outputi(u64);
void outputh(u64);
+
+// Memory allocation
blob - 8c5eb444d30483b9169d4472de388a9f08637b48
blob + 1a2e9694bafd83253434326ace1ffd76de2b7ae1
--- alpha/main.c
+++ alpha/main.c
for (;;);
}
+
static struct task*
task_new(void *entry)
{
- struct sysc_new_thread snt;
+ struct sysc sysc;
- snt.sysc.type = SYSC_NEW_THREAD;
- snt.entry = entry;
+ sysc.type = SYSC_NEW_THREAD;
+ sysc.new_thread.entry = entry;
+ sysc.new_thread.memsize = PAGE_SIZE;
+ sysc.new_thread.seats = 0;
for (int i = 0; i < MAX_TASKS; i++) {
if (tasks[i].assigned == 0) {
- sys_send((struct sysc *)&snt);
+ sys_send(&sysc);
- if (snt.retid == -1)
+ if (sysc.new_thread.ret_id == -1)
break;
tasks[i].assigned = 1;
- tasks[i].thread = snt.retid;
+ tasks[i].thread = sysc.new_thread.ret_id;
return &tasks[i];
}
}
blob - 626656de7372e28c8776f0e056d187d7fdb35b4d
blob + f1d4f0c49a7a3c8123c165c16d1de3bc11dfb79d
--- build.sh
+++ build.sh
KERNEL_DIR=kernel
OS_NAME=49.bin
-INCS='-I common -I .'
+INCS='-I common -I . -I alpha'
# Root task
cd alpha
blob - cee74ed4f57f2cd2531915e4dc3972c890094c26
blob + 4bbea456c1fc5e1c47816117ea97cf496fac0d68
--- c449
+++ c449
In this example thread 1 `main` is not able to read thread 0 static
`name` variable.
+[ ENTRY POINT ]
+In traditionnal C, the main function is the entry point. It allows
+argc and argv. In c449 it is different. Because of how the language
+is directly tied to the operating system. The entry point becomes.
+
+void main(struct contract *con, int argc, u8 *argv);
+
+Where con contains the data requested in the executable header for
+the thread to manage. Each thread entry follows this syntax.
+
+
[ C PREPROCESSOR ]
There are minor differences within C449. #define keyword does not
blob - 80dc8b3b55590067ed94ce974b03df157bb78893
blob + bb2f9923c7086b799d508df2928705ea6e57536a
--- kernel/kmain.c
+++ kernel/kmain.c
}
kprint("IDT configured!\n");
- syscall_init();
ammap = kmmap_init(kinfo);
if (ammap == nil) {
return;
}
+ syscall_init();
kpic_setup();
kprint("Page tables configured!\n");
static void
kloop(struct module *amodule, struct mmap *ammap)
{
- struct thread *athread = thread_create((void (*)(void))(u64)amodule->entry);
+ struct thread *athread = thread_create((void (*)(void))(u64)amodule->entry, nil);
+ athread->state = THREAD_RUNNING;
if (athread == nil)
kprint("Failed to create thread\n");
blob - 62195e7b1db99e5a7a72a440fefd5dd6630afab3
blob + 077a29ae933f75dc7207fb1a35d01863c1e87b4e
--- kernel/kmmap.c
+++ kernel/kmmap.c
count++;
if (count == pages) {
- for (u64 f = start; f < start + pages; f++)
+ for (u64 f = start; f < start + pages; f++) {
set_bitmap(f * PAGE_SIZE);
+ }
- // kprint("Address: "); kprinth(vminfo.tables[start]); kprint("\n");
return (u64 *)(start * PAGE_SIZE);
}
} else {
blob - 2aaa27bd3d0a50f812e72284bcf53e13aaaad651
blob + f6fa1af4a7b0b7ba0d65afb136dece90e87f1654
--- kernel/kthreads.c
+++ kernel/kthreads.c
#include "kmmap.h"
#include "kdebug.h"
#include "kthreads.h"
+#include "libc.h"
#define MAX_USER_THREADS 64
struct thread *cthread;
struct thread*
-thread_create(void (*entry)(void))
+thread_create(void (*entry)(void), struct sysc_new_thread *nthread)
{
struct thread *thread = nil;
u64 *sp, usp;
}
thread->base = allocate_memory(PAGE_SIZE * 2);
+ thread->con->memBlock = nil;
+ thread->con->memSize = 0;
if (thread->base == nil) {
thread->assigned = 0;
return nil;
}
+ if (nthread != nil) {
+ thread->con->memBlock = (u8 *)allocate_memory(nthread->memsize);
+ thread->con->memSize = nthread->memsize;
+
+ for (int i = 0; i < thread->con->memSize; i++)
+ thread->con->memBlock[i] = 0;
+ }
+
sp = (u64 *)((u8*)thread->base + PAGE_SIZE * 2);
usp = (u64)sp;
*(--sp) = 0x08; // Kernel CS
*(--sp) = (u64)entry; // RIP
+ *(--sp) = (u64)thread->con; // rdi, this is the struct contract passed
*(--sp) = 0; // rbp
*(--sp) = 0; // rbx
*(--sp) = 0; // r12
return thread;
}
+void
+thread_delete(u64 threadid)
+{
+ struct thread uthreads[threadid];
+}
+
s64
thread_getuid(struct thread *th)
{
s64 uid = cid;
for (u64 count = 0; count < MAX_USER_THREADS; count++) {
- uid = (uid + 1) % MAX_USER_THREADS;
+ uid = (uid + 1) % MAX_USER_THREADS;
- struct thread *th = &uthreads[uid];
+ struct thread *th = &uthreads[uid];
- if (th->assigned)
- return th;
+ if (th->assigned && th->state == THREAD_RUNNING)
+ return th;
}
return nil;
}
blob - db7769a823069ca6a111484422253a3d2584125a
blob + 19fbabd1b9e9124fcbbe564306ffed98b5414247
--- kernel/kthreads.h
+++ kernel/kthreads.h
#pragma once
+#include "libc.h"
#include "kmmap.h"
+#include "syscalls/syscalls.h"
enum thread_state {
THREAD_READY,
u64 *top;
u64 rsp;
+ struct contract *con;
+
u8 assigned;
enum thread_state state;
};
extern struct thread *cthread;
-struct thread *thread_create(void (*entry)(void));
+struct thread *thread_create(void (*entry)(void), struct sysc_new_thread *);
s64 thread_getuid(struct thread *th);
void thread_schedule(struct mmap *, struct thread *);
struct thread* thread_next(void);
blob - 2dc35b1e0b56da7ebf126adaf33be290cd292dc7
blob + 9a2536142cad0000aaa41b994eea2d2b3c4328b7
--- kernel/lidt.s
+++ kernel/lidt.s
timer_handler:
cli
+ push rdi
push rbp
push rbx
push r12
pop r12
pop rbx
pop rbp
+ pop rdi
iretq
blob - 014a9a1f363403a2edea51c96f40aa503e2abfb4
blob + 478f81a77d1f715eab260debc263446726aeda1f
--- kernel/switch.s
+++ kernel/switch.s
global start_alpha
start_alpha:
+ cli
mov rsp, [rsi + RSP_OFFSET]
+ pop rdi
pop r15
pop r14
pop r13
pop r12
pop rbx
pop rbp
-
+
iretq
; See kthread struct
blob - ef4077ea1afc937475b103521f2bd6c238d74b47
blob + af6e2abed99462469afc6841fd8300cd54b9c97c
--- kernel/syscalls.c
+++ kernel/syscalls.c
#include "types.h"
+#include "kmmap.h"
#include "kdebug.h"
#include "kthreads.h"
#include "syscalls/syscalls.h"
-#define MAX_SEATS 64
+#define MAX_SEATS 256
+#define MAX_SYSC_QUEUE 64
+#define THREADID_NONE -1
struct seatmap {
- u64 send; // Sender Thread
- u64 recv; // Receiver Thread
+ s64 send; // Sender Thread
+ s64 recv; // Receiver Thread
};
static struct seatmap seatmaps[MAX_SEATS];
+static u8 *sbuffers;
+s8
+seat_new(u64 threadid)
+{
+ for (int i = 0; i < MAX_SEATS; i++) {
+ if (seatmaps[i].recv == THREADID_NONE) {
+ seatmaps[i].recv = threadid;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
void syscall_handler(struct sysc *);
// Trampoline
{
u8 *jump = (u8 *)SYSC_BELL;
u64 addr = (u64)&syscall_handler;
+ sbuffers = (u8 *)allocate_memory(PAGE_SIZE * MAX_SEATS);
+ if (sbuffers == nil) {
+ kprint("Failed to create seat buffers!\n");
+ repeat:
+ goto repeat;
+ }
+
+ for (int i = 0; i < MAX_SEATS; i++) {
+ seatmaps[i].send = THREADID_NONE;
+ seatmaps[i].recv = THREADID_NONE;
+ }
+
// movabs rax, addr
jump[0] = 0x48;
jump[1] = 0xB8;
}
void
-syscall_echo_h(struct sysc_echo *echo)
+syscall_echo_h(struct sysc *call)
{
- switch (echo->type) {
+ struct sysc_echo *echo = &call->echo;
+ switch (echo->cmd) {
case SYSC_ECHO_STRING:
kprint(echo->msg);
break;
}
}
+// This functions creates a thread with all the resources it
+// needs such as the amount of seats. If another thread wishes
+// to connect to a specific thread it just does SYSC_CONNECT
void
-syscall_new_thread_h(struct sysc_new_thread *nthread)
+syscall_new_thread_h(struct sysc *call)
{
- struct thread *th = thread_create(nthread->entry);
+ struct sysc_new_thread *nthread = &call->new_thread;
+ struct thread *th = thread_create(nthread->entry, nthread);
s64 threadid;
if (th == nil)
kprint("failed to create thread from syscall!\n");
+ /*
+ if (seat_new(threadid) == -1) {
+ kprint("Failed to create new seat\n");
+ repeat:
+ goto repeat;
+ }
+ */
+
threadid = thread_getuid(th);
- nthread->retid = threadid;
+ nthread->ret_id = threadid;
+ th->state = THREAD_RUNNING;
kprint("Thread (id="); kprinti(threadid); kprint(") created!\n");
}
{
switch (call->type) {
case SYSC_ECHO:
- syscall_echo_h((struct sysc_echo *)call);
+ syscall_echo_h(call);
break;
case SYSC_NEW_THREAD:
- syscall_new_thread_h((struct sysc_new_thread *)call);
+ syscall_new_thread_h(call);
break;
default:
break;
blob - 9c4f59ed470664e3583932f89f1a9e98980ec009
blob + 355b272393886987af96ba873b5cab4a4589205e
--- servers/xhci/main.c
+++ servers/xhci/main.c
#include "libc.h"
void
-xhci_main()
+xhci_main(struct contract *con)
{
output("xhci: running\n");
+
+ output("xhci: memory size is "); outputi(con->memSize);
+ output(" bytes\n");
+
+ output("Memory block location is : "); outputh((u64)con->memBlock[0]); output("\n");
+
for (;;);
}
blob - d1edb04a4f5cfca5a1ece76b9ed6582ada0a95eb
blob + 4814d52593d770131e8ced32171fbab5cca710de
--- syscalls/syscalls.h
+++ syscalls/syscalls.h
#pragma once
#define SYSC_BELL 0xE00000
+#define SYSC_ECHO_MSG_LEN 256
enum sysc_type {
SYSC_ECHO,
SYSC_NEW_THREAD,
SYSC_FREE_THREAD,
- SYSC_CONTEXT_SWITCH, // This shouldn't be a thing its for testing before APIC and thread states
};
-struct sysc {
- enum sysc_type type;
-};
-
-enum sysc_echo_type {
+enum sysc_echo_cmd {
SYSC_ECHO_STRING,
SYSC_ECHO_INTEGER,
SYSC_ECHO_HEXADECIMAL,
};
struct sysc_echo {
- struct sysc sysc;
- enum sysc_echo_type type;
+ enum sysc_echo_cmd cmd;
union {
- const char *msg;
+ u8 msg[SYSC_ECHO_MSG_LEN];
u64 number;
};
};
struct sysc_new_thread {
- struct sysc sysc;
- void *entry;
- u64 size; // Unused for now
+ void *entry; // Entry point
+ u64 memsize;
+ u64 seats;
- s64 retid; // The threadId returned
+ s64 ret_id;
};
-struct sysc_free_thread {
- struct sysc sysc;
- u64 id;
+struct sysc {
+ enum sysc_type type;
+ union {
+ struct sysc_echo echo;
+ struct sysc_new_thread new_thread;
+ };
};
-struct sysc_context_switch {
- struct sysc sysc;
- u64 threadid;
-};
-
extern void (*sys_send)(struct sysc *call);