void setupMappings() { // The CoreServer does not need to setup mappings if (getpid() == CORESRV_PID) return; // Fill the mounts table memset(mounts, 0, sizeof(FileSystemMount) * FILESYSTEM_MAXMOUNTS); strlcpy(mounts[0].path, "/dev", PATHLEN); strlcpy(mounts[1].path, "/", PATHLEN); mounts[0].procID = DEVSRV_PID; mounts[0].options = ZERO; mounts[1].procID = ROOTSRV_PID; mounts[1].options = ZERO; // Set currentDirectory currentDirectory = "/"; // Load FileDescriptors. for (Size i = 0; i < FILE_DESCRIPTOR_MAX; i++) { FileDescriptor fd; fd.open = false; files.insert(fd); } #warning Solve this, by passing the file descriptor, procinfo, etc as a parameter to entry(), constructed by the kernel #warning If there was a parent, it would have passed the file descriptor table, argc/argv, memorymap, etc as an argument to ProcessCtl() // TODO: perhaps we can "bundle" the GetMounts() and ReadProcess() calls, so that // we do not need to send IPC message twice in this part (for mounts and getppid()) // TODO: this is inefficient. It should take only one IPC request to retrieve these things from our parent. Or better, avoid it. // Get our parent ID ProcessID ppid = getppid(); // Skip processes with no parent (e.g. from the BootImage) if (!ppid) return; // Inherit file descriptors, current directory, and more. CoreMessage msg; msg.type = IPCType; msg.from = SELF; // NOTE: we "abuse" the CoreMessage for ipc with our parent... IPCMessage(ppid, API::Receive, &msg, sizeof(msg)); // Copy the file descriptors VMCopy(ppid, API::Read, (Address) files.vector(), (Address) msg.path, files.size() * sizeof(FileDescriptor)); // Dummy reply, to tell our parent we received the fds.... very inefficient. IPCMessage(ppid, API::Send, &msg, sizeof(msg)); }
void setupMappings() { // The CoreServer does not need to setup mappings if (getpid() == CORESRV_PID) return; // Ask CoreServer for FileSystemMounts table CoreMessage msg; msg.action = GetMounts; msg.mounts = mounts; msg.type = IPCType; msg.from = SELF; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); // Set currentDirectory currentDirectory = "/"; // Load FileDescriptors. for (Size i = 0; i < FILE_DESCRIPTOR_MAX; i++) { FileDescriptor fd; fd.open = false; files.insert(fd); } // TODO: perhaps we can "bundle" the GetMounts() and ReadProcess() calls, so that // we do not need to send IPC message twice in this part (for mounts and getppid()) // TODO: this is inefficient. It should take only one IPC request to retrieve these things from our parent. Or better, avoid it. // Get our parent ID ProcessID ppid = getppid(); // Skip processes with no parent (e.g. from the BootImage) if (!ppid) return; // Inherit file descriptors, current directory, and more. // NOTE: we "abuse" the CoreMessage for ipc with our parent... IPCMessage(ppid, API::Receive, &msg, sizeof(msg)); // Copy the file descriptors VMCopy(ppid, API::Read, (Address) files.vector(), (Address) msg.path, files.size() * sizeof(FileDescriptor)); // Dummy reply, to tell our parent we received the fds.... very inefficient. IPCMessage(ppid, API::Send, &msg, sizeof(msg)); }
int stat(const char *path, struct stat *buf) { FileSystemMessage msg; FileStat st; ProcessID mnt = findMount(path); /* Fill message. */ msg.action = StatFile; msg.path = (char *) path; msg.stat = &st; msg.type = IPCType; /* Ask the FileSystem for the information. */ if (mnt) { IPCMessage(mnt, API::SendReceive, &msg, sizeof(msg)); /* Copy information into buf. */ if (msg.result == ESUCCESS) { buf->fromFileStat(&st); } /* Set errno. */ errno = msg.result; } else errno = ENOENT; /* Success. */ return msg.result == ESUCCESS ? 0 : -1; }
int main(int argc, char **argv) { SystemInformation info; CoreMessage msg; Timer::Info timer; msg.action = GetCoreCount; msg.type = IPCType; msg.from = SELF; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); ProcessCtl(SELF, InfoTimer, (Address) &timer); printf("Memory Total: %u KB\r\n" "Memory Available: %u KB\r\n" "Processor Cores: %u\r\n" "Timer: %l ticks (%u hertz)\r\n" "Uptime: %u.%us\r\n", info.memorySize / 1024, info.memoryAvail / 1024, msg.coreCount, (u32)timer.ticks, timer.frequency, timer.frequency ? (u32)timer.ticks / timer.frequency : 0, timer.frequency ? (u32)timer.ticks % timer.frequency : 0); return EXIT_SUCCESS; }
int touch(const char *path, mode_t mode) /* Creamos touch */ { FileSystemMessage msg; ProcessID mnt = findMount(path); /* ¿Como es el archivo?. */ msg.action = CreateFile; /* ¿Que hacemos con el archivo? */ msg.buffer = (char *) path; msg.mode = mode; msg.filetype = RegularFile; /* Tipo de archivo : txt, directorio, etc */ /* Le preguntamos al OS si permite crearlo. */ if (mnt) { IPCMessage(mnt, SendReceive, &msg, sizeof(msg)); /* ¿Error?. */ errno = msg.result; } else errno = ENOENT; /* Finalizando..... */ return msg.result == ESUCCESS ? 0 : -1; }
Error VGA::initialize() { CoreMessage mem; /* Request VGA memory. */ mem.action = CreatePrivate; mem.size = PAGESIZE; mem.virt = ZERO; mem.phys = VGA_PADDR; mem.access = Memory::Present | Memory::User | Memory::Readable | Memory::Writable | Memory::Pinned; mem.type = IPCType; IPCMessage(CORESRV_PID, API::SendReceive, &mem, sizeof(mem)); /* Point to the VGA mapping. */ vga = (u16 *) mem.virt; /* Clear screen. */ for (uint i = 0; i < width * height; i++) { vga[i] = VGA_CHAR(' ', LIGHTGREY, BLACK); } /* Disable hardware cursor. */ WriteByte(VGA_IOADDR, 0x0a); WriteByte(VGA_IODATA, 1 << 5); /* Successfull. */ return ESUCCESS; }
Address PageAllocator::allocate(Size *size) { CoreMessage msg; Address ret = start + allocated; // TODO: #warning TODO: perhaps align to page size??? Size bytes = *size > PAGEALLOC_MINIMUM ? *size : PAGEALLOC_MINIMUM; // Fill in the message. */ msg.action = CreatePrivate; msg.size = bytes; msg.access = VirtualMemory::Present | VirtualMemory::User | VirtualMemory::Readable | VirtualMemory::Writable | VirtualMemory::Reserved; msg.virt = USER_HEAP + allocated; msg.phys = ZERO; msg.type = IPCType; msg.from = SELF; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); // Update count allocated += msg.size; // Success *size = msg.size; return ret; }
int forkexec(const char *path, const char *argv[]) { ProcessMessage msg; char *arguments = new char[PAGESIZE]; uint count = 0; /* Fill in arguments. */ while (argv[count] && count < PAGESIZE / ARGV_SIZE) { strlcpy(arguments + (ARGV_SIZE * count), argv[count], ARGV_SIZE); count++; } /* We want to spawn a new process. */ msg.action = SpawnProcess; msg.path = (char *) path; msg.arguments = arguments; msg.number = count; /* Ask process server. */ IPCMessage(PROCSRV_PID, SendReceive, &msg, sizeof(msg)); /* Set errno. */ errno = msg.result; /* Cleanup. */ delete arguments; /* All done. */ return errno == ESUCCESS ? (int) msg.number : -1; }
void ProcessServer::exitProcessHandler(ProcessMessage *msg) { ProcessMessage reply; /* Clear process entry. */ memset(procs[msg->from], 0, sizeof(UserProcess)); // TODO: close files here!!! /* Ask kernel to terminate the process. */ ProcessCtl(msg->from, KillPID); /* Awake any processes waiting for this process' death. */ for (Size i = 0; i < MAX_PROCS; i++) { if (procs[i]->command[0] && procs[i]->waitProcessID == msg->from) { /* Clear wait status. */ procs[i]->waitProcessID = ANY; /* Send exit status. */ reply.action = WaitProcess; reply.number = msg->number; reply.result = ESUCCESS; IPCMessage(i, Send, &reply, sizeof(reply)); } } }
int mkdir(const char *path, mode_t mode) { FileSystemMessage msg; ProcessID mnt = findMount(path); /* Fill message. */ msg.action = CreateFile; msg.buffer = (char *) path; msg.mode = mode; msg.filetype = DirectoryFile; /* Ask the FileSystem to create it. */ if (mnt) { IPCMessage(mnt, SendReceive, &msg, sizeof(msg)); /* Set errno. */ errno = msg.result; } else errno = ENOENT; /* Success. */ return msg.result == ESUCCESS ? 0 : -1; }
void ProcFileSystem::refresh() { CoreMessage msg; ProcessInfo info; String slash("/"); Directory *procDir; // TODO: memory leak! Cleanup the whole cache first... (currently broken) // clearFileCache(); rootDir->clear(); /* Update root. */ rootDir->insert(DirectoryFile, "."); rootDir->insert(DirectoryFile, ".."); /* Reinsert into the cache. */ insertFileCache(rootDir, "."); insertFileCache(rootDir, ".."); // Refresh UserProcess table msg.action = ReadProcess; msg.buffer = procs; msg.number = ZERO; msg.type = IPCType; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); // Insert processes pseudo files for (int i = 0; i < MAX_PROCS; i++) { // Skip unused PIDs if (!procs[i].command[0]) continue; // Per-process directory procDir = new Directory; procDir->insert(DirectoryFile, "."); procDir->insert(DirectoryFile, ".."); procDir->insert(RegularFile, "cmdline"); procDir->insert(RegularFile, "status"); rootDir->insert(DirectoryFile, "%u", i); // Insert into the cache insertFileCache(procDir, "%u", i); insertFileCache(procDir, "%u/.", i); insertFileCache(rootDir, "%u/..", i); // Set commandline insertFileCache(new PseudoFile("%s", procs[i].command), "%u/cmdline", i); // Request kernel's process information ProcessCtl(i, InfoPID, (Address) &info); // Process status insertFileCache(new PseudoFile("%s", states[info.state]), "%u/status", i); } }
int MPI_Comm_size(MPI_Comm comm, int *size) { CoreMessage msg; msg.action = GetCoreCount; msg.from = SELF; msg.type = IPCType; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); *size = msg.coreCount; return MPI_SUCCESS; }
void ProcessServer::waitProcessHandler(ProcessMessage *msg) { if (msg->number < MAX_PROCS && msg->number != ANY && procs[msg->number]->command[0]) { procs[msg->from]->waitProcessID = msg->number; } else { msg->result = EINVAL; IPCMessage(msg->from, Send, msg, sizeof(*msg)); } }
int main(int argc, char **argv) { SystemInformation info; CoreMessage msg; msg.action = GetCoreCount; msg.type = IPCType; msg.from = SELF; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); printf("Memory Total: %u KB\r\n" "Memory Available: %u KB\r\n" "Processor Cores: %u\r\n", info.memorySize / 1024, info.memoryAvail / 1024, msg.coreCount); return EXIT_SUCCESS; }
int main(int argc, char **argv) { CoreMessage msg; ProcessInfo info; // Receive UserProcess table from the CoreServer msg.action = ReadProcess; msg.buffer = procs; msg.number = ZERO; IPCMessage(CORESRV_PID, API::SendReceive, &msg, sizeof(msg)); // Check the result if (msg.result != 0) { printf("%s: failed to receive process table: %s\n", argv[0], strerror(msg.result)); return EXIT_FAILURE; } // Print header printf("ID PARENT USER GROUP STATUS CMD\r\n"); // Loop processes for (int i = 0; i < MAX_PROCS; i++) { // Skip unused PIDs if (!procs[i].command[0]) continue; // Request kernel's process information ProcessCtl(i, InfoPID, (Address) &info); // Output a line printf("%3d %7d %4d %5d %10s %32s\r\n", i, procs[i].parent, procs[i].userID, procs[i].groupID, states[info.state], procs[i].command); } return EXIT_SUCCESS; }
int open(const char *path, int oflag, ...) { FileSystemMessage msg; ProcessID mnt = findMount(path); /* Fill message. */ msg.action = OpenFile; msg.buffer = (char *) path; /* Ask the FileSystem. */ if (mnt) { IPCMessage(mnt, SendReceive, &msg, sizeof(msg)); /* Set errno. */ errno = msg.result; } else errno = ENOENT; /* Success. */ return msg.result == ESUCCESS ? msg.fd : -1; }
pid_t waitpid(pid_t pid, int *stat_loc, int options) { ProcessMessage msg; /* Fill in the message. */ msg.action = WaitProcess; msg.number = pid; /* Ask ProcessServer. */ IPCMessage(PROCSRV_PID, SendReceive, &msg, sizeof(msg)); /* Did we succeed? */ if (msg.result == ESUCCESS) { if (stat_loc) { *stat_loc = msg.number; } return pid; } else return msg.result; }
ssize_t read(int fildes, void *buf, size_t nbyte) { FileSystemMessage msg; ProcessID mnt = findMount(fildes); /* Read the file. */ if (mnt) { msg.action = ReadFile; msg.fd = fildes; msg.buffer = (char *) buf; msg.size = nbyte; msg.offset = ZERO; IPCMessage(mnt, SendReceive, &msg, sizeof(msg)); /* Set error number. */ errno = msg.result; } else errno = ENOENT; /* Success. */ return errno >= 0 ? errno : (ssize_t) -1; }
int forkexec(const char *path, const char *argv[]) { CoreMessage msg; ExecutableFormat *fmt; MemoryRegion regions[16]; Memory::Range range; uint count = 0; pid_t pid = 0; int numRegions = 0; Vector<FileDescriptor> *fds = getFiles(); // Attempt to read executable format if (!(fmt = ExecutableFormat::find(path))) return -1; // Retrieve memory regions if ((numRegions = fmt->regions(regions, 16)) < 0) return -1; // Create new process pid = ProcessCtl(ANY, Spawn, fmt->entry()); // TODO: check the result of ProcessCtl() // TODO: make this much more efficient. perhaps let libexec write directly to the target buffer. // at least Map & copy in one shot. // TODO: move the memory administration updates to coreserver instead. // this process can read the libexec data once, and then let coreserver create a process for it. // Map program regions into virtual memory of the new process for (int i = 0; i < numRegions; i++) { // Copy executable memory from this region range.virt = regions[i].virtualAddress; range.phys = ZERO; range.size = regions[i].size; range.access = Memory::Present | Memory::User | Memory::Readable | Memory::Writable | Memory::Executable; // Create mapping first if (VMCtl(pid, Map, &range) != 0) { // TODO: convert from API::Error to errno. errno = EFAULT; return -1; } // Copy bytes VMCopy(pid, API::Write, (Address) regions[i].data, regions[i].virtualAddress, regions[i].size); } /* Create mapping for command-line arguments. */ range.virt = ARGV_ADDR; range.phys = ZERO; range.size = PAGESIZE; VMCtl(pid, Map, &range); // Allocate arguments char *arguments = new char[PAGESIZE]; memset(arguments, 0, PAGESIZE); // Fill in arguments while (argv[count] && count < PAGESIZE / ARGV_SIZE) { strlcpy(arguments + (ARGV_SIZE * count), argv[count], ARGV_SIZE); count++; } // Copy argc/argv into the new process if ((VMCopy(pid, API::Write, (Address) arguments, (Address) ARGV_ADDR, PAGESIZE)) < 0) { delete arguments; errno = EFAULT; return -1; } // Let the Child begin execution ProcessCtl(pid, Resume); // Send a pointer to our list of file descriptors to the child // TODO: ofcourse, insecure. To be fixed later. msg.type = IPCType; msg.from = SELF; msg.path = (char *) fds->vector(); IPCMessage(pid, API::SendReceive, &msg, sizeof(msg)); // Done. Cleanup. delete arguments; return pid; }
Error FileSystem::processRequest(FileSystemRequest *req) { char buf[PATHLEN]; FileSystemPath path; FileCache *cache = ZERO; File *file = ZERO; Directory *parent; FileSystemMessage *msg = req->getMessage(); // Copy the file path if ((msg->result = VMCopy(msg->from, API::Read, (Address) buf, (Address) msg->path, PATHLEN)) <= 0) { msg->result = EACCES; msg->type = IPCType; IPCMessage(msg->from, API::Send, msg, sizeof(*msg)); return msg->result; } path.parse(buf + strlen(m_mountPath)); // Do we have this file cached? if ((cache = findFileCache(&path)) || (cache = lookupFile(&path))) { file = cache->file; } // File not found else if (msg->action != CreateFile) { msg->result = ENOENT; msg->type = IPCType; IPCMessage(msg->from, API::Send, msg, sizeof(*msg)); return msg->result; } // Perform I/O on the file switch (msg->action) { case CreateFile: if (cache) msg->result = EEXIST; else { /* Attempt to create the new file. */ if ((file = createFile(msg->filetype, msg->deviceID))) { const char *p = **path.full(); insertFileCache(file, "%s", p); /* Add directory entry to our parent. */ if (path.parent()) { parent = (Directory *) findFileCache(**path.parent())->file; } else parent = (Directory *) m_root->file; parent->insert(file->getType(), **path.full()); msg->result = ESUCCESS; } else msg->result = EIO; } break; case DeleteFile: if (cache->entries.count() == 0) { clearFileCache(cache); msg->result = ESUCCESS; } else msg->result = ENOTEMPTY; break; case StatFile: msg->result = file->status(msg); break; case ReadFile: { msg->result = file->read(req->getBuffer(), msg->size, msg->offset); if (req->getBuffer().getCount()) req->getBuffer().flush(); } break; case WriteFile: { if (!req->getBuffer().getCount()) req->getBuffer().bufferedRead(); msg->result = file->write(req->getBuffer(), msg->size, msg->offset); } break; } // Only send reply if completed (not EAGAIN) if (msg->result != EAGAIN) { msg->type = IPCType; IPCMessage(msg->from, API::Send, msg, sizeof(*msg)); } return msg->result; }
namespace Pave_Libraries_Common { // State Estimation Update IPCMessage& Messages::StateEstimation = IPCMessage( "State Estimation", //"{double, double, double, double, double, double, double, double}", "{double, double, double, double}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::PauseDisable = IPCMessage( "PauseDisable", "{boolean, boolean}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::CostMap = IPCMessage( "CostMap", "{double, double, double, double, double, double, int, <double: 7>, <double: 7>, <double: 7>}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::BumblebeeUpdate = IPCMessage( "BumblebeeUpdate", "{int, <double: 1>, <double: 1>, <double: 1>, int, int, <int: 6>, <float: 6>, <float: 5>, <float: 5>, {double, double, double, double, double, double, double, double}}", IPC_VARIABLE_LENGTH, true, true ); /* IPCMessage& Messages::SplineIPC=IPCMessage( "SplineIPCUpdate", "{int, <int:1>,<int:1>}", IPC_VARIABLE_LENGTH, true, true };*/ /* IPCMessage& Messages::VisionUpdate = IPCMessage( "VisionUpdate", // "{int, <double: 1>, <double: 1>, <double: 1>, int, int, <int: 6>, <float: 6>, <float: 5>, <float: 5>, {double, double, double, double, double, double, double, double}}", // "{int, <double: 1>, <double: 1>, <double: 1>, int, int, <float: 5>, <float: 6>, <float: 6>, {double, double, double, double, double, double, double, double}}", "{int, <double: 1>, <double: 1>, <double: 1>, int, <{int, <float: 1>, <float: 1>}: 5}, {double, double, double, double, double, double, double, double}}", IPC_VARIABLE_LENGTH, true, true ); */ IPCMessage& Messages::VisionUpdate=IPCMessage( "VisionUpdate", "{int,<double:1>,<double:1>,<double:1>,int,<{int,<float:1>,<float:1>}:5>,{double, double, double, double, double, double, double, double}}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::PathUpdate = IPCMessage( "Path", "list_point3d", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::MaxSpeedUpdate = IPCMessage( "MaxSpeed", "double", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::SetWaypoints = IPCMessage( "SetWaypoints", "list_point2d", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::SetWheelSpeed = IPCMessage( "SetWheelSpeed", "{double, double}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::GetWheelSpeed = IPCMessage( "GetWheelSpeed", "{double, double}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::SetLight = IPCMessage( "SetLight", "{boolean}", 4, false, true ); // IPCMessage& Messages::SetEstop = IPCMessage( //"SetEstop", //"{boolean}", //4, //false, //true //); IPCMessage& Messages::GetEstop = IPCMessage( "GetEstop", "{boolean}", 4, false, true ); IPCMessage& Messages::ClearCostMap = IPCMessage( "ClearCostMap", "{boolean}", 4, false, true ); IPCMessage& Messages::HaveClearedCostMap = IPCMessage( "HaveClearedCostMap", "{boolean}", 4, false, true ); IPCMessage& Messages::JausEnabled = IPCMessage( "JausEnabled", "{boolean}", 4, false, true ); IPCMessage& Messages::GPSUpdate = IPCMessage( "GPSUpdate", "{double, double, double, double, boolean}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::RawGPSUpdate = IPCMessage( "RawGPSUpdate", "{double, double, double, double, boolean}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::CompassUpdate = IPCMessage( "CompassUpdate", "{double, double, double}", IPC_VARIABLE_LENGTH, true, true ); IPCMessage& Messages::GyroUpdate = IPCMessage( "GyroUpdate", "{double}", IPC_VARIABLE_LENGTH, true, true ); }