📄 kernelmultitasker.c
字号:
// If it's the kernel, we're finished kernelPanic(tmpMsg); else { kernelError(kernel_error, tmpMsg); if (kernelGraphicsAreEnabled()) kernelErrorDialog("Application Exception", tmpMsg); } // If the process was in kernel code, and we are not processing an // interrupt, take ownership of the process' stack memory and do a // stack trace if (!kernelProcessingInterrupt && (deadProcess->taskStateSegment.EIP >= KERNEL_VIRTUAL_ADDRESS)) { kernelMemoryChangeOwner(deadProcess->processId, exceptionProc->processId, 1, deadProcess->userStack, &stackMemory); // If possible, we will do a stack memory dump to disk. Don't try // this if we were servicing an interrupt when we faulted if (stackMemory) { kernelStackTrace((stackMemory + ((void *) deadProcess->taskStateSegment.ESP - deadProcess->userStack)), (stackMemory + deadProcess->userStackSize - sizeof(void *))); // Release the stack memory kernelMemoryRelease(stackMemory); } } // The scheduler may now dismantle the process deadProcess->state = proc_finished; kernelProcessingInterrupt = 0; // Make sure that when we return, we return to the scheduler exceptionProc->taskStateSegment.oldTSS = schedulerProc->tssSelector; // Mark the process as finished and yield the timeslice back to the // scheduler. The scheduler will take care of dismantling the process exceptionProc->state = proc_sleeping; kernelMultitaskerYield(); }}void kernelMultitaskerDumpProcessList(void){ // This routine is used to dump an internal listing of the current // process to the output. kernelTextOutputStream *currentOutput = NULL; kernelProcess *tmpProcess = NULL; char buffer[1024]; int count; // Make sure multitasking has been enabled if (!multitaskingEnabled) return; // Get the current output stream currentOutput = kernelTextGetCurrentOutput(); if (numQueued > 0) { kernelTextStreamPrintLine(currentOutput, "Process list:"); for (count = 0; count < numQueued; count ++) { tmpProcess = processQueue[count]; sprintf(buffer, "\"%s\" PID=%d UID=%d priority=%d " "priv=%d parent=%d\n %d%% CPU State=", (char *) tmpProcess->processName, tmpProcess->processId, tmpProcess->userId, tmpProcess->priority, tmpProcess->privilege, tmpProcess->parentProcessId, tmpProcess->cpuPercent); // Get the state switch(tmpProcess->state) { case proc_running: strcat(buffer, "running"); break; case proc_ready: strcat(buffer, "ready"); break; case proc_waiting: strcat(buffer, "waiting"); break; case proc_sleeping: strcat(buffer, "sleeping"); break; case proc_stopped: strcat(buffer, "stopped"); break; case proc_finished: strcat(buffer, "finished"); break; case proc_zombie: strcat(buffer, "zombie"); break; default: strcat(buffer, "unknown"); break; } kernelTextStreamPrintLine(currentOutput, buffer); } } else // This doesn't seem at all likely. kernelTextStreamPrintLine(currentOutput, "No processes remaining"); kernelTextStreamNewline(currentOutput); return;}int kernelMultitaskerCreateProcess(const char *name, int privilege, processImage *execImage){ // This function is called to set up an (initially) single-threaded // process in the multitasker. This is the routine used by external // sources -- the loader for example -- to define new processes. This // new process thread we're creating will have its state set to "stopped" // after this call. The caller should use the // kernelMultitaskerChangeThreadState routine to start the new thread. // This function returns the processId of the new process on success, // negative otherwise. int status = 0; int processId = 0; kernelProcess *newProcess = NULL; // Make sure multitasking has been enabled if (!multitaskingEnabled) return (status = ERR_NOTINITIALIZED); // Make sure the parameters are valid if ((name == NULL) || (execImage == NULL)) return (status = ERR_NULLPARAMETER); // Make sure that an unprivileged process is not trying to create a // privileged one if ((kernelCurrentProcess->privilege == PRIVILEGE_USER) && (privilege == PRIVILEGE_SUPERVISOR)) { kernelError(kernel_error, "An unprivileged process cannot create a " "privileged process"); return (status == ERR_PERMISSION); } // Create the new process processId = createNewProcess(name, PRIORITY_DEFAULT, privilege, execImage, 1); // create page directory // Get the pointer to the new process from its process Id newProcess = getProcessById(processId); if (newProcess == NULL) // We couldn't get access to the new process return (status = ERR_NOCREATE); // Create the process' environment status = kernelEnvironmentCreate(newProcess->processId, (variableList *) &(newProcess->environment), (variableList *) &(kernelCurrentProcess->environment)); if (status < 0) // Couldn't create an environment structure for this process return (status); // Don't assign input or output streams to this process. There are // multiple possibilities here, and the caller will have to either block // (which takes care of such things) or sort it out for themselves. // Return whatever was returned by the previous call return (processId);}int kernelMultitaskerSpawn(void *startAddress, const char *name, int argc, void *argv[]){ // This function is used to spawn a new thread from the current // process. The function needs to be told the starting address of // the code to execute, and an optional argument to pass to the // spawned function. It returns the new process Id on success, // negative otherwise. int status = 0; int processId = 0; kernelProcess *newProcess = NULL; processImage execImage; int count; // Make sure multitasking has been enabled if (!multitaskingEnabled) return (status = ERR_NOTINITIALIZED); // The start address CAN be NULL, if it is the zero offset in a // process' private address space. // Make sure the pointer to the name is not NULL if (name == NULL) // We cannot continue here return (status = ERR_NULLPARAMETER); // If the number of arguments is not zero, make sure the arguments // pointer is not NULL if (argc && !argv) return (status = ERR_NULLPARAMETER); // Make sure the current process isn't NULL if (kernelCurrentProcess == NULL) return (status = ERR_NOSUCHPROCESS); kernelMemClear(&execImage, sizeof(processImage)); execImage.virtualAddress = startAddress; execImage.entryPoint = startAddress; execImage.code = NULL; execImage.codeSize = 0; execImage.data = NULL; execImage.dataSize = 0; execImage.imageSize = 0; // Set up arguments execImage.argc = (argc + 1); execImage.argv[0] = (char *) name; for (count = 0; count < argc; count ++) execImage.argv[count + 1] = argv[count]; // OK, now we should create the new process processId = createNewProcess(name, kernelCurrentProcess->priority, kernelCurrentProcess->privilege, &execImage, 0); if (processId < 0) return (status = processId); // Get the pointer to the new process from its process Id newProcess = getProcessById(processId); // Make sure it's valid if (newProcess == NULL) // We couldn't get access to the new process return (status = ERR_NOCREATE); // Change the type to thread newProcess->type = proc_thread; // Increment the descendent counts incrementDescendents(newProcess); // Since we assume that the thread is invoked as a function call, // subtract 4 additional bytes from the stack pointer to account for // the space where the return address would normally go. newProcess->taskStateSegment.ESP -= 4; // Copy the environment newProcess->environment = kernelCurrentProcess->environment; // The new process should share (but not own) the same text streams as the // parent newProcess->textInputStream = kernelCurrentProcess->textInputStream; newProcess->textOutputStream = kernelCurrentProcess->textOutputStream; // Make the new thread runnable newProcess->state = proc_ready; // Return the new process' Id. return (newProcess->processId);}int kernelMultitaskerSpawnKernelThread(void *startAddress, const char *name, int argc, void *argv[]){ // This function is a wrapper around the regular spawn() call, which // causes threads to be spawned as children of the kernel, instead of // children of the calling process. This is important for threads that // are spawned from code which belongs to the kernel. int status = 0; int interrupts = 0; kernelProcess *myProcess; // Make sure multitasking has been enabled if (!multitaskingEnabled) return (status = ERR_NOTINITIALIZED); // What is the current process? myProcess = kernelCurrentProcess; // Disable interrupts while we're monkeying kernelProcessorSuspendInts(interrupts); // Change the current process to the kernel process kernelCurrentProcess = kernelProc; // Spawn status = kernelMultitaskerSpawn(startAddress, name, argc, argv); // Reset the current process kernelCurrentProcess = myProcess; // Reenable interrupts kernelProcessorRestoreInts(interrupts); // Done return (status);}int kernelMultitaskerGetProcess(int processId, process *userProcess){ // Return the requested process. int status = 0; kernelProcess *kernProcess = NULL; // Make sure multitasking has been enabled if (!multitaskingEnabled) return (status = ERR_NOTINITIALIZED); // Check params if (userProcess == NULL) return (status = ERR_NULLPARAMETER); // Try to match the requested process Id number with a real // live process structure kernProcess = getProcessById(processId); if (kernProcess == NULL) // That means there's no such process return (status = ERR_NOSUCHENTRY); // Make it into a user space process kernelProcess2Process(kernProcess, userProcess); return (status = 0);}int kernelMultitaskerGetProcessByName(const char *processName, process *userProcess){ // Return the requested process. int status = 0; kernelProcess *kernProcess = NULL; // Make sure multitasking has been enabled if (!multitaskingEnabled) return (status = ERR_NOTINITIALIZED); // Check params if ((processName == NULL) || (userProcess == NULL)) return (status = ERR_NULLPARAMETER); // Try to match the requested process Id number with a real // live process structure kernProcess = getProcessByName(processName); if (kernProcess == NULL) // That means there's no such process return (status = ERR_NOSUCHENTRY); // Make it into a user space process kernelProcess2Process(kernProcess, userProcess); return (status = 0);}int kernelMultitaskerGetProcesses(void *buffer, unsigned buffSize){ // Return user-space process structures into the supplied buffer int status = 0; kernelProcess *kernProcess = NULL; process *userProcess = NULL; // Make sure multitasking has been enabled if (!multitaskingEnabled) return (status = ERR_NOTINITIALIZED); // Check params if (buffer == NULL) return (status = ERR_NULLPARAMETER); for (status = 0; status < numQueued; status ++) { kernProcess = processQueue[status]; userProcess = (buffer + (status * sizeof(process))); if ((void *) userProcess >= (buffer + buffSize)) break; kernelProcess2Process(kernProcess, userProcess); } return (status);}int kernelMultitaskerGetCurrentProcessId(void){ // This is a very simple routine that can be called by external // programs to get the PID of the current running process. Of course, // internal functions can perform this action very easily themselves. int status = 0; // Make sure multitasking has been enabl
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -