Beispiel #1
0
/**
 * @brief Puts a task to sleep on the sleep queue until the next
 * event is signalled for the device.
 *
 * @param dev  Device number.
 */
int dev_wait(unsigned int dev __attribute__((unused)))
{
	disable_interrupts();

  	tcb_t* cur_tcb = get_cur_tcb();
    if(cur_tcb->holds_lock !=0){
        return -EHOLDSLOCK;
    }
 	tcb_t* sleep_queue = devices[dev].sleep_q;
  	if(sleep_queue == 0)
	{
		devices[dev].sleep_q = cur_tcb;
		devices[dev].sleep_q -> sleep_queue = 0;
	}
	else{
		while(sleep_queue -> sleep_queue !=0)
			sleep_queue = sleep_queue -> sleep_queue;
		sleep_queue->sleep_queue = cur_tcb;
		sleep_queue = sleep_queue-> sleep_queue;
		sleep_queue -> sleep_queue =0;
	}

  	dispatch_sleep();
	enable_interrupts();
	
	return 0;
}
Beispiel #2
0
int mutex_lock_syscall(int mutex  __attribute__((unused)))
{
	//printf("mutex_lock, %d\n", mutex);
	// if mutex invalid
	if (mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable == 1) {
		return EINVAL;
	}
	
	if (gtMutex[mutex].pHolding_Tcb == get_cur_tcb())
		return EDEADLOCK;
	
	// if blocked
	if (gtMutex[mutex].bLock == 1) {
		tcb_t** tmp = &(gtMutex[mutex].pSleep_queue);
		while (1) {
			if (*tmp == (void *)0) {
				gtMutex[mutex].pSleep_queue = runqueue_remove(get_cur_prio());
				break;
			}
			if((*tmp)->sleep_queue == (void *)0) {
				(*tmp)->sleep_queue = runqueue_remove(get_cur_prio());
				((*tmp)->sleep_queue) = (void *)0;
				break;
			}
			tmp = (tcb_t **)&((*tmp)->sleep_queue);
		}
		//printf("blocked!!!!!!!!!\n");
		//printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio);
		dispatch_save();
	}

	// if not blocked		
	gtMutex[mutex].bLock = 1;
	gtMutex[mutex].pHolding_Tcb = get_cur_tcb();
	
	//printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio);
	//printf("mutex sleep queue\n");
	/*
	tcb_t* tmp = gtMutex[mutex].pSleep_queue;
	while (tmp != (void *)0) {
		printf("sleep %d\n", tmp->native_prio);
		tmp = tmp->sleep_queue;
	}
	*/
	return 0;

}
Beispiel #3
0
int mutex_unlock(int mutex_num)
{
	if(debug_enabled1 == 1) printf("\tmutex::mutex_unlock:: id= %d tcb = %d\n", mutex_num, get_cur_tcb()->cur_prio);
	
	disable_interrupts();
	
	//check for valid mutex number
	if(mutex_num < 0 || mutex_num > mutexID) return -EINVAL;
	
	//mutex is valid
	mutex_t* mutex = &gtMutex[mutex_num-1]; //mutex we are referencing
	
	//check if we own this mutex
	if(mutex->pHolding_Tcb != get_cur_tcb()) return -EPERM;

	
	get_cur_tcb()->holds_lock--;
	
	//if the sleep queue is empty
	if(mutex->pSleep_queue == NULL_TCB)
	{
		mutex->bAvailable =	TRUE;
		mutex->bLock = 		FALSE;
		mutex->pHolding_Tcb = 	NULL_TCB;
	}
	//queue not empty
	else
	{
		//next is up
		tcb_t* next = mutex->pSleep_queue;
		
		//mutex held by next
		mutex->pSleep_queue = next->sleep_queue;
		mutex->pHolding_Tcb = next;
		
		//next holds mutex
		next->sleep_queue = NULL_TCB;
		next->holds_lock++;
		
		//next is ready to run
		runqueue_add(next, next->cur_prio);
	}

	enable_interrupts();
	return 0; //success
}
Beispiel #4
0
int mutex_lock(int mutex_num)
{
	if(debug_enabled1 == 1) printf("\tmutex::mutex_lock:: lock(%d) by tcb %d\n", mutex_num, get_cur_tcb()->cur_prio);
	
	disable_interrupts();
	
	//check for valid mutex number
	if(mutex_num < 0 || mutex_num > mutexID) return -EINVAL;
	
	//mutex is valid
	mutex_t* mutex = &gtMutex[mutex_num-1]; //mutex we are referencing

	//mutex is available
	if(mutex->bAvailable == TRUE) {
		//acquire  mutex
		mutex->bLock = 		TRUE;
		mutex->bAvailable = 	FALSE;
		mutex->pHolding_Tcb = 	get_cur_tcb();
		get_cur_tcb()->holds_lock++;
		enable_interrupts();
		return 0; //success
	}
	//mutex is not available
	else
	{
		//if current task is already holding it
		if(mutex->pHolding_Tcb == get_cur_tcb()) return -EDEADLOCK;
		
		//if the sleep queue is empty
		if( mutex->pSleep_queue == NULL_TCB ) mutex->pSleep_queue = get_cur_tcb();
		//else sleep queue is not empty
		else
		{
			//add to the end of the queue
			tcb_t* t = mutex->pSleep_queue;
			while(t->sleep_queue != NULL_TCB) t = t->sleep_queue;
			t->sleep_queue = get_cur_tcb();
		}
	}

	//sleep and wait..`
	dispatch_sleep();
	enable_interrupts();
	return 0; //success
}
Beispiel #5
0
/**
 * @brief Puts a task to sleep on the sleep queue until the next
 * event is signalled for the device.
 *
 * @param dev  Device number.
 */
void dev_wait(unsigned int dev )
{

	if(debug_enabled == 1)puts("dev_wait++\n");
	//add to the sleep queue
	tcb_t* sleep_me = get_cur_tcb();
	sleep_me->sleep_queue = devices[dev].sleep_queue;
	devices[dev].sleep_queue = sleep_me;
	if(debug_enabled == 1)printf("dev_wait...dev = %d:::new = (prio) %d:::old = %x\n", dev, (unsigned)devices[dev].sleep_queue->cur_prio, (unsigned)devices[dev].sleep_queue->sleep_queue);

}
Beispiel #6
0
int mutex_lock(int mutex  __attribute__((unused)))
{
    tcb_t* temp;
    
    disable_interrupts();

    // if the provided mutex identifier if invalid
    if(mutex > OS_NUM_MUTEX ||
            gtMutex[mutex].bAvailable == TRUE) {
        
        enable_interrupts();
        return -EINVAL;
    
    } 

    if(gtMutex[mutex].pHolding_Tcb == get_cur_tcb()) {

        // if the current task is already holding the lock
        enable_interrupts();
        return -EDEADLOCK;

    } else {
        if(gtMutex[mutex].bLock == 0) {
            // if the lock is not been locked
            // set lock status and holding tcb
            gtMutex[mutex].bLock = 1;
            gtMutex[mutex].pHolding_Tcb = get_cur_tcb();
            get_cur_tcb()->holds_lock = 1;
            #ifdef HLP
            get_cur_tcb()->cur_prio = 0;
            #endif // HLP
            gtMutex[mutex].pSleep_queue = 0;
            enable_interrupts();
            return 0;

        } else {
            // if the lock is been locked
            // move the current tack to mutex sleeping queue
            temp = gtMutex[mutex].pSleep_queue;

            if (temp == 0)
            {
                gtMutex[mutex].pSleep_queue = get_cur_tcb();
            } else {
                // put current tcb at the end of the mutex sleeping queue
                while((temp->sleep_queue) != 0) {
                    temp = temp->sleep_queue;
                }
                temp->sleep_queue = get_cur_tcb();
            }

            // context switch to another task
            dispatch_sleep();
        }
    }

    // the function cannot get here
    return 1; 
}
/*                                                                              
------------------------------------------------                                
Function: mutex_unlock                                                         
Description:                                                                    
Unlocks the mutex and assigns lock to next-in-queue.
If queue is empty, it simply unlocks the mutex
------------------------------------------------                                
*/     
int mutex_unlock(int mutex)
{
	tcb_t* curr_tcb;
	tcb_t* temp_tcb;

	curr_tcb = get_cur_tcb();

	if (mutex<1 || (gtMutex[mutex-1].bAvailable!=1)){
		return -EINVAL;
	}

	if(curr_tcb != gtMutex[mutex-1].pHolding_Tcb){
		return -EPERM;
	}

	gtMutex[mutex-1].pHolding_Tcb->holds_lock = 0;
	gtMutex[mutex-1].bLock = 0;
	curr_tcb->cur_prio = curr_tcb->native_prio;		

	/*Changing lock status in current_tcb*/
	if(gtMutex[mutex-1].pSleep_queue!=0){
		/* Updating status of next in line for lock*/
		/* If queue is not single-element */
		runqueue_add(gtMutex[mutex-1].pSleep_queue, gtMutex[mutex-1].pSleep_queue->native_prio);
		if(gtMutex[mutex-1].pSleep_queue->sleep_queue!=0){
			temp_tcb = gtMutex[mutex-1].pSleep_queue;
			gtMutex[mutex-1].pSleep_queue = temp_tcb->sleep_queue;
			temp_tcb->sleep_queue = 0;
		}
		else {
			/* If queue is single-element */
			temp_tcb = gtMutex[mutex-1].pSleep_queue;
			gtMutex[mutex-1].pSleep_queue = 0;
			temp_tcb->sleep_queue = 0;
			rear[mutex-1] = 0;		
		}
		/* Updating status of mutex */
		gtMutex[mutex-1].bLock = 1;
		gtMutex[mutex-1].pHolding_Tcb = temp_tcb;
		gtMutex[mutex-1].pHolding_Tcb->holds_lock = 1;		
	}
	else {
		/* If sleep queue is empty, unlock mutex*/
		gtMutex[mutex-1].bLock = 0;
		gtMutex[mutex-1].pHolding_Tcb = 0;
	}
	return 0; 
}
Beispiel #8
0
int event_wait(unsigned int dev)
{
  tcb_t *task = get_cur_tcb();

  if (dev >= NUM_DEVICES)
  	return -EINVAL;

  if (task->holds_lock)
  	return -EDEADLOCK;

  disable_interrupts();
  dev_wait(dev);
  enable_interrupts();

  return 1;
}
Beispiel #9
0
int mutex_unlock_syscall(int mutex  __attribute__((unused)))
{
	
	// if mutex invalid
	if (mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable == 1) {
		return EINVAL;
	}

	if (gtMutex[mutex].pHolding_Tcb != get_cur_tcb())
		return EPERM;
	
	// first tcb in pSleep_queue
	tcb_t* nextTcb = gtMutex[mutex].pSleep_queue;

	//if (nextTcb != (void *)0) {
	// set pSleep_queue to next one
	// gtMutex[mutex].pSleep_queue = (gtMutex[mutex].pSleep_queue)->sleep_queue;

	// if there are no other tcbs blocked
	if (nextTcb == (void *)0) {
		gtMutex[mutex].bLock = 0;
		gtMutex[mutex].pHolding_Tcb = (void *)0;
		
		// test
		//printf("mutex_unlock, %d\n", mutex);
		//printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio);

	}
	else {
		gtMutex[mutex].pSleep_queue = (gtMutex[mutex].pSleep_queue)->sleep_queue;
		nextTcb->sleep_queue = (void *)0;
		gtMutex[mutex].pHolding_Tcb = nextTcb;
		runqueue_add(nextTcb, nextTcb->native_prio);
		//printf("mutex_unlock, change to %d\n", mutex);

		//printf("mutex holding tcb: %d\n", (gtMutex[mutex].pHolding_Tcb)->native_prio);
		//printf("mutex sleep queue\n");
		/*
		tcb_t* tmp = gtMutex[mutex].pSleep_queue;
		while (tmp != (void *)0) {
			printf("sleep %d\n", tmp->native_prio);
			tmp = tmp->sleep_queue;	
		}
		*/
	}
	return 0;
}
Beispiel #10
0
int mutex_lock(int mutex  __attribute__((unused)))
{
	disable_interrupts();

	/* invalid mutex id, return error code */
	if(mutex < 0 || mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable){
		enable_interrupts();
		return -EINVAL;
	}
	else{
		tcb_t* cur_tcb = get_cur_tcb();
		/* current task is already holding the lock, return error code */
		if(cur_tcb == gtMutex[mutex].pHolding_Tcb){
			enable_interrupts();
			return -EDEADLOCK;
		}
		/* lock is holding by others, put current task to sleep */
		else if(gtMutex[mutex].bLock){
			/* put the task into sleep queue */
			if(gtMutex[mutex].pSleep_queue == NULL){
				gtMutex[mutex].pSleep_queue = cur_tcb;
				cur_tcb->sleep_queue = NULL;
			}
			else{
				tcb_t* tmp = gtMutex[mutex].pSleep_queue;
				while(tmp->sleep_queue != NULL){
					tmp = tmp->sleep_queue;
				}
				tmp->sleep_queue = cur_tcb;
				cur_tcb->sleep_queue = NULL;
			}
			/* sleep & context switch */
			dispatch_sleep();
		}
		/* no one's holding it, get go! */
		gtMutex[mutex].pHolding_Tcb = cur_tcb;
		gtMutex[mutex].bLock = TRUE;

		cur_tcb->holds_lock ++;
		//cur_tcb->native_prio = cur_tcb->cur_prio;
		//cur_tcb->cur_prio = 0;

		enable_interrupts();
		return 0;
	}
}
Beispiel #11
0
/**
 * @brief Puts a task to sleep on the sleep queue until the next
 * event is signalled for the device.
 *
 * @param dev  Device number.
 */
int dev_wait(unsigned int dev __attribute__((unused)))
{
  tcb_t* cur_tcb;
  tcb_t* sleepQ;

  disable_interrupts();

  // get current tcb and sleep devices on sleep queue
  cur_tcb = get_cur_tcb();
  sleepQ = devices[dev].sleep_queue;
  // if task is holding a lock, return error
  if (cur_tcb->holds_lock != 0)
    return -EHOLDSLOCK;
  // add cur_tcb to head of sleep queue linked list
  devices[dev].sleep_queue = cur_tcb;
  cur_tcb->sleep_queue = sleepQ;
  // dispatch to next task
  dispatch_sleep();
  return 0;
}
/*                                                                              
------------------------------------------------                                
Function: mutex_lock                                                         
Description:                                                                    
Locks the mutex if no process currently holds the 
mutex, else puts the current process in sleep queue.
------------------------------------------------                                
*/     
int mutex_lock(int mutex)
{	
	tcb_t* cur_tcb;

	/*Getting currrently running TCB*/
	cur_tcb = get_cur_tcb();		
	
	if (mutex<1 || mutex>OS_NUM_MUTEX || (gtMutex[mutex-1].bAvailable!=1)) {
		return -EINVAL;
	}
	if (gtMutex[mutex-1].pHolding_Tcb == cur_tcb) {
		return -EDEADLOCK;
	}

	/*Locking the current mutex, if available*/
	if (gtMutex[mutex-1].bLock == 0) {
		gtMutex[mutex-1].pHolding_Tcb = cur_tcb;
		gtMutex[mutex-1].bLock = 1;
		gtMutex[mutex-1].pHolding_Tcb->holds_lock = 1;
		cur_tcb->cur_prio = 0;		
		return 0;
	}
	/* adding process to mutex sleep queue */
	else {		
		/* If initial sleep queue is empty*/		
		if (gtMutex[mutex-1].pSleep_queue == 0){
			cur_tcb->sleep_queue = 0;
			gtMutex[mutex-1].pSleep_queue = cur_tcb;
			rear[mutex-1] = cur_tcb;
		} 
		else {
			/* Attaching current head to new del_tcb and updating head*/
			cur_tcb->sleep_queue = 0;
			rear[mutex-1]->sleep_queue = cur_tcb;
			rear[mutex-1] = cur_tcb;
		}	
		dispatch_sleep();		
		return 0; 
	}
	return 0;
}
Beispiel #13
0
/**
 * @brief Puts a task to sleep on the sleep queue until the next
 * event is signalled for the device.
 *
 * @param dev  Device number.
 */
int dev_wait(unsigned int dev)
{   
    disable_interrupts();
    // get the current task's tcb, no need to handle fault dev
    tcb_t* current_task_tcb = get_cur_tcb();

    // check if the current task holds any mutex
    if (current_task_tcb->cur_prio == HLP_PRIO) {
        printf("current taks has mutex on hand, cannot sleep!\n");
        return EHOLDSLOCK;
    }

    // insert the task on the head of device sleep queue
    current_task_tcb->sleep_queue = devices[dev].sleep_queue;
    devices[dev].sleep_queue = current_task_tcb;

    // make it sleep
    dispatch_sleep();
    
    return 0;
}
Beispiel #14
0
int mutex_unlock(int mutex  __attribute__((unused)))
{
    if (mutex >= OS_NUM_MUTEX) {
        return EINVAL;
    }
    disable_interrupts();
    tcb_t* cur_tcb = get_cur_tcb();
    mutex_t cur_mutex = gtMutex[mutex];

    /* check if provided mutex identifier is valid */
    if (!cur_mutex.bAvailable)
    {
        enable_interrupts();
        return EINVAL;
    }

    /* check if current task is holding the mutex */
    if (cur_tcb != cur_mutex.pHolding_Tcb)
    {
        enable_interrupts();
        return EPERM;
    }

    cur_mutex.pHolding_Tcb = 0;

    /* add first task in sleep queue to run queue */
    if (cur_mutex.pSleep_queue != 0)
    {
        tcb_t* h_tcb = cur_mutex.pSleep_queue;
        cur_mutex.pHolding_Tcb = h_tcb;
        runqueue_add(h_tcb, h_tcb->cur_prio);
        cur_mutex.pSleep_queue = h_tcb->sleep_queue;
        cur_mutex.bLock = 1;
    }
    cur_mutex.bLock = 0;
    enable_interrupts();
    return 0;
}
Beispiel #15
0
int mutex_unlock(int mutex  __attribute__((unused)))
{
	disable_interrupts();

	/* invalid mutex id, return error code */
	if(mutex < 0 || mutex >= OS_NUM_MUTEX || gtMutex[mutex].bAvailable){
		enable_interrupts();
		return -EINVAL;
	}
	else{
		tcb_t* cur_tcb = get_cur_tcb();
		/* current task does not hold the lock, return error code */
		if(cur_tcb != gtMutex[mutex].pHolding_Tcb){
			enable_interrupts();
			return -EPERM;
		}
		else{
			/* release the lock */
			gtMutex[mutex].pHolding_Tcb = NULL;
			gtMutex[mutex].bLock = FALSE;
			/* there is task waiting in the sleep queue, make it able to run */
			if(gtMutex[mutex].pSleep_queue != NULL){
				tcb_t* tmp = gtMutex[mutex].pSleep_queue;
				gtMutex[mutex].pSleep_queue = tmp->sleep_queue;
				tmp->sleep_queue = NULL;

					runqueue_add(tmp, tmp->cur_prio);
			}
			/* decrease the num of locks hold by current task by one */
			if(cur_tcb->holds_lock != 0)
				cur_tcb->holds_lock --;
			

			enable_interrupts();
			return 0;
		}
	}
}
Beispiel #16
0
int mutex_lock(int mutex  __attribute__((unused)))
{ 
  // Get the current task
  tcb_t* cur_tcb = get_cur_tcb();
  mutex_t* cur_mutex = &(gtMutex[mutex]);
 
  // Check if mutex is in range
  if((mutex <0) || (mutex >= OS_NUM_MUTEX)) return EINVAL;

  // Check if deadlock error
  if(cur_tcb == gtMutex[mutex].pHolding_Tcb) return EDEADLOCK;

  // Disable interrupts
  disable_interrupts();

  // If mutex is locked (blocked), wait until freed up by sleeping
  while(cur_mutex->bLock == 1){
    // Enable interrupts
    enable_interrupts();
    
    dispatch_sleep();
    
    //Disable interrupts
    disable_interrupts();
  }
  
  // Set holding Tcb to current task, set bLock = TRUE, give curr\ent task highest priority, set cur tasks's "holds_lock" val to 1
  cur_mutex->bLock = 1;
    cur_mutex->pHolding_Tcb = cur_tcb;
    cur_tcb->cur_prio = highest_prio();
    cur_tcb->holds_lock = 1;

    // Enable Interrupts
    enable_interrupts();

    return 0;
}
Beispiel #17
0
int mutex_lock(int mutex  __attribute__((unused)))
{
    disable_interrupts();
    tcb_t* cur_tcb = get_cur_tcb();
    uint8_t cur_prio = get_cur_prio();
    tcb_t* sleep_queue, *temp;
    mutex_t *cur_mutex = &(gtMutex[mutex]);


    /* check if provided mutex identifier is valid */
    if(mutex > num_mutices)
    {
        enable_interrupts();
        return EINVAL;
    }

    /* check if current task is holding the mutex */
    if(cur_mutex->pHolding_Tcb == cur_tcb)
    {
        enable_interrupts();
        return EDEADLOCK;
    }


    /* check if sleep queue is empty */
    if(cur_mutex->pSleep_queue == 0)
    {
        cur_mutex->pSleep_queue = cur_tcb;
        cur_tcb->sleep_queue = 0;
    }

    /* insert task at appropriate location in sleep queue */
    else
    {
        sleep_queue = cur_mutex->pSleep_queue;
        temp = sleep_queue;

        /* insert at front of the list */
        if(cur_prio < (sleep_queue->cur_prio))
        {
            cur_tcb->sleep_queue = cur_mutex->pSleep_queue;
            cur_mutex->pSleep_queue = cur_tcb;
        }
        else
        {
            sleep_queue = sleep_queue->sleep_queue;
            while(sleep_queue != 0)
            {
                if(cur_prio < (sleep_queue->cur_prio))
                {
                    cur_tcb->sleep_queue = sleep_queue;
                    temp->sleep_queue = cur_tcb;
                    break;
                }
                temp = sleep_queue;
                sleep_queue = sleep_queue->sleep_queue;
            }
        }
    }

    disable_interrupts();
    dispatch_sleep();
    enable_interrupts();

    return 0;
}
Beispiel #18
0
int mutex_unlock(int mutex  __attribute__((unused)))
{
    tcb_t* temp;

    disable_interrupts();

    // if the provided mutex identifier if invalid
    if(mutex > OS_NUM_MUTEX
            || gtMutex[mutex].bAvailable == TRUE) {
        
        enable_interrupts();
        return -EINVAL;
    
    } 

    if(gtMutex[mutex].pHolding_Tcb != get_cur_tcb()) {
        
        // if the urrent task does not hold the mutex
        enable_interrupts();
        return -EPERM;
    
    } else {
        temp = gtMutex[mutex].pHolding_Tcb;
        temp->holds_lock = 0;
        #ifdef HLP
            temp->cur_prio = temp->native_prio;
        #endif // HLP

        // if there is no element in sleep queue
        if(gtMutex[mutex].pSleep_queue == 0) {
            gtMutex[mutex].bLock = 0;
            gtMutex[mutex].pHolding_Tcb = 0;
            enable_interrupts();
            return 0;
        } else {

            // if the sleep queue have tasks waiting for the mutex

            // first tcb in sleeping queue gets the mutex
            gtMutex[mutex].pHolding_Tcb = gtMutex[mutex].pSleep_queue;
            // move the head of mutex sleeping queue to next
            gtMutex[mutex].pSleep_queue = gtMutex[mutex].pSleep_queue->sleep_queue;
            // clear the sleeping queue of the holding tcb
            gtMutex[mutex].pHolding_Tcb->sleep_queue = 0;

            gtMutex[mutex].pHolding_Tcb->holds_lock = 1;
            #ifdef HLP
                gtMutex[mutex].pHolding_Tcb->cur_prio = 0;
            #endif // HLP

            // put the wake up task into runqueue
            runqueue_add(gtMutex[mutex].pHolding_Tcb, gtMutex[mutex].pHolding_Tcb->cur_prio);
        
            // check the wake up task's priority and current running task's priority
            if(highest_prio() < get_cur_prio()) {
                // switch to the highest task
                dispatch_save();

            } else {
                // stay the same
                enable_interrupts();
                return 0;
            }
        }
    }

    // the function will not get here
	return 1; 
}