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

📄 kernelmultitasker.c

📁 上一个上传的有问题,这个是好的。visopsys包括系统内核和GUI的全部SOURCE code ,还包括一些基本的docs文档。里面src子目录对应所有SOURCE code.对于想研究操作系统的朋
💻 C
📖 第 1 页 / 共 5 页
字号:
	kernelPageGetPhysical(newProcess->parentProcessId, execImage->code);      // Make the process own its code/data memory.  Don't remap it yet      // because we want to map it at the requested virtual address.      status = kernelMemoryChangeOwner(newProcess->parentProcessId,				newProcess->processId, 0, execImage->code,				NULL);      if (status < 0)	{	  // Couldn't make the process own its memory	  releaseProcess(newProcess);	  return (status);	}      // Remap the code/data to the requested virtual address.      status = kernelPageMap(newProcess->processId, physicalCodeData,			     execImage->virtualAddress, execImage->imageSize);      if (status < 0)	{	  // Couldn't map the process memory	  releaseProcess(newProcess);	  return (status);	}      // Code should be read-only      status =	kernelPageSetAttrs(newProcess->processId, 0, PAGEFLAG_WRITABLE,			   execImage->virtualAddress, execImage->codeSize);      if (status < 0)	{	  releaseProcess(newProcess);	  return (status);	}    }  else    {      // This process will share a page directory with its parent      processPageDir = kernelPageShareDirectory(newProcess->parentProcessId, 						newProcess->processId);      if (processPageDir == NULL)	{	  // Not able to setup a page directory	  releaseProcess(newProcess);	  return (status = ERR_NOVIRTUAL);	}    }  // Give the process a stack  stackMemoryAddr =    kernelMemoryGet((DEFAULT_STACK_SIZE + DEFAULT_SUPER_STACK_SIZE),		    "process stack");  if (stackMemoryAddr == NULL)    {      // We couldn't make a stack for the new process.  Maybe the system      // doesn't have anough available memory?      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }  if (newProcess->privilege == PRIVILEGE_USER)    {      newProcess->userStackSize = DEFAULT_STACK_SIZE;      newProcess->superStackSize = DEFAULT_SUPER_STACK_SIZE;    }  else    newProcess->userStackSize =      (DEFAULT_STACK_SIZE + DEFAULT_SUPER_STACK_SIZE);  // Copy 'argc' and 'argv' arguments to the new process' stack while we  // still own the stack memory.  // Set pointers to the appropriate stack locations for the arguments  args = (stackMemoryAddr + newProcess->userStackSize - (2 * sizeof(int)));  // Calculate the amount of memory we need to allocate for argument data.  // Leave space for pointers to the strings, since the (int argc,  // char *argv[]) scheme means just 2 values on the stack: an integer  // an a pointer to an array of char* pointers...  argSpaceSize = ((execImage->argc + 1) * sizeof(char *));  for (count = 0; count < execImage->argc; count ++)    argSpaceSize += (strlen(execImage->argv[count]) + 1);  // Get memory for the argument data  argSpace = kernelMemoryGet(argSpaceSize, "process arguments");  if (argSpace == NULL)    {      kernelMemoryRelease(stackMemoryAddr);      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }        // Change ownership to the new process, and share it back with this process.  if (kernelMemoryChangeOwner(newProcess->parentProcessId,			      newProcess->processId, 1, argSpace,			      (void **) &newArgAddress) < 0)    {      kernelMemoryRelease(stackMemoryAddr);      kernelMemoryRelease(argSpace);      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }  if (kernelMemoryShare(newProcess->processId, newProcess->parentProcessId,			newArgAddress, (void **) &argSpace) < 0)    {      kernelMemoryRelease(stackMemoryAddr);      releaseProcess(newProcess);      return (status = ERR_MEMORY);    }  args[0] = execImage->argc;  args[1] = (int) newArgAddress;	  argv = (char **) argSpace;  argSpace += ((execImage->argc + 1) * sizeof(char *));  newArgAddress += ((execImage->argc + 1) * sizeof(char *));  // Copy the args into argv  for (count = 0; count < execImage->argc; count ++)    {      strcpy((argSpace + length), execImage->argv[count]);      argv[count] = (newArgAddress + length);      length += (strlen(execImage->argv[count]) + 1);    }  // argv[argc] is supposed to be a NULL pointer, according to  // some standard or other  argv[args[0]] = NULL;  // Unmap the argument space from this process  kernelPageUnmap(newProcess->parentProcessId, argSpace, argSpaceSize);  // Make the process own its stack memory  status = kernelMemoryChangeOwner(newProcess->parentProcessId, 				   newProcess->processId, 1, // remap				   stackMemoryAddr, 				   (void **) &(newProcess->userStack));  if (status < 0)    {      // Couldn't make the process own its memory      kernelMemoryRelease(stackMemoryAddr);      releaseProcess(newProcess);      return (status);    }  // Get the new virtual address of supervisor stack  if (newProcess->privilege == PRIVILEGE_USER)    newProcess->superStack = (newProcess->userStack + DEFAULT_STACK_SIZE);  // Create the TSS (Task State Segment) for this process.  status = createTaskStateSegment(newProcess, processPageDir);  if (status < 0)    {      // Not able to create the TSS      releaseProcess(newProcess);      return (status);    }  // Adjust the stack pointer to account for the arguments that we copied to  // the process' stack  newProcess->taskStateSegment.ESP -= sizeof(int);  // Set the EIP to the entry point  newProcess->taskStateSegment.EIP = (unsigned) execImage->entryPoint;  // added by Davide Airaghi for FPU-state handling                                                                                               FPU_STATUS_ZERO(newProcess->fpu,count)      // Finally, add the process to the process queue  status = addProcessToQueue(newProcess);  if (status < 0)    {      // Not able to queue the process.      releaseProcess(newProcess);      return (status);    }  // Return the processId on success.  return (status = newProcess->processId);}static int deleteProcess(kernelProcess *killProcess){  // Does all the work of actually destroyng a process when there's really  // no more use for it.  This occurs after all descendent threads have  // terminated, for example.  int status = 0;  // Processes cannot delete themselves  if (killProcess == kernelCurrentProcess)    {      kernelError(kernel_error, "Process %d cannot delete itself",		  killProcess->processId);      return (status = ERR_INVALID);    }  // Remove the process from the multitasker's process queue.  status = removeProcessFromQueue(killProcess);  if (status < 0)    {      // Not able to remove the process      kernelError(kernel_error, "Can't dequeue process");      return (status);    }  // We need to deallocate the TSS descriptor allocated to the process, if  // it has one  if (killProcess->tssSelector)    {      status = kernelDescriptorRelease(killProcess->tssSelector);      // If this was unsuccessful, we don't want to continue and "lose"       // the descriptor      if (status < 0)	{	  kernelError(kernel_error, "Can't release TSS");	  return (status);	}    }  // If the process has a signal stream, destroy it  if (killProcess->signalStream.buffer)    kernelStreamDestroy((stream *) &(killProcess->signalStream));  // Deallocate all memory owned by this process  status = kernelMemoryReleaseAllByProcId(killProcess->processId);  // Likewise, if this deallocation was unsuccessful, we don't want to  // deallocate the process structure.  If we did, the memory would become  // "lost".  if (status < 0)    {      kernelError(kernel_error, "Can't release process memory");      return (status);    }  // Delete the page table we created for this process  status = kernelPageDeleteDirectory(killProcess->processId);  // If this deletion was unsuccessful, we don't want to deallocate the   // process structure.  If we did, the page directory would become "lost".  if (status < 0)    {      kernelError(kernel_error, "Can't release page directory");      return (status);    }  // Finally, release the process structure  status = releaseProcess(killProcess);  if (status < 0)    {      kernelError(kernel_error, "Can't release process structure");      return (status);    }  return (status = 0);}static int exceptionThreadInitialize(void){  // This function will initialize the kernel's exception handler thread.    // It should be called after multitasking has been initialized.    int status = 0;  int procId = 0;  int count;  // One of the first things the kernel does at startup time is to install   // a simple set of interrupt handlers, including ones for handling   // processor exceptions.  We want to replace those with a set of task  // gates, so that a context switch will occur -- giving control to the  // exception handler thread.  // OK, we will now create the kernel's exception handler thread.  procId = kernelMultitaskerSpawn(&kernelExceptionHandler, "exception thread",				  0, NULL);  if (procId < 0)    {      kernelError(kernel_error, "Unable to create the kernel's exception "		  "thread");      return (procId);    }  exceptionProc = getProcessById(procId);  if (exceptionProc == NULL)    {      kernelError(kernel_error, "Unable to create the kernel's exception "		  "thread");      return (procId);    }  // Set the process state to sleep  exceptionProc->state = proc_sleeping;  status = kernelDescriptorSet(	       exceptionProc->tssSelector, // TSS selector	       &(exceptionProc->taskStateSegment), // Starts at...	       sizeof(kernelTSS),      // Maximum size of a TSS selector	       1,                      // Present in memory	       PRIVILEGE_SUPERVISOR,   // Highest privilege level	       0,                      // TSS's are system segs	       0x9,                    // TSS, 32-bit, non-busy	       0,                      // 0 for SMALL size granularity	       0);                     // Must be 0 in TSS  if (status < 0)    // Something went wrong    return (status);  // Interrupts should always be disabled for this task   exceptionProc->taskStateSegment.EFLAGS = 0x00000002;  // Set up interrupt task gates to send all the exceptions to this new  // thread  for (count = 0; count < 19; count ++)    {      status =	kernelDescriptorSetIDTTaskGate(count, exceptionProc->tssSelector);      if (status < 0)	{	  kernelError(kernel_error, "Unable to set interrupt task gate for "		      "exception %d", count);	  return (status);	}    }  return (status = 0);}static void idleThread(void){  // This is the idle task.  It runs in this loop whenever no other   // processes need the CPU.  However, the only thing it does inside  // that loop -- as you can probably see -- is run in a loop.  This should  // be run at the absolute lowest possible priority so that it will not   // be run unless there is absolutely nothing else in the other queues   // that is ready.  while(1);}static int spawnIdleThread(void){  // This function will create the idle thread at initialization time.  // Returns 0 on success, negative otherwise.  int status = 0;  int idleProcId = 0;  // The idle thread needs to be a child of the kernel  idleProcId = kernelMultitaskerSpawn(idleThread, "idle thread", 0, NULL);  if (idleProcId < 0)    return (idleProcId);  idleProc = getProcessById(idleProcId);  if (idleProc == NULL)    return (status = ERR_NOSUCHPROCESS);  // Set it to the lowest priority  status =    kernelMultitaskerSetProcessPriority(idleProcId, (PRIORITY_LEVELS - 1));  if (status < 0)    // There's no reason we should have to fail here, but make a warning    kernelError(kernel_warn, "The multitasker was unable to lower the "		"priority of the idle thread");  // Return success  return (status = 0);}static int schedulerShutdown(void){  // This function will perform all of the necessary shutdown to stop  // the sheduler and return control to the kernel's main task.  // This will probably only be useful at system shutdown time.  // NOTE that this function should NEVER be called directly.  If this  // advice is ignored, you have no assurance that things will occur  // the way you might expect them to.  To shut down the scheduler,  // set the variable schedulerStop to a nonzero value.  The scheduler  // will then invoke this function when it's ready.  int status = 0;  // Restore the normal operation of the system timer 0, which is  // mode 3, initial count of 0  status = kernelSysTimerSetupTimer(0, 3, 0);  if (status < 0)    kernelError(kernel_warn, "Could not restore system timer");  // Remove the task gate that we were using to capture the timer  // interrupt.  Replace it with the old default timer interrupt handler  kernelInterruptHook(INTERRUPT_NUM_SYSTIMER, oldSysTimerHandler);  // Give exclusive control to the current task  schedulerProc->taskStateSegment.oldTSS = kernelCurrentProcess->tssSelector;  // Do an interrupt return.  kernelProcessorIntReturn();  // We should never get here  return (status = 0);}static int markTaskBusy(int tssSelector, int busy){  // This function gets the requested TSS selector from the GDT and  // marks it as busy/not busy.  Returns negative on error.    int status = 0;  kernelDescriptor descriptor;

⌨️ 快捷键说明

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