Пример #1
0
void execute_ISR(Interrupt interrupt) {
    int error;

    switch (interrupt) {
        case timer_interrupt: {
            current_pcb->state = interrupted;

            char *PCB_string = PCB_toString(current_pcb, &error);
            printf("Timer interrupt during %s\n", PCB_string);
            free(PCB_string);

            runScheduler(timer_interrupt);
            break;
        }
        case io1_interrupt: {
            current_pcb->state = interrupted;

            printf("I/O 1 Trap request complete.\n");
            runScheduler(io1_interrupt);

            current_pcb->state = running;
            break;
        }
        case io2_interrupt: {
            current_pcb->state = interrupted;

            printf("I/O 2 Trap request complete.\n");
            runScheduler(io2_interrupt);

            current_pcb->state = running;
            break;
        }
        case trap_interrupt: {
            current_pcb->state = interrupted;

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("Trap requested by %s\n", PCB_string);

            execute_TSR(trap);

            break;
        }
        case no_interrupt:
            // This shouldn't happen here.
            break;
    }
}
Пример #2
0
void BasicEngine::run() {
  
  log->record(GreasyLog::devel, "BasicEngine::run", "Entering...");
  
  runScheduler();

  log->record(GreasyLog::devel, "BasicEngine::run", "Exiting...");

}
Пример #3
0
/** 
 * \fn     runSchedulerNotFromSm
 * \brief  Run scheduler due to other events then from SM (static function)
 * 
 * To comply with the SM behavior, this function is used for any case where the
 *    Mgmt-Queues scheduler may have work to do due to events external to the SM.
 * If the queues are not empty, this function runs the scheduler.
*				If the scheduler emptied the queues, update the SM.
 * 
 * \note   
 * \param  pTxMgmtQ - The module's object                                          
 * \return void 
 * \sa     
 */ 
static void runSchedulerNotFromSm (TTxMgmtQ *pTxMgmtQ)
{
	/* If the queues are not empty, run the scheduler. */
	if ( !ARE_ALL_MGMT_QUEUES_EMPTY(pTxMgmtQ->aQueues) )
	{
		runScheduler (pTxMgmtQ);
		
		/* If the queues are now both empty, call the SM with QUEUES_EMPTY event. */
		if ( ARE_ALL_MGMT_QUEUES_EMPTY(pTxMgmtQ->aQueues) )
        {
			mgmtQueuesSM (pTxMgmtQ, SM_EVENT_QUEUES_EMPTY);
        }
	}
}
Пример #4
0
void mutexUnlock(PCB_p pcb, Mutex_p mutex) {
    int error;

    printf("PID %lu: requested unlock on mutex M%lu - ", pcb->PID, mutex->ID);

    if (Mutex_unlock(mutex, pcb)) {
        // The mutex unlock succeeded. Resume process operation.
        printf("succeeded\n");
        pcb->state = running;
    } else {
        // The mutex unlock has failed.
        printf("blocked by PID %lu\n", mutex->key->PID);
        // The process has now been enqueued in the mutex queue, and will get the lock (and thus unlock) when it is its turn.
        // So enqueue PCB back into the ready queue and run the scheduler to dispatch the next process.
        // TODO: Move the enqueue into the scheduler.
        current_pcb->state = waiting;
        current_pcb->PC--;  // Decrement so that the PCB will try to unlock again next time it's run.
        PriorityQ_enqueue(ready_PCBs, current_pcb, &error);
        runScheduler(
                trap_interrupt);   // Current process has been blocked, run scheduler to dispatch the next one.
    }
}
Пример #5
0
/** 
 * \fn     runSchedulerNotFromSm
 * \brief  Run scheduler due to other events then from SM (static function)
 * 
 * To comply with the SM behavior, this function is used for any case where the
 *    Mgmt-Queues scheduler may have work to do due to events external to the SM.
 * If the queues are not empty, this function runs the scheduler.
*				If the scheduler emptied the queues, update the SM.
 * 
 * \note   
 * \param  pTxMgmtQ - The module's object                                          
 * \return void 
 * \sa     
 */ 
static void runSchedulerNotFromSm (TTxMgmtQ *pTxMgmtQ)
{
	TMgmtLinkQ *pLinkQ;
	TI_UINT32 uHlid;

	for (uHlid=0; uHlid<WLANLINKS_MAX_LINKS; uHlid++)
	{
		pLinkQ = &pTxMgmtQ->aMgmtLinkQ[uHlid]; /* Link queues */

		/* If the queues are not empty, run the scheduler. */
		if ( !ARE_LINK_MGMT_QUEUES_EMPTY(pLinkQ->aQueues) )
		{
			runScheduler (pTxMgmtQ);
		
			/* If the queues are now both empty, call the SM with QUEUES_EMPTY event. */
			if ( ARE_LINK_MGMT_QUEUES_EMPTY(pLinkQ->aQueues) )
			{
				mgmtQueuesSM (pTxMgmtQ, uHlid, SM_EVENT_QUEUES_EMPTY);
			}
        }
	}
}
Пример #6
0
/** 
 * \fn     mgmtQueuesSM
 * \brief  The module state-machine (static function)
 * 
 * The SM follows the system management states (see ETxConnState) and the Mgmt queues
 *   status (empty or not), and contorls the Tx queues flow accordingly (mgmt and data queues).
 * For detailed explanation, see the Tx-Path LLD document!
 * 
 * \note   To avoid recursion issues, all SM actions are done at the end of the function, 
 *            since some of them may invoke the SM again.
 * \param  pTxMgmtQ - The module's object                                          
 * \param  eSmEvent - The event to act upon                                          
 * \return void 
 * \sa     txMgmtQ_SetConnState
 */ 
static void mgmtQueuesSM (TTxMgmtQ *pTxMgmtQ, ESmEvent eSmEvent)
{
	ESmState  ePrevState = pTxMgmtQ->eSmState;
	ESmAction eSmAction  = SM_ACTION_NULL;

	switch(eSmEvent)
	{
		case SM_EVENT_CLOSE:
			/* 
			 * Tx link is closed (expected in any state), so disable both mgmt queues  
			 *   and if data-queues are active disable them via txPort module.
			 */
			pTxMgmtQ->eSmState = SM_STATE_CLOSE;
			pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_MGMT]  = TI_FALSE;
			pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_EAPOL] = TI_FALSE;
			if (ePrevState == SM_STATE_OPEN_DATA)
				eSmAction = SM_ACTION_ENABLE_MGMT;
			break;

		case SM_EVENT_MGMT:
			/* 
			 * Only Mgmt packets are permitted (expected from any state):
			 *   - Enable the mgmt queue and disable the Eapol queue.
			 *   - If data-queues are active disable them via txPort (this will run the scheduler).
			 *   - Else run the scheduler (to send mgmt packets if waiting).
			 */
			pTxMgmtQ->eSmState = SM_STATE_MGMT;
			pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_MGMT]  = TI_TRUE;
			pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_EAPOL] = TI_FALSE;
			if (ePrevState == SM_STATE_OPEN_DATA)
				eSmAction = SM_ACTION_ENABLE_MGMT;
			else
				eSmAction = SM_ACTION_RUN_SCHEDULER;
			break;

		case SM_EVENT_EAPOL:
			/* 
			 * EAPOL packets are also permitted (expected in MGMT or CLOSE state), so enable the 
			 *   EAPOL queue and run the scheduler (to send packets from EAPOL queue if waiting).
			 */
			if ( (ePrevState != SM_STATE_CLOSE) && (ePrevState != SM_STATE_MGMT) )
			{
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, "mgmtQueuesSM: Got SmEvent=EAPOL when eSmState=%d\n", ePrevState);
			}
			pTxMgmtQ->eSmState = SM_STATE_EAPOL;
			pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_MGMT]  = TI_TRUE;
			pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_EAPOL] = TI_TRUE;
			eSmAction = SM_ACTION_RUN_SCHEDULER;
			break;

		case SM_EVENT_OPEN:
			/* 
			 * All packets are now permitted (expected in EAPOL state), so if the mgmt-queues
			 *   are empty disable them and enable the data queues via txPort module.
			 */
			if (ePrevState != SM_STATE_EAPOL)
			{
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, "mgmtQueuesSM: Got SmEvent=OPEN when eSmState=%d\n", ePrevState);
			}
			if ( ARE_ALL_MGMT_QUEUES_EMPTY(pTxMgmtQ->aQueues) )
			{
				pTxMgmtQ->eSmState = SM_STATE_OPEN_DATA;
				pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_MGMT]  = TI_FALSE;
				pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_EAPOL] = TI_FALSE;
				eSmAction = SM_ACTION_ENABLE_DATA;
			}
			else
			{
				pTxMgmtQ->eSmState = SM_STATE_OPEN_MGMT;
			}
			break;

		case SM_EVENT_QUEUES_EMPTY:
			/* 
			 * The mgmt-queues are empty, so if in OPEN_MGMT state disable the 
			 *   mgmt-queues and enable the data-queues via txPort module.
			 */
			if (ePrevState == SM_STATE_OPEN_MGMT)
			{
				pTxMgmtQ->eSmState = SM_STATE_OPEN_DATA;
				pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_MGMT]  = TI_FALSE;
				pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_EAPOL] = TI_FALSE;
				eSmAction = SM_ACTION_ENABLE_DATA;
			}
			else
			{
				/* This may happen so it's just a warning and not an error. */
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_WARNING, "mgmtQueuesSM: Got SmEvent=QUEUES_EMPTY when eSmState=%d\n", ePrevState);
			}
			break;

		case SM_EVENT_QUEUES_NOT_EMPTY:

			/* A packet was inserted to the mgmt-queues */

			/* 
			 * If in OPEN_DATA state, enable mgmt-queues and disable data-queues via txPort module.
			 *
			 * Note: The scheduler is not run here because the txPort will call
			 *   txMgmtQueue_wakeAll() which will run the scheduler.
			 */
			if (ePrevState == SM_STATE_OPEN_DATA)
			{
				pTxMgmtQ->eSmState = SM_STATE_OPEN_MGMT;
				pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_MGMT]  = TI_TRUE;
				pTxMgmtQ->aQueueEnabledBySM[QUEUE_TYPE_EAPOL] = TI_TRUE;
				eSmAction = SM_ACTION_ENABLE_MGMT;
			}

			/* 
			 * If in MGMT or EAPOL state, run the scheduler to transmit the packet.
			 */
			else if ( (ePrevState == SM_STATE_MGMT) || (ePrevState == SM_STATE_EAPOL) )
			{
				eSmAction = SM_ACTION_RUN_SCHEDULER;
			}

			else
			{
				/* This may happen so it's just a warning and not an error. */
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_WARNING, "mgmtQueuesSM: Got SmEvent=QUEUES_NOT_EMPTY when eSmState=%d\n", ePrevState);
			}
			break;

		default:
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, "mgmtQueuesSM: Unknown SmEvent = %d\n", eSmEvent);
			break;
	}

TRACE6( pTxMgmtQ->hReport, REPORT_SEVERITY_INFORMATION, "mgmtQueuesSM: <currentState = %d, event = %d> --> nextState = %d, action = %d, MgmtQueEnbl=%d, EapolQueEnbl=%d\n", ePrevState, eSmEvent, pTxMgmtQ->eSmState, eSmAction, pTxMgmtQ->aQueueEnabledBySM[0], pTxMgmtQ->aQueueEnabledBySM[1]);

	/* 
	 * Execute the required action. 
	 * Note: This is done at the end of the SM because it may start a sequence that will call the SM again!
	 */
	switch (eSmAction)
	{
		case SM_ACTION_NULL:
			break;

		case SM_ACTION_ENABLE_DATA:
			txPort_enableData(pTxMgmtQ->hTxPort);
			break;

		case SM_ACTION_ENABLE_MGMT:
			txPort_enableMgmt(pTxMgmtQ->hTxPort);
			break;

		case SM_ACTION_RUN_SCHEDULER:
			runScheduler(pTxMgmtQ);
			break;

		default:
TRACE1(pTxMgmtQ->hReport, REPORT_SEVERITY_ERROR, ": Unknown SmAction = %d\n", eSmAction);
			break;
	}
}
Пример #7
0
void execute_TSR(TSR routine) {
    int error;

    switch (routine) {
        case io1_trap: {
            current_pcb->state = waiting;
            FIFOq_enqueue(io1_PCBs, current_pcb, &error);

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("I/O 1 Trap requested by %s\n", PCB_string);
            free(PCB_string);

            runScheduler(trap_interrupt);
            break;
        }
        case io2_trap: {
            current_pcb->state = waiting;
            FIFOq_enqueue(io2_PCBs, current_pcb, &error);

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("I/O 2 Trap requested by %s\n", PCB_string);
            free(PCB_string);

            runScheduler(trap_interrupt);
            break;
        }
        case terminate_trap: {
            current_pcb->state = terminated;
            current_pcb->termination = time(NULL);
            FIFOq_enqueue(terminated_PCBs, current_pcb, &error);
            processes_terminated++;

            // Unlock any mutexes that this terminated PCB may have.
            if (current_pcb->type == consumer || current_pcb->type == producer || current_pcb->type == resource_user_A) {
                Mutex_remove(current_pcb->mutex_A, current_pcb);
            } else  if (current_pcb->type == resource_user_B) {
                Mutex_remove(current_pcb->mutex_B, current_pcb);
            }

            char* PCB_string = PCB_toString(current_pcb, &error);
            printf("Terminated process: %s\n", PCB_string);
            free(PCB_string);
            current_pcb = NULL;

            runScheduler(trap_interrupt);
            break;
        }
        case mutex_lock_trap:
            if (current_pcb->type == resource_user_A) {
                // If this is a resource_user "A" process lock mutex A then B.
                if (!Mutex_Is_Locked(current_pcb->mutex_A) || current_pcb->mutex_A->key != current_pcb) {
                    mutexLock(current_pcb, current_pcb->mutex_A);
                } else if (!Mutex_Is_Locked(current_pcb->mutex_B) || current_pcb->mutex_B->key != current_pcb) {
                    mutexLock(current_pcb, current_pcb->mutex_B);
                }
            } else if (current_pcb->type == resource_user_B) {
                // If this is a resource_user "B" process then lock A then B if no-deadlock, and B then A if deadlock.
                if (!deadlock) {
                    if (!Mutex_Is_Locked(current_pcb->mutex_A) || current_pcb->mutex_A->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_A);
                    } else if (!Mutex_Is_Locked(current_pcb->mutex_B) || current_pcb->mutex_B->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_B);
                    }
                } else {
                    if (!Mutex_Is_Locked(current_pcb->mutex_B) || current_pcb->mutex_B->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_B);
                    } else if (!Mutex_Is_Locked(current_pcb->mutex_A) || current_pcb->mutex_A->key != current_pcb) {
                        mutexLock(current_pcb, current_pcb->mutex_A);
                    }
                }
            } else {
                mutexLock(current_pcb, current_pcb->mutex_A);
            }
            break;
        case mutex_unlock_trap:
            if (current_pcb->type == resource_user_A) {
                // If this is a resource_user "A" process unlock mutex B then A.
                if (Mutex_Is_Locked(current_pcb->mutex_B)) {
                    mutexUnlock(current_pcb, current_pcb->mutex_B);
                } else if (Mutex_Is_Locked(current_pcb->mutex_A)) {
                    mutexUnlock(current_pcb, current_pcb->mutex_A);
                }
            } else if (current_pcb->type == resource_user_B) {
                // If this is a resource_user "B" process then unlock B then A if no-deadlock, and A then B if deadlock.
                if (!deadlock) {
                    if (Mutex_Is_Locked(current_pcb->mutex_B)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_B);
                    } else if (Mutex_Is_Locked(current_pcb->mutex_A)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_B);
                    }
                } else {
                    if (Mutex_Is_Locked(current_pcb->mutex_A)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_A);
                    } else if (Mutex_Is_Locked(current_pcb->mutex_B)) {
                        mutexUnlock(current_pcb, current_pcb->mutex_B);
                    }
                }
            } else {
                mutexUnlock(current_pcb, current_pcb->mutex_A);
            }
            break;
        case condition_signal_and_wait_trap:
            printf("PID %lu: sent signal on condition %lu\n", current_pcb->PID, current_pcb->conditional_variable->ID);

            PCB_p returnedPCB = Condition_signal(current_pcb->conditional_variable, current_pcb);
            if (returnedPCB != NULL) {
                returnedPCB->state = ready;
                PriorityQ_enqueue(ready_PCBs, returnedPCB, &error);
            }

            printf("PID %lu: requested wait on condition %lu with mutex M%lu\n", current_pcb->PID,
                   current_pcb->conditional_variable->ID, current_pcb->mutex_A->ID);
            Condition_wait(current_pcb->conditional_variable, current_pcb->mutex_A, current_pcb);
            current_pcb->state = waiting;
            // Don't enqueue the current PCB as now it's waiting.

            // Interrupt this PCB and run the scheduler to dispatch the next process.
            runScheduler(trap_interrupt);
            break;
        case no_trap:
            // This shouldn't happen here.
            break;
    }
}