/* * ======== Semaphore_pendTimeout ======== * called by Clock when timeout for a semaphore expires */ Void Semaphore_pendTimeout(UArg arg) { UInt hwiKey; Semaphore_PendElem *elem = (Semaphore_PendElem *)arg; hwiKey = Hwi_disable(); /* Verify that Semaphore_post() hasn't already occurred */ if (elem->pendState == Semaphore_PendState_CLOCK_WAIT) { /* remove task's qElem from semaphore queue */ Queue_remove((Queue_Elem *)elem); elem->pendState = Semaphore_PendState_TIMEOUT; /* * put task back into readyQ * No need for Task_disable/restore sandwich since this * is called within Swi thread */ Task_unblockI(elem->tpElem.task, hwiKey); } Hwi_restore(hwiKey); }
/* * ======== Event_pendTimeout ======== * called by Clock when timeout for a event expires */ Void Event_pendTimeout(UArg arg) { UInt hwiKey; Event_PendElem *elem = (Event_PendElem *)xdc_uargToPtr(arg); hwiKey = Hwi_disable(); /* * Verify that Event_post() hasn't already serviced this qElem. */ if (elem->pendState == Event_PendState_CLOCK_WAIT) { /* remove eventElem from event_Elem queue */ Queue_remove((Queue_Elem *)elem); elem->pendState = Event_PendState_TIMEOUT; /* * put task back into readyQ * No need for Task_disable/restore sandwich since this * is called within Swi (or Hwi) thread */ Task_unblockI(elem->tpElem.task, hwiKey); } Hwi_restore(hwiKey); }
/* * ======== Task_unblock ======== */ Void Task_unblock(Task_Object *tsk) { UInt hwiKey; hwiKey = Hwi_disable(); Task_unblockI(tsk, hwiKey); Hwi_restore(hwiKey); }
/* * ======== Event_post ======== */ Void Event_post(Event_Object *event, UInt eventId) { UInt tskKey, hwiKey; Event_PendElem *elem; Queue_Handle pendQ; Assert_isTrue((eventId != 0), Event_A_nullEventId); Log_write3(Event_LM_post, (UArg)event, (UArg)event->postedEvents, (UArg)eventId); pendQ = Event_Instance_State_pendQ(event); /* atomically post this event */ hwiKey = Hwi_disable(); /* or in this eventId */ event->postedEvents |= eventId; /* confirm that ANY tasks are pending on this event */ if (Queue_empty(pendQ)) { Hwi_restore(hwiKey); return; } tskKey = Task_disable(); /* examine pendElem on pendQ */ elem = (Event_PendElem *)Queue_head(pendQ); /* check for match, consume matching eventIds if so. */ elem->matchingEvents = Event_checkEvents(event, elem->andMask, elem->orMask); if (elem->matchingEvents != 0) { /* remove event elem from elem queue */ Queue_remove((Queue_Elem *)elem); /* mark the Event as having been posted */ elem->pendState = Event_PendState_POSTED; /* disable Clock object */ if (BIOS_clockEnabled && (elem->tpElem.clock != NULL)) { Clock_stop(elem->tpElem.clock); } /* put task back into readyQ */ Task_unblockI(elem->tpElem.task, hwiKey); } Hwi_restore(hwiKey); /* context switch may occur here */ Task_restore(tskKey); }
/* * ======== Task_sleepTimeout ======== * called by Clock when timeout for a Task_sleep() expires */ Void Task_sleepTimeout(UArg arg) { UInt hwiKey; Task_PendElem *elem = (Task_PendElem *)xdc_uargToPtr(arg); hwiKey = Hwi_disable(); /* * put tsk back into readyQ * No need for Task_disable/restore sandwich since this * is called within Swi (or Hwi) thread */ Task_unblockI(elem->task, hwiKey); Hwi_restore(hwiKey); }
/* * ======== Semaphore_post ======== */ Void Semaphore_post(Semaphore_Object *sem) { UInt tskKey, hwiKey; Semaphore_PendElem *elem; Queue_Handle pendQ; /* Event_post will do a Log_write, should we do one here too? */ Log_write2(Semaphore_LM_post, (UArg)sem, (UArg)sem->count); pendQ = Semaphore_Instance_State_pendQ(sem); hwiKey = Hwi_disable(); if (Queue_empty(pendQ)) { if (((UInt)sem->mode & 0x1) != 0) { /* if BINARY bit is set */ sem->count = 1; } else { sem->count++; Assert_isTrue((sem->count != 0), Semaphore_A_overflow); } Hwi_restore(hwiKey); if (Semaphore_supportsEvents && (sem->event != NULL)) { Semaphore_eventPost(sem->event, sem->eventId); } return; } /* lock task scheduler */ tskKey = Task_disable(); /* dequeue tsk from semaphore queue */ elem = (Semaphore_PendElem *)Queue_dequeue(pendQ); /* mark the Semaphore as having been posted */ elem->pendState = Semaphore_PendState_POSTED; /* put task back into readyQ */ Task_unblockI(elem->tpElem.task, hwiKey); Hwi_restore(hwiKey); Task_restore(tskKey); }
/* * ======== GateMutexPri_leave ======== * Only releases the gate if key == FIRST_ENTER. */ Void GateMutexPri_leave(GateMutexPri_Object *obj, IArg key) { UInt tskKey, hwiKey; Task_Handle owner; Task_Handle newOwner; Task_PendElem *elem; Queue_Handle pendQ; pendQ = GateMutexPri_Instance_State_pendQ(obj); owner = Task_self(); /* * Prior to tasks starting, Task_self() will return NULL. * Simply return here as, by definition, there is * is only one thread running at this time. */ if (owner == NULL) { return; } /* * Gate may only be called from task context, so Task_disable is sufficient * protection. */ tskKey = Task_disable(); /* Assert that caller is gate owner. */ // ASSERT(owner == obj->owner); /* If this is not the outermost call to leave, just return. */ if (key != FIRST_ENTER) { Task_restore(tskKey); return; } /* * Restore this task's priority. The if-test is worthwhile because of the * cost of a call to setPri. */ if (obj->ownerOrigPri != Task_getPri(owner)) { Task_setPri(owner, obj->ownerOrigPri); } /* If the list of waiting tasks is not empty... */ if (!Queue_empty(pendQ)) { /* * Get the next owner from the front of the queue (the task with the * highest priority of those waiting on the queue). */ elem = (Task_PendElem *)Queue_dequeue(pendQ); newOwner = elem->task; /* Setup the gate. */ obj->owner = newOwner; obj->ownerOrigPri = Task_getPri(newOwner); /* Task_unblockI must be called with interrupts disabled. */ hwiKey = Hwi_disable(); Task_unblockI(newOwner, hwiKey); Hwi_restore(hwiKey); } /* If the gate is to be posted... */ else { obj->mutexCnt = 1; } Task_restore(tskKey); }