/* * Spawn a user process. * Params: * program - the full path of the program executable file * command - the command, including name of program and arguments * pThread - reference to Kernel_Thread pointer where a pointer to * the newly created user mode thread (process) should be * stored * Returns: * The process id (pid) of the new process, or an error code * if the process couldn't be created. Note that this function * should return ENOTFOUND if the reason for failure is that * the executable file doesn't exist. */ int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread) { /* * Hints: * - Call Read_Fully() to load the entire executable into a memory buffer * - Call Parse_ELF_Executable() to verify that the executable is * valid, and to populate an Exe_Format data structure describing * how the executable should be loaded * - Call Load_User_Program() to create a User_Context with the loaded * program * - Call Start_User_Thread() with the new User_Context * * If all goes well, store the pointer to the new thread in * pThread and return 0. Otherwise, return an error code. */ /* Por Victor Rosales */ char *exeFileData = 0; ulong_t exeFileLength = 0; struct Exe_Format exeFormat; struct User_Context *userContext = NULL; struct Kernel_Thread *process = NULL; int ret = 0; ret = Read_Fully(program, (void**) &exeFileData, &exeFileLength); if (ret != 0) { ret = ENOTFOUND; goto error; } ret = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat); if (ret != 0) { ret = ENOEXEC; goto error; } ret = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext); if (ret != 0) { ret = -1; goto error; } process = Start_User_Thread(userContext, false); if (process == NULL) { ret = -1; goto error; } *pThread = process; ret =(*pThread)->pid; error: if (exeFileData) Free(exeFileData); exeFileData = 0; return ret; }
/* * Spawn a user process. * Params: * program - the full path of the program executable file * command - the command, including name of program and arguments * pThread - reference to Kernel_Thread pointer where a pointer to * the newly created user mode thread (process) should be * stored * Returns: * The process id (pid) of the new process, or an error code * if the process couldn't be created. Note that this function * should return ENOTFOUND if the reason for failure is that * the executable file doesn't exist. */ int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread) { /* * Hints: * - Call Read_Fully() to load the entire executable into a memory buffer * - Call Parse_ELF_Executable() to verify that the executable is * valid, and to populate an Exe_Format data structure describing * how the executable should be loaded * - Call Load_User_Program() to create a User_Context with the loaded * program * - Call Start_User_Thread() with the new User_Context * * If all goes well, store the pointer to the new thread in * pThread and return 0. Otherwise, return an error code. */ char *exeFileData = 0; ulong_t exeFileLength; struct Exe_Format exeFormat; struct User_Context* pUserContext; if (userdebug) { Print("Reading %s...\n", program); } if (Read_Fully(program, (void**) &exeFileData, &exeFileLength) != 0) { Print("Read_Fully failed to read %s from disk\n", program); return -1; } if (userdebug) { Print("Read_Fully OK\n"); } if (Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat) != 0) { Print("Parse_ELF_Executable failed\n"); return -1; } if (userdebug) { Print("Parse_ELF_Executable OK\n"); } Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, (struct User_Context **)&pUserContext); *pThread = Start_User_Thread(pUserContext, false); return (*pThread)->pid; }
/* * Spawn a user process. * Params: * program - the full path of the program executable file * command - the command, including name of program and arguments * pThread - reference to Kernel_Thread pointer where a pointer to * the newly created user mode thread (process) should be * stored * Returns: * Zero or an error code * if the process couldn't be created. Note that this function * should return ENOTFOUND if the reason for failure is that * the executable file doesn't exist. */ int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread, bool background) { int rc; char *exeFileData = 0; ulong_t exeFileLength; struct User_Context *userContext = 0; struct Kernel_Thread *process = 0; struct Exe_Format exeFormat; /* * Load the executable file data, parse ELF headers, * and load code and data segments into user memory. */ if ((rc = Read_Fully(program, (void **)&exeFileData, &exeFileLength)) != 0 || (rc = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat)) != 0 || (rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext)) != 0) goto fail; /* * User program has been loaded, so we can free the * executable file data now. */ Free(exeFileData); exeFileData = 0; strncpy(userContext->name, program, MAX_PROC_NAME_SZB); userContext->name[MAX_PROC_NAME_SZB - 1] = '\0'; /* Start the process! */ process = Start_User_Thread(userContext, background); if (process != 0) { /* Return Kernel_Thread pointer */ *pThread = process; } else rc = ENOMEM; return rc; fail: if (exeFileData != 0) Free(exeFileData); if (userContext != 0) Destroy_User_Context(userContext); return rc; }
struct Kernel_Thread* Start_User_Program( const struct User_Program* program, Boolean detached , int argc, char *argv[], char *command, int commandLeng\ th) { // your P1 code here // copy paramters argmemBase = &processMem[userContext->size-4096]; memcpy(argmemBase, &argc, sizeof(int)); // subtract base address for (i=0; i < argc; i++) argv[i] = (char *) (argv[i] - command); memcpy(&argmemBase[sizeof(int)], argv, sizeof(char *) * argc); memcpy(&argmemBase[sizeof(int) + sizeof(char *) * argc], command, commandLeng\ th); // Fire it up! return Start_User_Thread( userContext, program->entryAddr, detached ); }
/* * Spawn a user process. * Params: * program - the full path of the program executable file * command - the command, including name of program and arguments * pThread - reference to Kernel_Thread pointer where a pointer to * the newly created user mode thread (process) should be * stored * Returns: * The process id (pid) of the new process, or an error code * if the process couldn't be created. Note that this function * should return ENOTFOUND if the reason for failure is that * the executable file doesn't exist. */ int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread, bool detached) { /* * Hints: * - Call Read_Fully() to load the entire executable into a memory buffer * - Call Parse_ELF_Executable() to verify that the executable is * valid, and to populate an Exe_Format data structure describing * how the executable should be loaded * - Call Load_User_Program() to create a User_Context with the loaded * program * - Call Start_User_Thread() with the new User_Context * * If all goes well, store the pointer to the new thread in * pThread and return 0. Otherwise, return an error code. */ // TODO("Spawn a process by reading an executable from a filesystem"); int error = 0; char *exeFileData = 0; ulong_t exeFileLength; struct Exe_Format exeFormat; struct User_Context *userContext = 0; // userContext will become (*pThread)->userContext, through function Attach_User_Context() if everything is successful if(USERDEBUG) Print("Reading %s %s\n", program, command); if((error = Read_Fully(program, (void**) &exeFileData, &exeFileLength)) != 0) { if(USERDEBUG) Print("Read_Fully failed to read %s from disk\n", program); Free(exeFileData); return error; } if(USERDEBUG) Print("Read_Fully OK\n"); if((error = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat)) != 0) { if(USERDEBUG) Print("Parse_ELF_Executable failed\n"); Free(exeFileData); return error; } if(USERDEBUG) Print("Parse_ELF_Executable OK\n"); if((error = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &userContext)) != 0) { if(USERDEBUG) Print("Load_User_Program failed\n"); Free(exeFileData); Free(userContext); return error; } if(USERDEBUG) Print("Load_User_Program for program: %s OK\n", program); /*deleting local copy of exeFileData because Load_User_Program was successfully*/ Free(exeFileData); (*pThread) = Start_User_Thread(userContext, detached); if(!(*pThread)) return ENOMEM; if(USERDEBUG) { Print("Spawn complete\nDump_All_Thread_List:\n"); Dump_All_Thread_List(); } return (*pThread)->pid; }
/* * Spawn a user process. * Params: * program - the full path of the program executable file * command - the command, including name of program and arguments * pThread - reference to Kernel_Thread pointer where a pointer to * the newly created user mode thread (process) should be * stored * Returns: * The process id (pid) of the new process, or an error code * if the process couldn't be created. Note that this function * should return ENOTFOUND if the reason for failure is that * the executable file doesn't exist. */ int Spawn(const char *program, const char *command, struct Kernel_Thread **pThread) { /* * Hints: * - Call Read_Fully() to load the entire executable into a memory buffer * - Call Parse_ELF_Executable() to verify that the executable is * valid, and to populate an Exe_Format data structure describing * how the executable should be loaded * - Call Load_User_Program() to create a User_Context with the loaded * program * - Call Start_User_Thread() with the new User_Context * * If all goes well, store the pointer to the new thread in * pThread and return 0. Otherwise, return an error code. */ //TODO("Spawn a process by reading an executable from a filesystem"); char *exeFileData = 0; ulong_t exeFileLength; struct Exe_Format exeFormat; struct User_Context * pUserContext = NULL; struct Kernel_Thread* pkthread; int rc; if (lprogdebug) { Print("Reading %s...\n", program); } if ( (rc = Read_Fully(program, (void**) &exeFileData, &exeFileLength)) != 0) { Print("Read_Fully failed to read %s from disk\n", program); goto fail; } if (lprogdebug) { Print("Read_Fully OK\n"); } if ((rc = Parse_ELF_Executable(exeFileData, exeFileLength, &exeFormat)) != 0) { Print("Parse_ELF_Executable failed\n"); goto fail; } if (lprogdebug) { Print("Parse_ELF_Executable OK\n"); } if ( (rc = Load_User_Program(exeFileData, exeFileLength, &exeFormat, command, &pUserContext)) != 0) { Print("Load_User_Program failed\n"); goto fail; } if ((pkthread = Start_User_Thread(pUserContext, false)) == NULL) //ERROR detached should be false { Print("Start_User_Thread Failed!\n"); rc = -1; goto fail; } /* * User program has been loaded, so we can free the * executable file data now. */ Free(exeFileData); exeFileData = 0; /* If we arrived here, everything was fine and the program exited */ //Print("If you see this you're happy\n"); *pThread = pkthread; if(pThread == NULL) Print("wrong!\n"); return pkthread->pid; // Exit(0); as this is not a thread, we don't exit but return. fail: /* We failed; release any allocated memory */ //if(Interrupts_Enabled()) Disable_Interrupts(); if(pUserContext != NULL && pUserContext->memory != NULL) Free(pUserContext->memory); Enable_Interrupts(); return rc; }