summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/ipc/request.c36
-rw-r--r--src/kernel/ipc/request.h4
-rw-r--r--src/kernel/linker/elf.c6
-rw-r--r--src/kernel/mem/paging.c1
-rw-r--r--src/kernel/mem/paging.h2
-rw-r--r--src/kernel/mem/seg.c21
-rw-r--r--src/kernel/mem/seg.h1
-rw-r--r--src/kernel/task/idt.h1
-rw-r--r--src/kernel/task/idt_.asm6
-rw-r--r--src/kernel/task/syscall.c2
-rw-r--r--src/kernel/task/task.c24
-rw-r--r--src/kernel/task/task.h3
12 files changed, 84 insertions, 23 deletions
diff --git a/src/kernel/ipc/request.c b/src/kernel/ipc/request.c
index 9e42d6a..e59a66c 100644
--- a/src/kernel/ipc/request.c
+++ b/src/kernel/ipc/request.c
@@ -47,7 +47,7 @@ int request_has(int id) {
return 2;
}
-void request_answer(int id, uint32_t answer, uint32_t answer2) {
+void request_answer(int id, uint32_t answer, uint32_t answer2, int errcode) {
int i;
//check if we own the object, if not return (also return if descriptor does not exist)
struct object *obj = objdesc_read(current_thread->process, id);
@@ -64,22 +64,27 @@ void request_answer(int id, uint32_t answer, uint32_t answer2) {
obj->request->acknowledged = RS_FINISHED;
switch (obj->request->func >> 30) {
case PT_OBJDESC:
- if (obj->owner == obj->request->requester->process) {
+ if ((int)answer <= 0) {
obj->request->answer.n = answer;
} else {
- int n = objdesc_get(obj->request->requester->process, objdesc_read(obj->owner, answer));
- if (n == -1) {
- n = objdesc_add(obj->request->requester->process, objdesc_read(obj->owner, answer));
+ if (obj->owner == obj->request->requester->process) {
+ obj->request->answer.n = answer;
+ } else {
+ int n = objdesc_get(obj->request->requester->process, objdesc_read(obj->owner, answer));
+ if (n == -1) {
+ n = objdesc_add(obj->request->requester->process, objdesc_read(obj->owner, answer));
+ }
+ obj->request->answer.n = n;
}
- obj->request->answer.n = n;
}
break;
case PT_LONG:
obj->request->answer.n = answer;
break;
case PT_LONGLONG:
- obj->request->answer.ll = (uint64_t)((uint64_t)answer << 32) | answer2;
+ obj->request->answer.ll = (uint64_t)((uint64_t)answer2 << 32) | answer;
}
+ obj->request->errcode = errcode;
//wake up receiver thread (thread_wakeUp)
thread_wakeUp(obj->request->requester);
//dereference request from object, unlock objects busymutex
@@ -150,15 +155,19 @@ static struct request *mkrequest(int id, struct thread *requester,
uint32_t v = (i == 0 ? a : (i == 1 ? b : c));
switch (n) {
case PT_OBJDESC:
- if (obj->owner == current_thread->process) {
+ if ((int)v <= 0) {
rq->params[i] = v;
} else {
- int d = objdesc_get(obj->owner, objdesc_read(current_thread->process, v));
- if (d == -1) {
- d = objdesc_add(obj->owner, objdesc_read(current_thread->process, v));
- rq->obj_close[i] = d;
+ if (obj->owner == current_thread->process) {
+ rq->params[i] = v;
+ } else {
+ int d = objdesc_get(obj->owner, objdesc_read(current_thread->process, v));
+ if (d == -1) {
+ d = objdesc_add(obj->owner, objdesc_read(current_thread->process, v));
+ rq->obj_close[i] = d;
+ }
+ rq->params[i] = d;
}
- rq->params[i] = d;
}
break;
case PT_LONG:
@@ -201,6 +210,7 @@ int request(int obj, uint32_t rq_ptr) {
case PT_LONGLONG:
urq->answerll = rq->answer.ll;
}
+ urq->errcode = rq->errcode;
kfree(rq);
return 0;
}
diff --git a/src/kernel/ipc/request.h b/src/kernel/ipc/request.h
index 0b60a5c..0afc48b 100644
--- a/src/kernel/ipc/request.h
+++ b/src/kernel/ipc/request.h
@@ -24,6 +24,7 @@ struct request {
int64_t ll;
uint32_t n;
} answer;
+ int errcode; //returned when function has finished
};
struct user_request {
@@ -35,12 +36,13 @@ struct user_sendrequest {
uint32_t func, a, b, c;
uint32_t answeri;
int64_t answerll;
+ int errcode;
};
//syscalls
int request_get(int obj, uint32_t ptr, int wait);
int request_has(int obj);
-void request_answer(int obj, uint32_t answer, uint32_t answer2); //answer2 used for long long.
+void request_answer(int obj, uint32_t answer, uint32_t answer2, int errcode); //answer2 used for long long.
int request_mapShm(int obj, uint32_t pos, int number);
int request(int obj, uint32_t rq_ptr);
diff --git a/src/kernel/linker/elf.c b/src/kernel/linker/elf.c
index bbf4906..6ad5d34 100644
--- a/src/kernel/linker/elf.c
+++ b/src/kernel/linker/elf.c
@@ -16,6 +16,8 @@ thread_entry elf_load(uint8_t *data, struct process* process) {
int i;
if (elf_check(data)) return 0;
+ struct page_directory *r = current_pagedir;
+ cli();
pagedir_switch(process->pagedir);
phdr = (struct elf_phdr*)((uint8_t*)(data + ehdr->e_phoff));
@@ -28,6 +30,10 @@ thread_entry elf_load(uint8_t *data, struct process* process) {
}
}
}
+
+ pagedir_switch(r);
+ sti();
+
return (thread_entry)ehdr->e_entry;
}
diff --git a/src/kernel/mem/paging.c b/src/kernel/mem/paging.c
index 8996162..9972b2a 100644
--- a/src/kernel/mem/paging.c
+++ b/src/kernel/mem/paging.c
@@ -22,7 +22,6 @@ void frame_free(uint32_t id) {
bitset_clear(&frames, id);
}
-
void paging_init(size_t totalRam) {
uint32_t i;
diff --git a/src/kernel/mem/paging.h b/src/kernel/mem/paging.h
index cb76cd6..ec10560 100644
--- a/src/kernel/mem/paging.h
+++ b/src/kernel/mem/paging.h
@@ -26,7 +26,7 @@ struct page_directory {
struct segment_map *mappedSegs;
};
-extern struct page_directory *kernel_pagedir;
+extern struct page_directory *kernel_pagedir, *current_pagedir;
uint32_t frame_alloc();
void frame_free(uint32_t id);
diff --git a/src/kernel/mem/seg.c b/src/kernel/mem/seg.c
index aa71564..ffaa84c 100644
--- a/src/kernel/mem/seg.c
+++ b/src/kernel/mem/seg.c
@@ -71,3 +71,24 @@ int simpleseg_handleFault(struct segment_map* sm, size_t addr, int write) {
void simpleseg_delete(struct segment* seg) {
}
+
+int simpleseg_resize(struct segment_map *map, size_t len) {
+ size_t i;
+
+ if (map == 0) return -1;
+ if (map->seg->delete != simpleseg_delete) return -2;
+
+ struct simpleseg *s = (struct simpleseg*)map->seg->seg_data;
+ if (len & 0xFFF) len = (len & 0xFFFFF000) + 0x1000;
+ if (len < map->len) {
+ for (i = map->start + len; i < map->start + map->len; i += 0x1000) {
+ page_unmapFree(pagedir_getPage(map->pagedir, i, 0));
+ }
+ map->len = len;
+ s->len = len;
+ } else if (len > map->len) {
+ map->len = len;
+ s->len = len;
+ }
+ return 0;
+}
diff --git a/src/kernel/mem/seg.h b/src/kernel/mem/seg.h
index 4d6660f..26664dc 100644
--- a/src/kernel/mem/seg.h
+++ b/src/kernel/mem/seg.h
@@ -37,5 +37,6 @@ struct segment_map* simpleseg_map(struct segment* seg, struct page_directory* pa
void simpleseg_unmap(struct segment_map*);
void simpleseg_delete(struct segment *seg);
int simpleseg_handleFault(struct segment_map* map, size_t addr, int write);
+int simpleseg_resize(struct segment_map *map, size_t len);
#endif
diff --git a/src/kernel/task/idt.h b/src/kernel/task/idt.h
index ed37eb0..b12d6c5 100644
--- a/src/kernel/task/idt.h
+++ b/src/kernel/task/idt.h
@@ -17,7 +17,6 @@ struct idt_ptr {
} __attribute__((packed));
struct registers {
- uint32_t cr3; //page directory physical address
uint32_t ds; // Data segment selector
uint32_t edi, esi, ebp, esp, ebx, edx, ecx, eax; // Pushed by pusha.
uint32_t int_no, err_code; // Interrupt number and error code (if applicable)
diff --git a/src/kernel/task/idt_.asm b/src/kernel/task/idt_.asm
index 1a594ca..95878c0 100644
--- a/src/kernel/task/idt_.asm
+++ b/src/kernel/task/idt_.asm
@@ -47,14 +47,8 @@ idt_flush:
mov fs, ax
mov gs, ax
- mov eax, cr3
- push eax
-
call idt_%1Handler
- pop eax
- mov cr3, eax
-
pop eax ; reload the original data segment descriptor
mov ds, ax
mov es, ax
diff --git a/src/kernel/task/syscall.c b/src/kernel/task/syscall.c
index dd909e0..9a1ce81 100644
--- a/src/kernel/task/syscall.c
+++ b/src/kernel/task/syscall.c
@@ -31,6 +31,7 @@ CALL3V(request_answer, request_answer_sc);
CALL3(request_mapShm, request_mapShm_sc);
CALL2(request, request_sc);
CALL2(send_msg, send_msg_sc);
+CALL2(process_setheapseg, proc_setheap_sc);
static void thread_new_sc(struct registers* r) {
thread_new(current_thread->process, (thread_entry)r->ebx, (void*)r->ecx);
@@ -56,4 +57,5 @@ int_callback syscalls[] = {
request_mapShm_sc,
request_sc,
send_msg_sc,
+ proc_setheap_sc,
0 };
diff --git a/src/kernel/task/task.c b/src/kernel/task/task.c
index dec7565..9221813 100644
--- a/src/kernel/task/task.c
+++ b/src/kernel/task/task.c
@@ -77,6 +77,7 @@ void tasking_switch() {
}
current_thread = thread_next();
+ pagedir_switch(current_thread->process->pagedir);
gdt_setKernelStack(((uint32_t)current_thread->kernelStack_addr) + current_thread->kernelStack_size);
@@ -278,6 +279,7 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi
p->pagedir = pagedir_new();
p->next = processes;
p->stacksBottom = 0xDF000000;
+ p->heapseg = 0;
p->next_objdesc = 0;
p->objects = 0;
@@ -289,6 +291,7 @@ struct process *process_new(struct process* parent, uint32_t uid, uint32_t privi
static void thread_delete(struct thread *th) {
kfree(th->kernelStack_addr);
+ if (th->userStack_seg != 0) seg_unmap(th->userStack_seg);
th->process->threads--;
if (threads == th) {
threads = th->next;
@@ -319,3 +322,24 @@ static void process_delete(struct process *pr) {
}
kfree(pr);
}
+
+int process_setheapseg(size_t start, size_t end) { //syscall
+ struct process *p = current_thread->process;
+ if (start >= 0xE0000000 || end >= 0xE0000000) return -1;
+ if (p->heapseg == 0) {
+ struct segment *s = simpleseg_make(start, end - start, 1);
+ if (s == 0) return -5;
+ p->heapseg = seg_map(s, p->pagedir, 0);
+ if (p->heapseg == 0) return -1;
+ return 0;
+ } else if (p->heapseg->start != start) {
+ seg_unmap(p->heapseg);
+ struct segment *s = simpleseg_make(start, end - start, 1);
+ if (s == 0) return -5;
+ p->heapseg = seg_map(s, p->pagedir, 0);
+ if (p->heapseg == 0) return -1;
+ return 0;
+ } else {
+ return simpleseg_resize(p->heapseg, end - start);
+ }
+}
diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h
index 1c22785..3dad63d 100644
--- a/src/kernel/task/task.h
+++ b/src/kernel/task/task.h
@@ -32,6 +32,8 @@ struct process {
struct obj_descriptor *objects;
uint32_t next_objdesc;
+ struct segment_map *heapseg;
+
struct process *next; //Forms a linked list
};
@@ -62,5 +64,6 @@ void thread_exit();
void process_exit(uint32_t retval);
struct thread * thread_new(struct process *proc, thread_entry entry_point, void *data);
struct process* process_new(struct process *parent, uint32_t uid, uint32_t privilege);
+int process_setheapseg(size_t start, size_t end); //syscall
#endif