diff options
Diffstat (limited to 'src/kernel/task')
-rw-r--r-- | src/kernel/task/task.cpp | 67 | ||||
-rw-r--r-- | src/kernel/task/task.h | 3 |
2 files changed, 52 insertions, 18 deletions
diff --git a/src/kernel/task/task.cpp b/src/kernel/task/task.cpp index e513608..1a5d535 100644 --- a/src/kernel/task/task.cpp +++ b/src/kernel/task/task.cpp @@ -340,37 +340,36 @@ static void process_delete(process *pr) { kfree(pr); } -size_t process_sbrk(size_t size) { - process *p = current_process; - if (p->data == 0) return -1; - ASSERT(p->data < K_HIGHHALF_ADDR); - if (p->data + size >= K_HIGHHALF_ADDR) return -1; +size_t process::sbrk(size_t size) { + if (data == 0) return -1; + ASSERT(data < K_HIGHHALF_ADDR); + if (data + size >= K_HIGHHALF_ADDR) return -1; size_t ret; - if (p->dataseg == 0) { - size_t start = p->data; + if (dataseg == 0) { + size_t start = data; if (start & 0x0FFF) start = (start & 0xFFFFF000) + 0x1000; size_t end = start + size; if (end & 0x0FFF) end = (end & 0xFFFFF000) + 0x1000; segment *s = new simpleseg(start, end - start, 1); if (s == 0) return -5; - p->dataseg = s->map(p->pagedir, 0); - if (p->dataseg == 0) return -1; + dataseg = s->map(pagedir, 0); + if (dataseg == 0) return -1; ret = start; - p->data = start + size; + data = start + size; } else { - size_t start = p->dataseg->start; - size_t end = p->data + size; + size_t start = dataseg->start; + size_t end = data + size; if (end <= start) return -1; if (end & 0x0FFF) end = (end & 0xFFFFF000) + 0x1000; - simpleseg *s = (simpleseg*)(p->dataseg->seg); - s->resize(p->dataseg, end - start); + simpleseg *s = (simpleseg*)(dataseg->seg); + s->resize(dataseg, end - start); - ret = p->data; - p->data += size; + ret = data; + data += size; } /* (DBG) ke_vt->writeStr("(sbrk "); ke_vt->writeHex(size); @@ -380,8 +379,40 @@ size_t process_sbrk(size_t size) { return ret; } +void* process::set_args(char** args) { + if (args == 0) return 0; + + cli(); // we're writing to this process's user space + page_directory *r = current_pagedir; + pagedir_switch(pagedir); + + int len = sizeof(char*), argc = 0; + for (char** a = args; *a != 0; a++) { + len += strlen(*a) + 1 + sizeof(char*); + argc++; + } + + void* p = (void*)sbrk(len); + char** si = (char**)p; + char* s = (char*)p + ((argc + 1) * sizeof(char*)); + for (int i = 0; i < argc; i++) { + si[i] = s; + strcpy(s, args[i]); + s += strlen(args[i]) + 1; + } + si[argc] = 0; + + pagedir_switch(r); + sti(); + + return p; +} + +// syscalls +size_t process_sbrk(size_t size) { + return current_process->sbrk(size); +} void process_brk(size_t ptr) { ASSERT(ptr < K_HIGHHALF_ADDR); - process_sbrk(ptr - current_process->data); + current_process->sbrk(ptr - current_process->data); } - diff --git a/src/kernel/task/task.h b/src/kernel/task/task.h index 1c32657..99738b9 100644 --- a/src/kernel/task/task.h +++ b/src/kernel/task/task.h @@ -41,6 +41,9 @@ class process { process() : fd(4, 4) {} // must not be used directly process(process *parent, uint32_t uid, uint32_t privilege); + + void* set_args(char** args); + size_t sbrk(size_t size); }; class thread { |