📄 kernelmultitasker.c
字号:
if (status < 0) { // Crap. An error updating the descriptor. return (status); } // Now, fill the TSS (Task State Segment) for the process. // destroy old TSS! kernelFree(Process->taskStateSegment); // set the new one Process->taskStateSegment = newTSS; Process->TSSsize = newTSSsize; Process->max_io_port = portNum; Process->IOMap = (unsigned char *) (&(((kernelTSS *)(Process->taskStateSegment))->IOMap)); // All done! Re-enable ints kernelProcessorRestoreInts(interrupts); // for Debug //kernelError(kernel_error,"TSS is growing ... now it's %d bytes",newTSSsize); } if (perm == PORT_VAL_BIT_TRUE) ALLOW_PORT_IO(portNum,Process->IOMap) else { if (perm == PORT_VAL_BIT_FALSE) NOT_ALLOW_PORT_IO(portNum,Process->IOMap) else return (status = ERR_BUG); } // for Debug p = (unsigned char *)(&((kernelTSS *)(Process->taskStateSegment))->IOMap); a = GET_PORT_BIT(portNum,Process->IOMap); b = GET_PORT_BIT(portNum, p); kernelError(kernel_error,"Port Bit: %d , %d",a,b); return (status = 0); }////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// Below here, the functions are exported for external use////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////int kernelMultitaskerInitialize(void){ // This function intializes the kernel's multitasker. int status = 0; unsigned cr0 = 0; int count; // Make sure multitasking is NOT enabled already if (multitaskingEnabled) return (status = ERR_ALREADY); // Now we must initialize the process queue for (count = 0; count < MAX_PROCESSES; count ++) processQueue[count] = NULL; numQueued = 0; // Initialize the CPU for floating point operation. We set // CR0[EM]=0 (no emulation) // CR0[MP]=1 (math present) // CR0[NE]=1 (floating point errors cause exceptions) kernelProcessorGetCR0(cr0); cr0 = ((cr0 & ~0x04UL) | 0x22); kernelProcessorSetCR0(cr0); // We need to create the kernel's own process. status = createKernelProcess(); // Make sure it was successful if (status < 0) return (status); // Now start the scheduler status = schedulerInitialize(); if (status < 0) // The scheduler couldn't start return (status); // Create an "idle" thread to consume all unused cycles status = spawnIdleThread(); // Make sure it was successful if (status < 0) return (status); // Set up any specific exception handlers. exceptionVector[EXCEPTION_DEVNOTAVAIL].handler = fpuExceptionHandler; // Log a boot message kernelLog("Multitasking started"); // Return success return (status = 0);}int kernelMultitaskerShutdown(int nice){ // This function will shut down the multitasker and halt the scheduler, // returning exclusive control to the kernel process. If the nice // argument is non-zero, this function will do a nice orderly shutdown, // killing all the running processes gracefully. If it is zero, the // resources allocated to the processes will never be freed, and the // multitasker will just stop. Returns 0 on success, negative otherwise. int status = 0; // Make sure multitasking has been enabled if (!multitaskingEnabled) // We can't yield if we're not multitasking yet return (status = ERR_NOTINITIALIZED); // If we are doing a "nice" shutdown, we will kill all the running // processes (except the kernel and scheduler) gracefully. if (nice) kernelMultitaskerKillAll(); // Set the schedulerStop flag to stop the scheduler schedulerStop = 1; // Yield control back to the scheduler, so that it can stop kernelMultitaskerYield(); // Make note that the multitasker has been disabled multitaskingEnabled = 0; // Deallocate the stack used by the scheduler kernelMemoryReleaseSystem(schedulerProc->userStack); // Print a message kernelLog("Multitasking stopped"); return (status = 0);}void kernelExceptionHandler(int exceptionNum, unsigned address){ // This code sleeps until woken up by an exception. char message[256]; char *symbolName = NULL; int count; extern kernelSymbol *kernelSymbols; extern int kernelNumberSymbols; // We got an exception. // If there's a handler for this exception type, call it if (exceptionVector[exceptionNum].handler != NULL) { if (exceptionVector[exceptionNum].handler() >= 0) // The exception was handled. Return to the task. return; } kernelCurrentProcess->state = proc_stopped; // If the fault occurred while we were processing an interrupt, // we should tell the PIC that the interrupt service routine is // finished. It's not really fair to kill a process because an // interrupt handler is screwy, but that's what we have to do for // the time being. if (kernelProcessingInterrupt) kernelPicEndOfInterrupt(0xFF); if (kernelCurrentProcess == NULL) // We have to make an error here. We can't return to the program // that caused the exception, and we can't tell the multitasker // to kill it. We'd better make a kernel panic. kernelPanic("Exception handler unable to determine current process"); else if (!multitaskingEnabled || (kernelCurrentProcess == kernelProc)) sprintf(message, "The kernel has experienced %s %s exception", exceptionVector[exceptionNum].a, exceptionVector[exceptionNum].name); else sprintf(message, "Process \"%s\" caused %s %s exception", kernelCurrentProcess->processName, exceptionVector[exceptionNum].a, exceptionVector[exceptionNum].name); if (multitaskingEnabled) { if (address >= KERNEL_VIRTUAL_ADDRESS) { if (kernelSymbols) { // Find roughly the kernel function where the exception // happened for (count = 0; count < kernelNumberSymbols; count ++) { if ((address >= kernelSymbols[count].address) && (address < kernelSymbols[count + 1].address)) { symbolName = kernelSymbols[count].symbol; break; } } } if (symbolName) sprintf((message + strlen(message)), " in function %s (%08x)", symbolName, address); else sprintf((message + strlen(message)), " at kernel address %08x", address); } else sprintf((message + strlen(message)), " at application address %08x", address); } if (kernelProcessingInterrupt) sprintf((message + strlen(message)), " while processing interrupt %d", kernelPicGetActive()); if (!multitaskingEnabled || (kernelCurrentProcess == kernelProc)) // If it's the kernel, we're finished kernelPanic(message); else { kernelError(kernel_error, message); if (kernelGraphicsAreEnabled()) kernelErrorDialog("Application Exception", message); } /* // If the process was in kernel code do a stack trace if (!kernelProcessingInterrupt && (address >= KERNEL_VIRTUAL_ADDRESS)) kernelStackTrace((kernelCurrentProcess->userStack + ((void *) kernelCurrentProcess->taskStateSegment.ESP - kernelCurrentProcess->userStack)), (kernelCurrentProcess->userStack + kernelCurrentProcess->userStackSize - sizeof(void *))); */ // The scheduler may now dismantle the process kernelCurrentProcess->state = proc_finished; kernelProcessingInterrupt = 0; // Yield control. 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; // next 3 lines added by Davide Airaghi int orig_privilege = 0; orig_privilege = privilege; privilege &= ~ PRIVILEGE_KERNEL; // 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); } // added by Davide Airaghi privilege = orig_privilege; // 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 *sta
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -