コード例 #1
0
ファイル: timer.c プロジェクト: Danielhu229/geekos-task
/*
 * Calibrate the delay loop.
 * This will initialize s_spinCountPerTick, which indicates
 * how many iterations of the loop are executed per timer tick.
 */
static void Calibrate_Delay(void) {
    Disable_Interrupts();

    /* Install temporarily interrupt handler */
    Install_IRQ(TIMER_IRQ, &Timer_Calibrate);
    Enable_IRQ(TIMER_IRQ);

    Enable_Interrupts();

    /* Wait a few ticks */
    while (g_numTicks < CALIBRATE_NUM_TICKS) ;

    /*
     * Execute the spin loop.
     * The temporary interrupt handler will overwrite the
     * loop counter when the next tick occurs.
     */
    Spin(INT_MAX);

    Disable_Interrupts();

    /*
     * Mask out the timer IRQ again,
     * since we will be installing a real timer interrupt handler.
     */
    Disable_IRQ(TIMER_IRQ);
    Enable_Interrupts();
}
コード例 #2
0
ファイル: user.c プロジェクト: wyl0706/GEEKOS
/*
 * If the given thread has a User_Context,
 * switch to its memory space.
 *
 * Params:
 *   kthread - the thread that is about to execute
 *   state - saved processor registers describing the state when
 *      the thread was interrupted
 */
void Switch_To_User_Context(struct Kernel_Thread* kthread, struct Interrupt_State* state)
{
    /*
     * Hint: Before executing in user mode, you will need to call
     * the Set_Kernel_Stack_Pointer() and Switch_To_Address_Space()
     * functions.
     */
    //TODO("Switch to a new user address space, if necessary");
    	 Set_Kernel_Stack_Pointer((ulong_t)((kthread->stackPage)+PAGE_SIZE));
	// ERROR: only user thread need this function
	if(Interrupts_Enabled())
		Disable_Interrupts();
	if (kthread->userContext != 0)
	{
		//Print("SuC: %d ldt: %d\n", (int)(kthread->userContext), 
		//	(int)));
		//Set_Kernel_Stack_Pointer((ulong_t)(kthread->esp));
		Switch_To_Address_Space(kthread->userContext);
		//Print("Switch to Address Space!\n");
		//Print("jump to %d\n", (int)(kthread->userContext->entryAddr));
		//Dump_Interrupt_State(state);
		//KASSERT(0);
	}
	Enable_Interrupts();

}
コード例 #3
0
int P(int sid)
{
	struct Semaphore* sema = (&s_semaphoreList)->head;
	struct Mutex* mutex;
	struct Condition* cond;

	//find sem by sid
	while (sema != 0)
	{
		if (sema->sid == sid)
		{
			mutex = &(sema->mutex); // important
			cond = &(sema->cond);

			Enable_Interrupts();
			Mutex_Lock(mutex);
			while(sema->count <= 0)
			{
				Cond_Wait(cond, mutex);
				//Print("WAKE UP!");
			}
			sema->count--;
			Mutex_Unlock(mutex);
			Disable_Interrupts();
			
			return 0;
		}
		sema = Get_Next_In_Semaphore_List(sema);
	}
	
	return -1;
}
コード例 #4
0
/*
 * Wake up all threads waiting on the given condition.
 * The mutex guarding the condition should be held!
 */
void Cond_Broadcast(struct Condition* cond)
{
    KASSERT(Interrupts_Enabled());
    Disable_Interrupts();  /* prevent scheduling */
    Wake_Up(&cond->waitQueue);
    Enable_Interrupts();  /* resume scheduling */
}
コード例 #5
0
ファイル: kthread.c プロジェクト: Dreamgoing/myGeekos
/*
 * Wait for given thread to die.
 * Interrupts must be enabled.
 * Returns the thread exit code.
 */
int Join(struct Kernel_Thread* kthread)
{
    int exitCode;

    KASSERT(Interrupts_Enabled());

    /* It is only legal for the owner to join */
    KASSERT(kthread->owner == g_currentThread);

    Disable_Interrupts();

    /* Wait for it to die */
    while (kthread->alive) {
	Wait(&kthread->joinQueue);
    }

    /* Get thread exit code. */
    exitCode = kthread->exitCode;

    /* Release our reference to the thread */
    Detach_Thread(kthread);

    Enable_Interrupts();

    return exitCode;
}
コード例 #6
0
ファイル: syscall.c プロジェクト: khwang18c/CMSC412
/*
 * Flush filesystem buffers
 * Params: none
 * Returns: 0 if successful, error code (< 0) if unsuccessful
 */
static int Sys_Sync(struct Interrupt_State *state) {
  int rc;
  Enable_Interrupts();
  rc = Sync();
  Disable_Interrupts();
  return rc;
}
コード例 #7
0
ファイル: syscall.c プロジェクト: sinabeuro/geekos5
/*
 * Open a file.
 * Params:
 *   state->ebx - address of user string containing path of file to open
 *   state->ecx - length of path
 *   state->edx - file mode flags
 *
 * Returns: a file descriptor (>= 0) if successful,
 *   or an error code (< 0) if unsuccessful
 */
static int Sys_Open(struct Interrupt_State *state)
{
	char path[VFS_MAX_PATH_LEN] = {'\0', };
	struct File **pFile;
	int fd;
	int rc;
	struct File** fileList = g_currentThread->userContext->fileList;

	for(fd = 0; fd < USER_MAX_FILES; fd++){
		if(fileList[fd] == NULL){
			pFile = &fileList[fd];
			break;
		}
	}
	
	if(fd == USER_MAX_FILES)
	{
		return -1;
	}
	
	Copy_From_User(path, state->ebx, state->ecx);
    Enable_Interrupts();
	if((rc = Open(path, state->edx, pFile)) < 0){
		fd = rc;
	}
	Disable_Interrupts();

	return fd;
    //TODO("Open system call");
}
コード例 #8
0
ファイル: kthread.c プロジェクト: Dreamgoing/myGeekos
/*
 * Voluntarily give up the CPU to another thread.
 * Does nothing if no other threads are ready to run.
 */
void Yield(void)
{
    Disable_Interrupts();
    Make_Runnable(g_currentThread);
    Schedule();
    Enable_Interrupts();
}
コード例 #9
0
ファイル: kthread.c プロジェクト: Dreamgoing/myGeekos
/*
 * Exit the current thread.
 * Calling this function initiates a context switch.
 */
void Exit(int exitCode)
{
    struct Kernel_Thread* current = g_currentThread;

    if (Interrupts_Enabled())
	Disable_Interrupts();

    /* Thread is dead */
    current->exitCode = exitCode;
    current->alive = false;

    /* Clean up any thread-local memory */
    Tlocal_Exit(g_currentThread);

    /* Notify the thread's owner, if any */
    Wake_Up(&current->joinQueue);

    /* Remove the thread's implicit reference to itself. */
    Detach_Thread(g_currentThread);

    /*
     * Schedule a new thread.
     * Since the old thread wasn't placed on any
     * thread queue, it won't get scheduled again.
     */
    Schedule();

    /* Shouldn't get here */
    KASSERT(false);
}
コード例 #10
0
ファイル: syscall.c プロジェクト: khwang18c/CMSC412
/*
 * Mount a filesystem.
 * Params:
 * state->ebx - contains a pointer to the Mount_Syscall_Args structure
 *   which contains the block device name, mount prefix,
 *   and filesystem type
 *
 * Returns:
 *   0 if successful, error code if unsuccessful
 */
static int Sys_Mount(struct Interrupt_State *state) {
    int rc = 0;
    struct VFS_Mount_Request *args = 0;

    /* Allocate space for VFS_Mount_Request struct. */
    if ((args =
         (struct VFS_Mount_Request *)Malloc(sizeof(struct VFS_Mount_Request)))
        == 0) {
        rc = ENOMEM;
        goto done;
    }

    /* Copy the mount arguments structure from user space. */
    if (!Copy_From_User(args, state->ebx, sizeof(struct VFS_Mount_Request))) {
        rc = EINVALID;
        goto done;
    }

    /*
     * Hint: use devname, prefix, and fstype from the args structure
     * and invoke the Mount() VFS function.  You will need to check
     * to make sure they are correctly nul-terminated.
     */
    /* TODO("Mount system call"); */
    Enable_Interrupts(); // duped from schulman
    // Print("eee %s %s %s\n", args->devname, args->prefix, args->fstype);
    rc = Mount(args->devname, args->prefix, args->fstype);
    Disable_Interrupts(); // duped from schulman


  done:
    if (args != 0) Free(args);
    return rc;
}
コード例 #11
0
ファイル: syscall.c プロジェクト: sinabeuro/geekos5
/*
 * Open a directory.
 * Params:
 *   state->ebx - address of user string containing path of directory to open
 *   state->ecx - length of path
 *
 * Returns: a file descriptor (>= 0) if successful,
 *   or an error code (< 0) if unsuccessful
 */
static int Sys_OpenDirectory(struct Interrupt_State *state)
{
	char path[VFS_MAX_PATH_LEN] = {'\0' };
	struct File **pDir; /* important */
	int fd;
	int rc;
	struct File** fileList = g_currentThread->userContext->fileList;

	for(fd = 0; fd < USER_MAX_FILES; fd++){
		if(fileList[fd] == NULL){
			pDir = &fileList[fd];
			break;
		}
	}
	
	if(fd == USER_MAX_FILES)
	{
		return -1;
	}

	Copy_From_User(path, state->ebx, state->ecx);
    Enable_Interrupts();			
    //Print("Sys_OpenDirectory : %s\n", path);
	if((rc = Open_Directory(path, pDir)) < 0){ /* important */
		fd = rc;
	}
	//Print("%d, fileList[fd] : %x\n", fd, fileList[fd]);
	Disable_Interrupts();

	return fd;
    //TODO("Open directory system call");
}
コード例 #12
0
ファイル: syscall.c プロジェクト: khwang18c/CMSC412
/*
 * Open a directory.
 * Params:
 *   state->ebx - address of user string containing path of directory to open
 *   state->ecx - length of path
 *
 * Returns: a file descriptor (>= 0) if successful,
 *   or an error code (< 0) if unsuccessful
 */
static int Sys_OpenDirectory(struct Interrupt_State *state) {
  char *path;
  struct File *file;
  int rc = 0;

  rc = get_path_from_registers(state->ebx, state->ecx, &path);
  if(rc != 0) {
    return rc;
  }

  rc = next_descriptor();
  if(rc < 0) {
    return rc;
  }

  Enable_Interrupts(); // duped from schulman
  rc = Open_Directory(path, &file);
  Disable_Interrupts();
  Free(path);

  if(rc >= 0) {
    return add_file_to_descriptor_table(file);
  } else {
    return rc;
  }
}
コード例 #13
0
ファイル: syscall.c プロジェクト: khwang18c/CMSC412
/*
 * Read a directory entry from an open directory handle.
 * Params:
 *   state->ebx - file descriptor of the directory
 *   state->ecx - user address of struct VFS_Dir_Entry to copy entry into
 * Returns: 0 if successful, error code (< 0) if unsuccessful
 */
static int Sys_ReadEntry(struct Interrupt_State *state) {
  int bytes_written = 0;
  /* where is the file table? */
  if(state->ebx > USER_MAX_FILES) {
    return EINVALID;
  }
  if( g_currentThread->userContext->file_descriptor_table[state->ebx] ) {
    void *data_buffer = Malloc(sizeof(struct VFS_Dir_Entry));
    if(!data_buffer) {
      return ENOMEM;
    }
    Enable_Interrupts();
    bytes_written = Read_Entry(g_currentThread->userContext->file_descriptor_table[state->ebx], data_buffer);
    Disable_Interrupts();
    if(bytes_written < 0) {
      Free(data_buffer);
      return bytes_written;
    }
    if (!Copy_To_User(state->ecx, data_buffer, sizeof(struct VFS_Dir_Entry))) {
      Free(data_buffer);
      return EINVALID;
    }
    Free(data_buffer);
    return bytes_written;
  } else {
    return ENOTFOUND;
  }
}
コード例 #14
0
int V(int sid)
{
	struct Semaphore* sema = (&s_semaphoreList)->head;
	struct Mutex* mutex;
	struct Condition* cond;

	//find sem by sid
	while (sema != 0)
	{
		if (sema->sid == sid)
		{
			mutex = &(sema->mutex);
			cond = &(sema->cond);
			
			Enable_Interrupts();
			Mutex_Lock(mutex);
			sema->count = sema->count + 1;
			//Print("wait queue : %d", cond->waitQueue);
			Cond_Broadcast(cond);
			Mutex_Unlock(mutex);
			Disable_Interrupts();
			
			return 0;
		}
		sema = Get_Next_In_Semaphore_List(sema);
	}
	
	return -1;
}
コード例 #15
0
/*
 * Exit system call.
 * The interrupted user process is terminated.
 * Params:
 *   state->ebx - process exit code
 * Returns:
 *   Never returns to user mode!
 */
static int Sys_Exit(struct Interrupt_State* state)
{
    Enable_Interrupts();
    Detach_User_Context(g_currentThread);
    Disable_Interrupts();
    Exit(state->ebx);
    return 0;
}
コード例 #16
0
//------------------------------------------------------------------------------
//    Main Function:                                                          
//------------------------------------------------------------------------------
void main()
{
    //--------------------------------------------------------------------------
    //  PIC Initialization Section
    //--------------------------------------------------------------------------
    Disable_Interrupts(GLOBAL);                 // all interrupts OFF
    Setup_adc(ADC_OFF);                         // ADC not needed
    Setup_adc_ports(NO_ANALOGS);                // No ADC ports needed 
    Setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);  // Timer 0 set for  42.6us, 
    Setup_timer_1(T1_DISABLED);                 // Timer 1  

    Set_Tris_A(TRISA_Enabled);          // SPI Disabled
    Set_Tris_B(TRISB_Disable);          // Flash SPI Disabled 
    Set_Tris_C(TRISC_Disable);          // Flash SPI Disabled

    Output_high(FLASH_SELECT);          // Slash Select High
    Output_high(FLASH_CLOCK);           // Pulse the clock
    Output_low(RTC_RST);                // Disable RTC
    Output_High(FPGALoad);              // FPGA Upload pin
    Output_High(FPGAReset);             // FPGA reset off
    Output_High(TestLED);               // indication of boot up

    spi_enabled   = False;              // ZBC to PIC SPI disabled initially
    spi_write     = False;              // ZBC to PIC SPI disabled initially
    
    Refresh_RTCSPI();                   // Refresh data from RTC into SPI buffer

    //--------------------------------------------------------------------------
    //  USB Initialization Section            
    //--------------------------------------------------------------------------
    usb_init_cs();                      // Initialize the USB Connection
    if(read_eeprom(BOOT_TYPE) > 0) {    // We want boot from FLASH
        FlashToFPGA();                  // If not hooked up to USB then try to init
        Output_Low(FPGAReset);          // FPGA reset off
        Output_High(FPGAReset);         // FPGA reset off
        Output_Low(TestLED);            // Turn off Test LED
    }
    else {
        FGPA_SPI_Init();                // Put PIC in SPI Slave mode 
    }
    
    //--------------------------------------------------------------------------
    //  Main Command Loop:            
    //--------------------------------------------------------------------------
    do {                                // Always do USB Task
        usb_task();                     // so it will detect USB pluging in 
        if(usb_enumerated()) {          // Are we plugged into the USB port ?
            usb_rcvdata_task();         // If so, check for data 
        }
        if(spi_enabled) {               // if ZBC to PIC SPI enabled, then check 
            if(SSP_HAS_DATA()) {
                Handle_SPI();           // Handle SPI request from ZBC
            }
        }                               // Otherwise... just
    } while(True);                      // Continue forever, what else can we do ?
}
コード例 #17
0
ファイル: syscall.c プロジェクト: sinabeuro/geekos5
/*
 * Wait for a process to exit.
 * Params:
 *   state->ebx - pid of process to wait for
 * Returns: the exit code of the process,
 *   or error code (< 0) on error
 */
static int Sys_Wait(struct Interrupt_State* state)
{
	int exitcode;
	Enable_Interrupts();
	exitcode = Join(Lookup_Thread(state->ebx, 1)); // weak;
	Disable_Interrupts();
	return exitcode;

    //TODO("Wait system call");
}
コード例 #18
0
ファイル: syscall.c プロジェクト: khwang18c/CMSC412
/*
 * Create directory
 * Params:
 *   state->ebx - address of user string containing path of new directory
 *   state->ecx - length of path
 *
 * Returns: 0 if successful, error code (< 0) if unsuccessful
 */
static int Sys_CreateDir(struct Interrupt_State *state) {
  char *path;
  int rc = get_path_from_registers(state->ebx, state->ecx, &path);
  if(rc) { return rc; }
  Enable_Interrupts();
  // Print("creating %s\n", path);
  rc = Create_Directory(path);
  Disable_Interrupts();
  return rc;
}
コード例 #19
0
ファイル: syscall.c プロジェクト: khwang18c/CMSC412
/*
 * Delete a file.
 * Params:
 *   state->ebx - address of user string containing path to delete
 *   state->ecx - length of path
 *
 * Returns: 0 if successful, error code (< 0) if unsuccessful
 */
static int Sys_Delete(struct Interrupt_State *state) {
  char *path;
  int rc = get_path_from_registers(state->ebx, state->ecx, &path);
  if(rc) { return rc; }
  Enable_Interrupts(); // duped from schulman
  rc = Delete(path);
  Disable_Interrupts();
  Free(path);
  return rc;
}
コード例 #20
0
ファイル: kthread.c プロジェクト: Dreamgoing/myGeekos
/*
 * The reaper thread.  Its job is to de-allocate memory
 * used by threads which have finished.
 */
static void Reaper(ulong_t arg)
{
    struct Kernel_Thread *kthread;

    Disable_Interrupts();

    while (true) {
	/* See if there are any threads needing disposal. */
	if ((kthread = s_graveyardQueue.head) == 0) {
	    /* Graveyard is empty, so wait for a thread to die. */
	    Wait(&s_reaperWaitQueue);
	}
	else {
	    /* Make the graveyard queue empty. */
	    Clear_Thread_Queue(&s_graveyardQueue);

	    /*
	     * Now we can re-enable interrupts, since we
	     * have removed all the threads needing disposal.
	     */
	    Enable_Interrupts();
	    Yield();   /* allow other threads to run? */

	    /* Dispose of the dead threads. */
	    while (kthread != 0) {
		struct Kernel_Thread* next = Get_Next_In_Thread_Queue(kthread);
#if 0
		Print("Reaper: disposing of thread @ %x, stack @ %x\n",
		    kthread, kthread->stackPage);
#endif
		Destroy_Thread(kthread);
		kthread = next;
	    }

	    /*
	     * Disable interrupts again, since we're going to
	     * do another iteration.
	     */
	    Disable_Interrupts();
	}
    }
}
コード例 #21
0
ファイル: rtc.c プロジェクト: freemicronix/FreeMicroNix
void Initialize_RTC(void)
{
	Install_Interrupt_Handler(IRQ8, RTC_Handler);	// Install the handler
	Disable_Interrupts();
	outb(0x70, 0x8B);		// Select register B and disable NMI
	char prev = inb(0x71);	// Read the current value of register B
	outb(0x70, 0x8B);
	outb(0x71, prev | 0x40);// Write the prev value, turning on bit 6 or register B
	Enable_Interrupts();
	kprintf("Real Time Clock Initialized\n");
}
コード例 #22
0
ファイル: syscall.c プロジェクト: sinabeuro/geekos5
static int Sys_GetCwd(struct Interrupt_State *state)
{
	char spath[VFS_MAX_PATH_LEN] = {'\0', };
	int rc; 
	
	Enable_Interrupts();
	rc = Get_Path(Get_Cwd(), spath);
	Disable_Interrupts();
	Copy_To_User(state->ebx, spath, state->ecx);
	return rc;
}
コード例 #23
0
/*
 * The mutex is currently locked.
 * Atomically reenable preemption and wait in the
 * mutex's wait queue.
 */
static void Mutex_Wait(struct Mutex *mutex)
{
    KASSERT(mutex->state == MUTEX_LOCKED);
    KASSERT(g_preemptionDisabled);

    Disable_Interrupts();
    g_preemptionDisabled = false;
    Wait(&mutex->waitQueue);
    g_preemptionDisabled = true;
    Enable_Interrupts();
}
コード例 #24
0
/*
 * Wait for a process to exit.
 * Params:
 *   state->ebx - pid of process to wait for
 * Returns: the exit code of the process,
 *   or error code (< 0) on error
 */
static int Sys_Wait(struct Interrupt_State* state)
{
    int exit_code;
    struct Kernel_Thread *kthread=Lookup_Thread((int)state->ebx);
    if(kthread==NULL)return -1;
	Enable_Interrupts();
	exit_code = Join(kthread);
	Disable_Interrupts();    
    
    
    return exit_code;
}
コード例 #25
0
ファイル: syscall.c プロジェクト: sinabeuro/geekos5
/*
 * Get file metadata.
 * Params:
 *   state->ebx - address of user string containing path of file
 *   state->ecx - length of path
 *   state->edx - user address of struct VFS_File_Stat object to store metadata in
 *
 * Returns: 0 if successful, error code (< 0) if unsuccessful
 */
static int Sys_Stat(struct Interrupt_State *state)
{
	char path[VFS_MAX_PATH_LEN] = {'\0', };
	int rc = 0;
	Copy_From_User(path, state->ebx, state->ecx);
	
    Enable_Interrupts();
	rc = Stat(path, (struct VFS_File_Stat *)(USER_BASE_ADDR + state->edx));  /* weak */
	Disable_Interrupts();
	return rc;
    //TODO("Stat system call");
}
コード例 #26
0
ファイル: syscall.c プロジェクト: Foshie/Classes
/*
 * Wait for a process to exit.
 * Params:
 *   state->ebx - pid of process to wait for
 * Returns: the exit code of the process,
 *   or error code (< 0) on error
 */
static int Sys_Wait(struct Interrupt_State *state) {
    int exitCode;
    struct Kernel_Thread *kthread = Lookup_Thread(state->ebx, 0);
    if (kthread == 0)
        return -12;

    Enable_Interrupts();
    exitCode = Join(kthread);
    Disable_Interrupts();

    return exitCode;
}
コード例 #27
0
ファイル: userseg.c プロジェクト: khwang18c/CMSC412
/*
 * Destroy a User_Context object, including all memory
 * and other resources allocated within it.
 */
void Destroy_User_Context(struct User_Context *userContext) {
    KASSERT(userContext->refCount == 0);

    /* Free the context's LDT descriptor */
    Free_Segment_Descriptor(userContext->ldtDescriptor);

    /* Free the context's memory */
    Disable_Interrupts();
    Free(userContext->memory);
    Free(userContext);
    Enable_Interrupts();
}
コード例 #28
0
ファイル: floppy.c プロジェクト: Dreamgoing/myGeekos
/*
 * Wait for the controller to issue an interrupt.
 * Must be called with interrupts disabled.
 */
static void Wait_For_Interrupt(void)
{
    KASSERT(!Interrupts_Enabled());

    /* Spin wait */

    s_interruptOccurred = 0;
    Enable_Interrupts();
    while (!s_interruptOccurred) {
	/* FIXME: Could sleep here */
    }
    Disable_Interrupts();
}
コード例 #29
0
ファイル: syscall.c プロジェクト: sinabeuro/geekos5
/*
 * Read a directory entry from an open directory handle.
 * Params:
 *   state->ebx - file descriptor of the directory
 *   state->ecx - user address of struct VFS_Dir_Entry to copy entry into
 * Returns: 0 if successful, error code (< 0) if unsuccessful
 */
static int Sys_ReadEntry(struct Interrupt_State *state)
{
	int rc;
	struct File** fileList = g_currentThread->userContext->fileList;

	Enable_Interrupts();
	//Print("%d, fileList[state->ebx] : %x\n", state->ebx, fileList[state->ebx]);
	rc = Read_Entry(fileList[state->ebx], (struct VFS_File_Stat *)(USER_BASE_ADDR + state->ecx));  /* weak */
	Disable_Interrupts();
	return rc;

    //TODO("ReadEntry system call");
}
コード例 #30
0
/*
 * Create a new user process.
 * Params:
 *   state->ebx - user address of name of executable
 *   state->ecx - length of executable name
 *   state->edx - user address of command string
 *   state->esi - length of command string
 * Returns: pid of process if successful, error code (< 0) otherwise
 */
static int Sys_Spawn(struct Interrupt_State* state)
{
    int retVal = -1;
    char *exeName = NULL;
    char *command = NULL;
    ulong_t exeNameLen = state->ecx + 1; /* +1 to add the 0 NULL later */
    ulong_t commandLen = state->esi + 1; /* +1 to add the 0 NULL later */
    struct Kernel_Thread* kthread = NULL;

    /* get some memory for the exe name and the args */
    exeName = (char*) Malloc(exeNameLen);
    if (exeName == NULL)
        goto memfail;
    command = (char*) Malloc(commandLen);
    if (command == NULL)
        goto memfail;

    memset(exeName, '\0', exeNameLen);
    if(!Copy_From_User(exeName, state->ebx, exeNameLen)){
        retVal = EUNSPECIFIED;
        goto fail;
    }
    memset(command, '\0', commandLen);
    if(!Copy_From_User(command, state->edx, commandLen)) {
        retVal = EUNSPECIFIED;
        goto fail;
    }

    Enable_Interrupts();
    if ((retVal = Spawn(exeName, command, &kthread))) {
        goto fail;
    }
    Disable_Interrupts();

    if (exeName!=NULL)
        Free(exeName);
    if (command!=NULL)
        Free(command);

    return kthread->pid;

memfail:
    retVal = ENOMEM;

fail:
    if(exeName)
        Free(exeName);
    if (command)
        Free(command);
    return retVal;
}