mirror of
https://github.com/RGBCube/serenity
synced 2025-07-07 16:37:34 +00:00
Lots of hacking:
- Turn Keyboard into a CharacterDevice (85,1) at /dev/keyboard. - Implement MM::unmapRegionsForTask() and MM::unmapRegion() - Save SS correctly on interrupt. - Add a simple Spawn syscall for launching another process. - Move a bunch of IO syscall debug output behind DEBUG_IO. - Have ASSERT do a "cli" immediately when failing. This makes the output look proper every time. - Implement a bunch of syscalls in LibC. - Add a simple shell ("sh"). All it can do now is read a line of text from /dev/keyboard and then try launching the specified executable by calling spawn(). There are definitely bugs in here, but we're moving on forward.
This commit is contained in:
parent
72514c8b97
commit
fe237ee215
29 changed files with 276 additions and 32 deletions
|
@ -10,6 +10,8 @@
|
|||
#include <ELFLoader/ExecSpace.h>
|
||||
#include "MemoryManager.h"
|
||||
|
||||
//#define DEBUG_IO
|
||||
|
||||
Task* current;
|
||||
Task* s_kernelTask;
|
||||
|
||||
|
@ -104,6 +106,14 @@ Task::Region* Task::allocateRegion(size_t size, String&& name)
|
|||
return m_regions.last().ptr();
|
||||
}
|
||||
|
||||
int Task::sys$spawn(const char* path)
|
||||
{
|
||||
auto* child = Task::create(path, m_uid, m_gid);
|
||||
if (child)
|
||||
return child->pid();
|
||||
return -1;
|
||||
}
|
||||
|
||||
Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
||||
{
|
||||
auto parts = path.split('/');
|
||||
|
@ -118,6 +128,7 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
|||
if (!elfData)
|
||||
return nullptr;
|
||||
|
||||
cli();
|
||||
Task* t = new Task(parts.takeLast(), uid, gid);
|
||||
|
||||
ExecSpace space;
|
||||
|
@ -137,9 +148,14 @@ Task* Task::create(const String& path, uid_t uid, gid_t gid)
|
|||
}
|
||||
|
||||
t->m_tss.eip = (dword)space.symbolPtr("_start");
|
||||
if (!t->m_tss.eip) {
|
||||
delete t;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MemoryManager::the().unmapRegionsForTask(*t);
|
||||
MemoryManager::the().mapRegionsForTask(*current);
|
||||
|
||||
// Add this task to head of task list (meaning it's next to run too, ATM.)
|
||||
cli();
|
||||
s_tasks->prepend(t);
|
||||
system.nprocess++;
|
||||
kprintf("Task %u (%s) spawned @ %p\n", t->pid(), t->name().characters(), t->m_tss.eip);
|
||||
|
@ -357,10 +373,12 @@ void Task::taskDidCrash(Task* crashedTask)
|
|||
{
|
||||
// NOTE: This is called from an excepton handler, so interrupts are disabled.
|
||||
crashedTask->setState(Crashing);
|
||||
crashedTask->dumpRegions();
|
||||
// crashedTask->dumpRegions();
|
||||
|
||||
s_tasks->remove(crashedTask);
|
||||
|
||||
MemoryManager::the().unmapRegionsForTask(*crashedTask);
|
||||
|
||||
if (!scheduleNewTask()) {
|
||||
kprintf("Task::taskDidCrash: Failed to schedule a new task :(\n");
|
||||
HANG;
|
||||
|
@ -491,7 +509,16 @@ static bool contextSwitch(Task* t)
|
|||
// Some sanity checking to force a crash earlier.
|
||||
auto csRPL = t->tss().cs & 3;
|
||||
auto ssRPL = t->tss().ss & 3;
|
||||
ASSERT(csRPL == ssRPL);
|
||||
|
||||
if (csRPL != ssRPL) {
|
||||
kprintf("Fuckup! Switching from %s(%u) to %s(%u) has RPL mismatch\n",
|
||||
current->name().characters(), current->pid(),
|
||||
t->name().characters(), t->pid()
|
||||
);
|
||||
kprintf("code: %w:%x\n", t->tss().cs, t->tss().eip);
|
||||
kprintf(" stk: %w:%x\n", t->tss().ss, t->tss().esp);
|
||||
ASSERT(csRPL == ssRPL);
|
||||
}
|
||||
|
||||
if (current) {
|
||||
// If the last task hasn't blocked (still marked as running),
|
||||
|
@ -572,17 +599,24 @@ int Task::sys$seek(int fd, int offset)
|
|||
ssize_t Task::sys$read(int fd, void* outbuf, size_t nread)
|
||||
{
|
||||
Task::checkSanity("Task::sys$read");
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("Task::sys$read: called(%d, %p, %u)\n", fd, outbuf, nread);
|
||||
#endif
|
||||
auto* handle = fileHandleIfExists(fd);
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("Task::sys$read: handle=%p\n", handle);
|
||||
#endif
|
||||
if (!handle) {
|
||||
kprintf("Task::sys$read: handle not found :(\n");
|
||||
return -1;
|
||||
}
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("call read on handle=%p\n", handle);
|
||||
#endif
|
||||
nread = handle->read((byte*)outbuf, nread);
|
||||
kprintf("called read\n");
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("Task::sys$read: nread=%u\n", nread);
|
||||
#endif
|
||||
return nread;
|
||||
}
|
||||
|
||||
|
@ -598,7 +632,9 @@ int Task::sys$close(int fd)
|
|||
int Task::sys$open(const char* path, size_t pathLength)
|
||||
{
|
||||
Task::checkSanity("sys$open");
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("Task::sys$open(): PID=%u, path=%s {%u}\n", m_pid, path, pathLength);
|
||||
#endif
|
||||
auto* handle = current->openFile(String(path, pathLength));
|
||||
if (handle)
|
||||
return handle->fd();
|
||||
|
@ -607,14 +643,15 @@ int Task::sys$open(const char* path, size_t pathLength)
|
|||
|
||||
FileHandle* Task::openFile(String&& path)
|
||||
{
|
||||
kprintf("calling vfs::open with vfs=%p, path='%s'\n", &VirtualFileSystem::the(), path.characters());
|
||||
auto handle = VirtualFileSystem::the().open(move(path));
|
||||
if (!handle) {
|
||||
kprintf("vfs::open() failed\n");
|
||||
return nullptr;
|
||||
}
|
||||
handle->setFD(m_fileHandles.size());
|
||||
#ifdef DEBUG_IO
|
||||
kprintf("vfs::open() worked! handle=%p, fd=%d\n", handle.ptr(), handle->fd());
|
||||
#endif
|
||||
m_fileHandles.append(move(handle)); // FIXME: allow non-move Vector::append
|
||||
return m_fileHandles.last().ptr();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue