示例#1
0
文件: mutex.c 项目: 153633/embd_lab4
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;

}
示例#2
0
/**
 * @brief Context switch to the highest priority task that is not this task -- 
 * and save the current task but don't mark is runnable.
 *
 * There is always an idle task to switch to.
 */
void dispatch_sleep(void)
{
	tcb_t *dest, *temp;
	temp = cur_tcb;
	uint8_t cp = get_cur_prio(); /* i.e task that was just put to sleep */
	uint8_t hp = highest_prio(); /* next task to run */

	/* Run idle task if there are no other */
	if(cp == hp)
		dest = runqueue_remove(IDLE_PRIO);
	else
		dest = runqueue_remove(hp);

	/* Set cur_tcb to the task that we are about to run */
	cur_tcb = dest;
	
	/* Set the cur_kstack var of the task that we are about to run */
	cur_kstack = (int)dest->kstack_high;
	
	ctx_switch_full(&(dest->context), &(temp->context));
}
示例#3
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; 
}
示例#4
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;
}