⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kernelmultitasker.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
      // there's simply nothing to do.  However, if there is some process      // that is in a 'waiting' state, then there will be stuff to do when      // it wakes up.      if (nextProcess == NULL)	{	  // Resume the loop	  schedulerSwitchedByCall = 1;	  continue;	}      // Update some info about the next process      nextProcess->waitTime = 0;      nextProcess->state = proc_running;            // Export (to the rest of the multitasker) the pointer to the      // currently selected process.      kernelCurrentProcess = nextProcess;      // Set the system timer 0 to interrupt this task after a known      // period of time (mode 0)      status = kernelSysTimerSetupTimer(0, 0, TIME_SLICE_LENGTH);      if (status < 0)	{	  kernelError(kernel_warn, "The scheduler was unable to control "		      "the system timer");	  // Shut down the scheduler.	  schedulerShutdown();	  // Just in case	  kernelProcessorStop();	}      // In the final part, we do the actual context switch.      // Acknowledge the timer interrupt if one occurred      if (!schedulerSwitchedByCall)	kernelPicEndOfInterrupt(INTERRUPT_NUM_SYSTIMER);      // Reset the "switched by call" flag      schedulerSwitchedByCall = 0;      // Move the selected task's selector into the link field      // cast required! Davide Airaghi      ((kernelTSS *)(schedulerProc->taskStateSegment))->oldTSS = nextProcess->tssSelector;      // Return to the task.  Do an interrupt return.      kernelProcessorIntReturn();      // Continue to loop    }  // If we get here, then the scheduler is supposed to shut down  schedulerShutdown();  // We should never get here  return (status = 0);}static int schedulerInitialize(void){  // This function will do all of the necessary initialization for the  // scheduler.  Returns 0 on success, negative otherwise  // The scheduler needs to make a task (but not a fully-fledged  // process) for itself.  All other task switches will follow  // as nested tasks from the scheduler.    int status = 0;  int interrupts = 0;  processImage schedImage = {    scheduler, scheduler,    NULL, 0xFFFFFFFF,    NULL, 0xFFFFFFFF,    0xFFFFFFFF,    "", 0, { NULL }  };    status = createNewProcess("scheduler process", kernelProc->priority,			    kernelProc->privilege, &schedImage, 0);  if (status < 0)    return (status);  schedulerProc = getProcessById(status);  removeProcessFromQueue(schedulerProc);  // Set the instruction pointer to the scheduler task  // cast required! Davide Airaghi  ((kernelTSS *)(schedulerProc->taskStateSegment))->EIP = (unsigned) scheduler;  // Interrupts should always be disabled for this task, and we manually set  // the NT (nested task) flag as well, since Virtual PC doesn't do it when  // we switch the first time.  // cast required! Davide Airaghi  ((kernelTSS *)(schedulerProc->taskStateSegment))->EFLAGS = 0x00004002;  // Get a page directory  // cast required! Davide Airaghi  ((kernelTSS *)(schedulerProc->taskStateSegment))->CR3 =    (unsigned) kernelPageGetDirectory(KERNELPROCID);  // Not busy  markTaskBusy(schedulerProc->tssSelector, 0);  // The scheduler task should now be set up to run.  We should set   // up the kernel task to resume operation    // Before we load the kernel's selector into the task reg, mark it as  // not busy, since one cannot load the task register, with a busy TSS  // selector...  markTaskBusy(kernelProc->tssSelector, 0);  // Make the kernel's Task State Segment be the current one.  In  // reality, it IS still the currently running code  kernelProcessorLoadTaskReg(kernelProc->tssSelector);  // Reset the schedulerTime and schedulerTimeslices  schedulerTime = 0;  schedulerTimeslices = 0;    // Make sure the scheduler is set to "run"  schedulerStop = 0;  // Clear the "switched by call" flag  schedulerSwitchedByCall = 0;  // Make note that the multitasker has been enabled.  We do it a little  // early so we can finish some of our tasks of creating threads without  // complaints  multitaskingEnabled = 1;  // Yield control to the scheduler  kernelMultitaskerYield();  // Disable interrupts, so we can insure that we don't immediately get  // a timer interrupt.  kernelProcessorSuspendInts(interrupts);  // Hook the system timer interrupt.  oldSysTimerHandler = kernelInterruptGetHandler(INTERRUPT_NUM_SYSTIMER);  if (oldSysTimerHandler == NULL)    return (status = ERR_NOTINITIALIZED);  // Install a task gate for the interrupt, which will be the scheduler's  // timer interrupt.  After this point, our new scheduler task will run  // with every clock tick  status = kernelDescriptorSetIDTTaskGate((0x20 + INTERRUPT_NUM_SYSTIMER), 	 				  schedulerProc->tssSelector);  if (status < 0)    {      kernelProcessorRestoreInts(interrupts);      return (status);    }  // Reenable interrupts after we get control back from the scheduler  kernelProcessorRestoreInts(interrupts);  // Return success  return (status = 0);}static int createKernelProcess(void){  // This function will create the kernel process at initialization time.  // Returns 0 on success, negative otherwise.  int status = 0;  int kernelProcId = 0;  processImage kernImage = {    (void *) KERNEL_VIRTUAL_ADDRESS,    kernelMain,     NULL, 0xFFFFFFFF,    NULL, 0xFFFFFFFF,    0xFFFFFFFF,    "", 0, { NULL }  };  // The kernel process is its own parent, of course, and it is owned   // by "admin".  We create no page table, and there are no arguments.  kernelProcId =     createNewProcess("kernel process", KERNEL_PRIORITY, PRIVILEGE_SUPERVISOR, &kernImage, 0);   if (kernelProcId < 0)    // Damn.  Not able to create the kernel process    return (kernelProcId);  // Get the pointer to the kernel's process  kernelProc = getProcessById(kernelProcId);  // Make sure it's not NULL  if (kernelProc == NULL)    // Can't access the kernel process    return (status = ERR_NOSUCHPROCESS);  // Interrupts are initially disabled for the kernel  // cast required! Davide Airaghi  ((kernelTSS *)(kernelProc->taskStateSegment))->EFLAGS = 0x00000002;  // Set the current process to initially be the kernel process  kernelCurrentProcess = kernelProc;  // Deallocate the stack that was allocated, since the kernel already  // has one.  kernelMemoryRelease(kernelProc->userStack);  // Create the kernel process' environment  status = kernelEnvironmentCreate(KERNELPROCID, (variableList *)				   &(kernelProc->environment), NULL);  if (status < 0)    // Couldn't create an environment structure for this process    return (status);  // Make the kernel's text streams be the console streams  kernelProc->textInputStream = kernelTextGetConsoleInput();  kernelProc->textInputStream->ownerPid = KERNELPROCID;  kernelProc->textOutputStream = kernelTextGetConsoleOutput();  // Make the kernel process runnable  kernelProc->state = proc_ready;  // Return success  return (status = 0);}static void incrementDescendents(kernelProcess *theProcess){  // This will walk up a chain of dependent child threads, incrementing  // the descendent count of each parent    kernelProcess *parentProcess = NULL;  if (theProcess->processId == KERNELPROCID)    // The kernel is its own parent    return;  parentProcess = getProcessById(theProcess->parentProcessId);  if (parentProcess == NULL)    // No worries.  Probably not a problem    return;  parentProcess->descendentThreads++;  // Do a recursion to walk up the chain  incrementDescendents(parentProcess);  // Done  return;}static void decrementDescendents(kernelProcess *theProcess){  // This will walk up a chain of dependent child threads, decrementing  // the descendent count of each parent    kernelProcess *parentProcess = NULL;  if (theProcess->processId == KERNELPROCID)    // The kernel is its own parent    return;  parentProcess = getProcessById(theProcess->parentProcessId);  if (parentProcess == NULL)    // No worries.  Probably not a problem    return;  parentProcess->descendentThreads--;  // Do a recursion to walk up the chain  decrementDescendents(parentProcess);  // Done  return;}static void kernelProcess2Process(kernelProcess *kernProcess,				  process *userProcess){  // Given a kernel-space process structure, create the corresponding  // user-space version.    strncpy(userProcess->processName, (char *) kernProcess->processName,	  MAX_PROCNAME_LENGTH);  userProcess->userId = kernProcess->userId;  userProcess->processId = kernProcess->processId;  userProcess->type = kernProcess->type;  userProcess->priority = kernProcess->priority;  userProcess->privilege = kernProcess->privilege;  userProcess->parentProcessId = kernProcess->parentProcessId;  userProcess->descendentThreads = kernProcess->descendentThreads;  userProcess->cpuPercent = kernProcess->cpuPercent;  userProcess->state = kernProcess->state;}static int fpuExceptionHandler(void){  // This function gets called when a EXCEPTION_DEVNOTAVAIL (7) exception  // occurs.  It can happen under two circumstances:  // CR0[EM] is set: No FPU is present.  We can implement emulation here  //     later in this case, if we want.  // CR0[TS] and CR0[MP] are set: A task switch has occurred since the  //     last FP operation, and we need to restore the state.  int status = 0;  if (fpuProcess == kernelCurrentProcess->processId)    // This process was the last to use the FPU.  Just clear the task    // switched bit    kernelProcessorClearTaskSwitched();  else    {      // Some other process has been using the FPU, or it has not been      // used at all.  Figure out whether we should restore the state      // or else initialize the FPU for this process.      if (kernelCurrentProcess->fpuStateValid)	// Restore the FPU state	kernelProcessorFpuStateRestore(kernelCurrentProcess->fpuState);      else	{	  // The process has not previously used the FPU.  Initialize it	  // and remember that from now on we have to save FPU state.	  kernelProcessorFpuInit();	  kernelCurrentProcess->fpuInUse = 1;	}      fpuProcess = kernelCurrentProcess->processId;    }  return (status = 0);}// set the permission (allow: perm = PORT_VAL_BIT_TRUE; not allow: perm = PORT_VAL_BIT_FALSE )// of a process to have or not to have IO perm on the specified port// return: 0 = ok, < 0 = not ok// Davide Airaghistatic int kernelMultitaskerSetIOperm(int processId, unsigned int portNum,unsigned perm) {  int status = 0;  kernelProcess *Process = NULL;  void * newTSS = NULL;  unsigned int newTSSsize = 0;  int interrupts = 0;  unsigned char * p = NULL;  char a = 10 , b = 11;    // Make sure multitasking has been enabled  if (!multitaskingEnabled)    return (status = ERR_NOTINITIALIZED);  Process = getProcessById(processId);  if (Process == NULL)    {      // There's no such process      kernelError(kernel_error, "No process %d to set IOPerm", processId);      return (status = ERR_NOSUCHPROCESS);    }    if (portNum >= IO_PORTS)	return (status = ERR_BOUNDS);    if (portNum > Process->max_io_port && perm == PORT_VAL_BIT_FALSE) {        // next for debug	// kernelError(kernel_error,"p# %d >? maxp# %d",portNum,Process->max_io_port);	return 0;    }	    // for Debug    //kernelError(kernel_error,"TSS is %d bytes",Process->TSSsize);    if ((portNum > Process->max_io_port) && perm == PORT_VAL_BIT_TRUE) {	// TSS isn't big enough to store IOMap ... we have to do something!	    // Allocate data for TSS!	     newTSSsize = sizeof(kernelTSS)+(sizeof(unsigned char)*(IOMAP_REQUESTED_SIZE(portNum)-1));	     newTSS = kernelMalloc(newTSSsize);	     if (newTSS == NULL) {	        return (ERR_MEMORY);	     }	     kernelMemClear((void *)newTSS, newTSSsize);	     kernelMemCopy(Process->taskStateSegment,newTSS,Process->TSSsize);	     // OK, now the very critical part of the routine ...	     // disable ints for precaution	     kernelProcessorSuspendInts(interrupts);	     	     // Fill in the process' Task State Segment descriptor	     status = kernelDescriptorSet(	         Process->tssSelector, // TSS selector number	         newTSS, // Starts at... 		 newTSSsize,      // Limit of a TSS segment		 1,                      // Present in memory	         PRIVILEGE_SUPERVISOR,   // TSSs are supervisor privilege level		 0,                      // TSSs are system segs    		 0xB,                    // TSS, 32-bit, busy	         0,                      // 0 for SMALL size granularity	         0);                     // Must be 0 in TSS

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -