Compare commits
No commits in common. "656667812a5a8e21f5369a62ba0c7a986baa200d" and "755242719c92870f512842f50b8f8c44414248b2" have entirely different histories.
656667812a
...
755242719c
@ -163,30 +163,24 @@ int main()
|
|||||||
}
|
}
|
||||||
if (child == 0)
|
if (child == 0)
|
||||||
{
|
{
|
||||||
sleep(1);
|
sleep(2);
|
||||||
pid_t child = fork();
|
|
||||||
printf("I am the child (PID %ld), my parent is PID %ld!!\n", getpid(), getppid());
|
printf("I am the child (PID %ld), my parent is PID %ld!!\n", getpid(), getppid());
|
||||||
if (child) execv("/bin/sym", NULL);
|
execv("/bin/sym", NULL);
|
||||||
else
|
|
||||||
execv("/bin/init", NULL);
|
|
||||||
perror("execv");
|
perror("execv");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else { printf("Success!! Got PID %ld\n", child); }
|
else { printf("Success!! Got PID %ld\n", child); }
|
||||||
|
|
||||||
int status;
|
int status;
|
||||||
for (;;)
|
pid_t result;
|
||||||
|
while ((result = waitpid(child, &status, 0)) == 0) // Child has not yet exited
|
||||||
{
|
{
|
||||||
pid_t result;
|
msleep(100);
|
||||||
while ((result = wait(&status)) == 0) // No child has exited yet
|
|
||||||
{
|
|
||||||
msleep(100);
|
|
||||||
}
|
|
||||||
if (result < 0)
|
|
||||||
{
|
|
||||||
perror("wait");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if (WIFEXITED(status)) { printf("Child process %ld exited with code %d\n", result, WEXITSTATUS(status)); }
|
|
||||||
}
|
}
|
||||||
|
if (result < 0)
|
||||||
|
{
|
||||||
|
perror("waitpid");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (WIFEXITED(status)) { printf("Child process %ld exited with code %d\n", result, WEXITSTATUS(status)); }
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,8 @@
|
|||||||
namespace Syscall
|
namespace Syscall
|
||||||
{
|
{
|
||||||
void entry(Context* context);
|
void entry(Context* context);
|
||||||
|
|
||||||
|
char* strdup_from_user(const char* user_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sys_exit(Context* context, int status);
|
void sys_exit(Context* context, int status);
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "memory/MemoryManager.h"
|
|
||||||
#include "memory/VMM.h"
|
|
||||||
#include "misc/utils.h"
|
|
||||||
|
|
||||||
char* strdup_from_user(const char* user_string);
|
|
||||||
|
|
||||||
template <typename T, unsigned long S = sizeof(T), typename V> T* user_address_to_typed_pointer(V address)
|
|
||||||
{
|
|
||||||
uint64_t phys = VMM::get_physical((uint64_t)address);
|
|
||||||
if (phys == (uint64_t)-1) return nullptr;
|
|
||||||
return (T*)MemoryManager::get_unaligned_mappings((void*)phys, Utilities::get_blocks_from_size(PAGE_SIZE, S),
|
|
||||||
MAP_READ_WRITE);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, unsigned long S = sizeof(T)> void free_user_typed_pointer(T* ptr)
|
|
||||||
{
|
|
||||||
MemoryManager::release_unaligned_mappings(ptr, Utilities::get_blocks_from_size(PAGE_SIZE, S));
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> T* obtain_user_ref(T* user_ptr)
|
|
||||||
{
|
|
||||||
return user_address_to_typed_pointer<T>(user_ptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T> void release_user_ref(T* ptr)
|
|
||||||
{
|
|
||||||
return free_user_typed_pointer(ptr);
|
|
||||||
}
|
|
@ -33,4 +33,11 @@ void Syscall::entry(Context* context)
|
|||||||
default: context->rax = -ENOSYS; break;
|
default: context->rax = -ENOSYS; break;
|
||||||
}
|
}
|
||||||
VMM::exit_syscall_context();
|
VMM::exit_syscall_context();
|
||||||
|
}
|
||||||
|
|
||||||
|
char* Syscall::strdup_from_user(const char* user_string) // FIXME: This function is a little hacky.
|
||||||
|
{
|
||||||
|
uint64_t phys = VMM::get_physical((uint64_t)user_string);
|
||||||
|
if (phys == (uint64_t)-1) { return nullptr; }
|
||||||
|
return strdup((const char*)phys);
|
||||||
}
|
}
|
@ -1,10 +0,0 @@
|
|||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "std/string.h"
|
|
||||||
|
|
||||||
char* strdup_from_user(
|
|
||||||
const char* user_string) // FIXME: This function is a little hacky. Use the obtain_user_ref and similar functions.
|
|
||||||
{
|
|
||||||
uint64_t phys = VMM::get_physical((uint64_t)user_string);
|
|
||||||
if (phys == (uint64_t)-1) { return nullptr; }
|
|
||||||
return strdup((const char*)phys);
|
|
||||||
}
|
|
@ -10,7 +10,6 @@
|
|||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
@ -58,7 +57,7 @@ void sys_fork(Context* context)
|
|||||||
|
|
||||||
void sys_exec(Context* context, const char* pathname)
|
void sys_exec(Context* context, const char* pathname)
|
||||||
{
|
{
|
||||||
char* kpathname = strdup_from_user(pathname);
|
char* kpathname = Syscall::strdup_from_user(pathname);
|
||||||
if (!kpathname)
|
if (!kpathname)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
#include "errno.h"
|
#include "errno.h"
|
||||||
#include "memory/VMM.h"
|
#include "memory/VMM.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
|
|
||||||
void sys_exit(Context* context, int status)
|
void sys_exit(Context* context, int status)
|
||||||
@ -21,4 +20,24 @@ void sys_sleep(Context* context, uint64_t ms)
|
|||||||
task->task_sleep = ms;
|
task->task_sleep = ms;
|
||||||
task->state = task->Sleeping;
|
task->state = task->Sleeping;
|
||||||
Scheduler::task_yield(context);
|
Scheduler::task_yield(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sys_waitpid(Context* context, long pid, int* wstatus,
|
||||||
|
int) // FIXME: Use the value in options and block if WNOHANG has not been specified.
|
||||||
|
{
|
||||||
|
Task* child = Scheduler::find_by_pid(pid); // FIXME: Wait for any child process if PID is -1.
|
||||||
|
if (!child)
|
||||||
|
{
|
||||||
|
context->rax = -ESRCH;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (child->state != child->Dying) // FIXME: This should block if WNOHANG has not been specified.
|
||||||
|
{
|
||||||
|
context->rax = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint64_t phys = VMM::get_physical((uint64_t)wstatus);
|
||||||
|
if (phys != (uint64_t)-1) { *(int*)phys = (int)(child->exit_status & 0xff); }
|
||||||
|
child->state = child->Exited;
|
||||||
|
context->rax = (long)child->id;
|
||||||
}
|
}
|
@ -8,7 +8,6 @@
|
|||||||
#include "render/TextRenderer.h"
|
#include "render/TextRenderer.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "sys/Syscall.h"
|
#include "sys/Syscall.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "thread/Scheduler.h"
|
#include "thread/Scheduler.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
|
|
||||||
@ -146,7 +145,7 @@ void sys_open(Context* context, const char* filename, int flags)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* kernel_filename = strdup_from_user(filename);
|
char* kernel_filename = Syscall::strdup_from_user(filename);
|
||||||
if (!kernel_filename)
|
if (!kernel_filename)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
@ -226,7 +225,7 @@ void sys_close(Context* context, int fd)
|
|||||||
|
|
||||||
void sys_mkdir(Context* context, const char* filename)
|
void sys_mkdir(Context* context, const char* filename)
|
||||||
{
|
{
|
||||||
char* kfilename = strdup_from_user(filename);
|
char* kfilename = Syscall::strdup_from_user(filename);
|
||||||
if (!kfilename)
|
if (!kfilename)
|
||||||
{
|
{
|
||||||
context->rax = -EFAULT;
|
context->rax = -EFAULT;
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
#include "panic/Panic.h"
|
#include "panic/Panic.h"
|
||||||
#include "std/stdlib.h"
|
#include "std/stdlib.h"
|
||||||
#include "std/string.h"
|
#include "std/string.h"
|
||||||
#include "sys/UserMemory.h"
|
|
||||||
#include "sys/elf/ELFLoader.h"
|
#include "sys/elf/ELFLoader.h"
|
||||||
#include "thread/PIT.h"
|
#include "thread/PIT.h"
|
||||||
#include "thread/Task.h"
|
#include "thread/Task.h"
|
||||||
@ -45,14 +44,6 @@ template <typename Callback> void sched_for_each_task(Callback callback)
|
|||||||
} while (task != base_task);
|
} while (task != base_task);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Callback> void sched_for_each_child(Task* task, Callback callback)
|
|
||||||
{
|
|
||||||
sched_for_each_task([&](Task* child) {
|
|
||||||
if (child->ppid == task->id) { return callback(child); }
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Task* Scheduler::find_by_pid(uint64_t pid)
|
Task* Scheduler::find_by_pid(uint64_t pid)
|
||||||
{
|
{
|
||||||
Task* result = nullptr;
|
Task* result = nullptr;
|
||||||
@ -273,13 +264,6 @@ void Scheduler::task_exit(Context* context, int64_t status)
|
|||||||
else
|
else
|
||||||
sched_current_task->state = sched_current_task->Dying;
|
sched_current_task->state = sched_current_task->Dying;
|
||||||
sched_current_task->exit_status = status;
|
sched_current_task->exit_status = status;
|
||||||
if (sched_current_task->id != 1)
|
|
||||||
{
|
|
||||||
sched_for_each_child(sched_current_task, [](Task* child) {
|
|
||||||
if (child->state != child->Exited) child->ppid = 1;
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
task_yield(context);
|
task_yield(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -438,51 +422,4 @@ void Scheduler::sleep(unsigned long ms)
|
|||||||
Task* Scheduler::current_task()
|
Task* Scheduler::current_task()
|
||||||
{
|
{
|
||||||
return sched_current_task;
|
return sched_current_task;
|
||||||
}
|
|
||||||
|
|
||||||
void sys_waitpid(Context* context, long pid, int* wstatus,
|
|
||||||
int) // FIXME: Use the value in options and block if WNOHANG has not been specified.
|
|
||||||
{
|
|
||||||
Task* child = nullptr;
|
|
||||||
if (pid == -1)
|
|
||||||
{
|
|
||||||
sched_for_each_child(sched_current_task, [&](Task* task) {
|
|
||||||
if (task->state == task->Dying)
|
|
||||||
{
|
|
||||||
child = task;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
});
|
|
||||||
if (!child)
|
|
||||||
{
|
|
||||||
context->rax = 0; // No child has exited, let's return 0.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
child = Scheduler::find_by_pid(pid);
|
|
||||||
if (!child)
|
|
||||||
{
|
|
||||||
context->rax = -ESRCH;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (child->state != child->Dying) // FIXME: This should block if WNOHANG has not been specified.
|
|
||||||
{
|
|
||||||
context->rax = 0;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (wstatus)
|
|
||||||
{
|
|
||||||
int* kwstatus = obtain_user_ref(wstatus);
|
|
||||||
if (kwstatus)
|
|
||||||
{
|
|
||||||
*kwstatus = (int)(child->exit_status & 0xff);
|
|
||||||
release_user_ref(kwstatus);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
child->state = child->Exited;
|
|
||||||
context->rax = (long)child->id;
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user