void CPU_scheduler(CPU_p cpu, Interrupt_type interrupt_type, int PC) { while (!Queue_isEmpty(cpu->newProcessesQueue)) { PCB_p temp_pcb = Queue_dequeue(cpu->newProcessesQueue); PCB_set_state(temp_pcb, ready); //PCB_set_pc(temp_pcb, PC); Queue_enqueue(cpu->readyQueue, temp_pcb); fprintf(file, "Process ID: %u Enqueued\n", temp_pcb->pid); fprintf(file, "%s", PCB_toString(temp_pcb)); } fprintf(file, "\n"); switch (interrupt_type) { case timer: // 1. Put process back into the readyQueue Queue_enqueue(cpu->readyQueue, cpu->currentProcess); // 2. Change its state from interrupted to ready PCB_set_state(cpu->currentProcess, ready); // 3. Make call to dispatcher CPU_dispatcher(cpu, timer); // 4. Returned from dispatcher, do any housekeeping // Nothing here to do at the moment! // 5. Returns to pseudo-ISR return; break; default: CPU_dispatcher(cpu, normal); break; } return; }
void bfs(BFSVertex* vertices, int nelem, int s) { Queue q; for (int u = 0; u < nelem; u++) { if (vertices[u].super.n != s) { vertices[u].super.color = WHITE; vertices[u].d = 1E10; vertices[u].super.parent = -1; } } vertices[s].super.color = GRAY; vertices[s].d = 0; vertices[s].super.parent = -1; Queue_init(&q); Queue_create_queue(&q, nelem); Queue_enqueue(&q, s); while (!Queue_is_empty(&q)) { int u = Queue_dequeue(&q); for (Adj* adj_v = vertices[u].super.first; adj_v; adj_v = adj_v->next) { if (vertices[adj_v->n].super.color == WHITE) { vertices[adj_v->n].super.color = GRAY; vertices[adj_v->n].d = vertices[u].d + 1; vertices[adj_v->n].super.parent = u; Queue_enqueue(&q, adj_v->n); } } vertices[u].super.color = BLACK; } }
static int test_enqueue() { Queue* queue = Queue_new(0); int array[] = {1, 2, 3}; Queue_enqueue(queue, &array[0]); Queue_enqueue(queue, &array[1]); Queue_enqueue(queue, &array[2]); nu_assert_eq_int(3, Queue_size(queue)); Queue_free(queue); return 0; }
static int test_capacity() { Queue* queue = Queue_new(2); int array[] = {1, 2, 3}; nu_assert(Queue_enqueue(queue, &array[0])); nu_assert(Queue_enqueue(queue, &array[1])); nu_assert(!Queue_enqueue(queue, &array[2])); Queue_dequeue(queue); nu_assert(Queue_enqueue(queue, &array[2])); Queue_free(queue); return 0; }
int main(void) { const int MAX_QUEUE_SIZE = 7; Queue_t queue = Queue_new(); const char * dllName = userChoice(); dynamic_t * dll = dynamic_init(dllName); if (NULL == dll) { printf("Can't load dynamic!\n"); return 1; } if (NULL == dll->check) { printf("Can't get compare function!\n"); return 1; } if (NULL == dll->react) { printf("Can't get reaction function!\n"); return 1; } puts("Dynamic loaded!"); srand(time(NULL)); for (int i = 0; i < MAX_QUEUE_SIZE; i++) { int prec = !(rand() % 3) ? 1 + rand() % 15 : 0; printf("%dth day's precipitation: %d\n", i, prec); Queue_enqueue(queue, prec); } if(dll->check(queue)) dll->react(); Queue_delete(queue); return 0; }
/* * ======== Task_unblockI ======== * Unblock a task. * * Place task in its ready list. * Must be called within Task_disable/Task_restore block * and with interrupts disabled */ Void Task_unblockI(Task_Object *tsk, UInt hwiKey) { #ifndef ti_sysbios_knl_Task_DISABLE_ALL_HOOKS Int i; #endif UInt curset = Task_module->curSet; UInt mask = tsk->mask; Queue_enqueue(tsk->readyQ, (Queue_Elem *)tsk); Task_module->curSet = curset | mask; tsk->mode = Task_Mode_READY; Task_module->workFlag = 1; /* It's safe to enable intrs here */ Hwi_restore(hwiKey); #ifndef ti_sysbios_knl_Task_DISABLE_ALL_HOOKS for (i = 0; i < Task_hooks.length; i++) { if (Task_hooks.elem[i].readyFxn != NULL) { Task_hooks.elem[i].readyFxn(tsk); } } #endif Log_write3(Task_LD_ready, (UArg)tsk, (UArg)tsk->fxn, (UArg)tsk->priority); /* Hard-disable intrs - this fxn is called with them disabled */ Hwi_disable(); }
// parse a recieved byte stream for packets void Packets_rxCallback(char* rx, uint8_t length){ length -= PACKETS_TERMINATOR_LEN; uint8_t crc_high = length-2; uint8_t crc_low = length-1; Packet packet; packet.crc = 0; packet.length = length-3; for (uint8_t i = 0; i < length; i++){ if (i == 0) packet.address = rx[i]; else if (i == crc_high){ packet.crc = rx[i]; packet.crc = packet.crc << 8 ; } else if (i == crc_low) packet.crc += rx[i]; else packet.data[i-1] = rx[i]; } // check crc uint16_t crc = crc16(rx, length-2); if (crc != packet.crc){ Packets_setError(PACKETS_ERR_CRC); return; } Queue* queue; queue = Packets_getQueue(); Queue_enqueue(queue, &packet); }
/******************************************************************************* * @fn SensorTag_processOadWriteCB * * @brief Process a write request to the OAD profile. * * @param event - event type: * OAD_WRITE_IDENTIFY_REQ * OAD_WRITE_BLOCK_REQ * @param connHandle - the connection Handle this request is from. * @param pData - pointer to data for processing and/or storing. * * @return None. */ static void SensorTag_processOadWriteCB(uint8_t event, uint16_t connHandle, uint8_t *pData) { oadTargetWrite_t *oadWriteEvt = ICall_malloc( sizeof(oadTargetWrite_t) + \ sizeof(uint8_t) * OAD_PACKET_SIZE); if ( oadWriteEvt != NULL ) { oadWriteEvt->event = event; oadWriteEvt->connHandle = connHandle; oadWriteEvt->pData = (uint8_t *)(&oadWriteEvt->pData + 1); memcpy(oadWriteEvt->pData, pData, OAD_PACKET_SIZE); Queue_enqueue(hOadQ, (Queue_Elem *)oadWriteEvt); // Post the application's semaphore. Semaphore_post(sem); } else { // Fail silently. } }
// ----------------------------------------------------------------------------- //! \brief Creates a queue node and puts the node in RTOS queue. //! //! \param msgQueue - queue handle. //! \param sem - thread's event processing semaphore that queue is //! associated with. //! \param pMsg - pointer to message to be queued //! //! \return TRUE if message was queued, FALSE otherwise. // ----------------------------------------------------------------------------- uint8_t NPIUtil_enqueueMsg(Queue_Handle msgQueue, Semaphore_Handle sem, uint8_t *pMsg) { queueRec_t *pRec; // Allocated space for queue node. if (pRec = NPIUTIL_MALLOC(sizeof(queueRec_t))) { pRec->pData = pMsg; Queue_enqueue(msgQueue, &pRec->_elem); // Wake up the application thread event handler. if (sem) { Semaphore_post(sem); } return TRUE; } // Free the message. NPIUTIL_FREE(pMsg); return FALSE; }
/* * ======== GIO_reclaim ======== */ Int GIO_reclaim(GIO_Object *obj, Ptr *pBuf, SizeT *pSize, UArg *pArg) { IOM_Packet *packet; Queue_Handle doneList; Queue_Handle freeList; UInt key; Int status; Error_Block eb; doneList = GIO_Instance_State_doneList(obj); freeList = GIO_Instance_State_freeList(obj); Error_init(&eb); while (obj->doneCount == 0) { if (Sync_wait(obj->sync, obj->timeout, &eb) == Sync_WaitStatus_TIMEOUT) { return (IOM_ETIMEOUT); } } key = Hwi_disable(); obj->doneCount--; packet = Queue_dequeue(doneList); Hwi_restore(key); if (pArg != NULL) { *pArg = packet->arg; } /* pBuf is set to NULL by GIO_read() and GIO_write() */ if (pBuf != NULL) { *pBuf = packet->addr; } if (pSize != NULL) { *pSize = packet->size; } status = packet->status; /* * re-signal if more buffers are ready * This is required in the case of ISyncEvent and ISyncSwi to allow * clients to reclaim a single buffer and not force them to bleed the * stream. */ if (obj->doneCount > 0) { Sync_signal(obj->sync); } /* recycle packet back onto free list */ key = Hwi_disable(); obj->freeCount++; Queue_enqueue(freeList, (Queue_Elem *)packet); Hwi_restore(key); return (status); }
static int test_front_back() { Queue* queue = Queue_new(0); nu_assert_eq_ptr(NULL, Queue_front(queue)); nu_assert_eq_ptr(NULL, Queue_back(queue)); int array[] = {1, 2, 3}; Queue_enqueue(queue, &array[0]); Queue_enqueue(queue, &array[1]); Queue_enqueue(queue, &array[2]); nu_assert_eq_ptr(&array[0], Queue_front(queue)); nu_assert_eq_ptr(&array[2], Queue_back(queue)); nu_assert_eq_int(3, Queue_size(queue)); Queue_free(queue); return 0; }
/********************************************************************* * @fn Util_enqueueMsg * * @brief Creates a queue node and puts the node in RTOS queue. * * @param msgQueue - queue handle. * @param sem - thread's event processing semaphore that queue is * associated with. * @param pMsg - pointer to message to be queued * * @return TRUE if message was queued, FALSE otherwise. */ uint8_t Util_enqueueMsg(Queue_Handle msgQueue, Semaphore_Handle sem, uint8_t *pMsg) { queueRec_t *pRec; // Allocated space for queue node. #ifdef USE_ICALL if (pRec = ICall_malloc(sizeof(queueRec_t))) #else if (pRec = (queueRec_t *)malloc(sizeof(queueRec_t))) #endif { pRec->pData = pMsg; Queue_enqueue(msgQueue, &pRec->_elem); // Wake up the application thread event handler. if (sem) { Semaphore_post(sem); } return TRUE; } // Free the message. #ifdef USE_ICALL ICall_free(pMsg); #else free(pMsg); #endif return FALSE; }
int main() { // moduleTests_Queue(); Queue_t queue1 = Queue_new(); Queue_t queue2 = Queue_new(); for(int i = 0; i < 10; i++){ Queue_enqueue(queue1, randInt()); Queue_enqueue(queue2, randInt()); } Queue_bindQueues(queue1, queue2); Queue_subscribeSingleOverflowEvent(queue1, singleQueueOverflow1, "queue1"); Queue_subscribeSingleOverflowEvent(queue1, singleQueueOverflow2, "queue1"); Queue_subscribeSingleOverflowEvent(queue2, singleQueueOverflow1, "queue2"); Queue_subscribeSingleOverflowEvent(queue2, singleQueueOverflow2, "queue2"); Queue_subscribePairOverflowEvent(queue1, queuePairOverflow, "queue1"); Queue_subscribePairEmptyEvent(queue1, queuePairEmpty, "queue1"); Queue_subscribePairOverflowEvent(queue2, queuePairOverflow, "queue2"); Queue_subscribePairEmptyEvent(queue2, queuePairEmpty, "queue2"); for(int i = 0; i < 50; i++){ int rndInt = randInt(); if(randBool()){ if(rndInt >= 0){ Queue_enqueue(queue1, rndInt); }else{ Queue_dequeue(queue1); } }else{ if(rndInt >= 0){ Queue_enqueue(queue2, rndInt); }else{ Queue_dequeue(queue2); } } } Queue_delete(queue1); Queue_delete(queue2); return 0; }
/* * ======== callback ======== * This function is called by the underlying IOM driver. */ static Void callback(Ptr cbArg, IOM_Packet *packet) { GIO_Handle obj = (GIO_Handle)cbArg; GIO_AppCallback *appCallback = (GIO_AppCallback *)packet->misc; Int status; Ptr addr; SizeT size; Queue_Handle list; UInt key; key = Hwi_disable(); obj->submitCount--; Hwi_restore(key); if (appCallback == NULL) { Sync_signal(obj->sync); } else { if (obj->model == GIO_Model_ISSUERECLAIM) { /* put packet on doneList where GIO_reclaim() will find it */ list = GIO_Instance_State_doneList(obj); key = Hwi_disable(); obj->doneCount++; Queue_enqueue(list, (Queue_Elem *)packet); Hwi_restore(key); Sync_signal(obj->sync); } else { list = GIO_Instance_State_freeList(obj); status = packet->status; addr = packet->addr; size = packet->size; key = Hwi_disable(); obj->freeCount++; Queue_enqueue(list, (Queue_Elem *)packet); Hwi_restore(key); (*appCallback->fxn)(appCallback->arg, status, addr, size); } } }
/** * Function that creates 0-5 new processes and puts them into a list. */ Queue *CPU_create_processes(Queue *queue, int numb_process, int process_ID) { int n; for (n = 0; n < numb_process; n++) { PCB *pcb = PCB_constructor(); PCB_set_pid(pcb, process_ID + n); PCB_set_priority(pcb, rand() % 31 + 1); PCB_set_state(pcb, created); queue = Queue_enqueue(queue, pcb); } return queue; }
//parser enqueues void *enq_helper(void* argPtr) { Queue_enqueue(((EPacket_t*)(argPtr))->x, ((EPacket_t*)(argPtr))->q, ((EPacket_t*)(argPtr))->queue_size); printf("%d: enqueuehelper getting mainmutex\n", pthread_self()); pthread_mutex_lock(&mainMutex); printf("%d: enqueuehelper got mainmutex, ++work; workInSystem = %d \n", pthread_self(), workInSystem); workInSystem++; printf("%d: enqueuehelper going to release mainmutex; workInSystem = %d \n", pthread_self(), workInSystem); pthread_mutex_unlock(&mainMutex); printf("%d: enqueuehelper released mainmutex\n", pthread_self()); }
/* * ======== Swi_post ======== */ Void Swi_post(Swi_Object *swi) { UInt hwiKey; UInt swiKey; #ifndef ti_sysbios_knl_Swi_DISABLE_ALL_HOOKS Int i; #endif Log_write3(Swi_LM_post, (UArg)swi, (UArg)swi->fxn, (UArg)swi->priority); hwiKey = Hwi_disable(); if (swi->posted) { Hwi_restore(hwiKey); return; } swi->posted = TRUE; swiKey = Swi_disable(); /* Place the Swi in the appropriate ready Queue. */ Queue_enqueue(swi->readyQ, (Queue_Elem *)swi); /* Add this priority to current set */ Swi_module->curSet |= swi->mask; Hwi_restore(hwiKey); /* Not in FIFO order. OK! */ #ifndef ti_sysbios_knl_Swi_DISABLE_ALL_HOOKS /* * This hook location supports the STS "set ready time" operation on * Swis. This is equivalent to pre-BIOS 6. */ for (i = 0; i < Swi_hooks.length; i++) { if (Swi_hooks.elem[i].readyFxn != NULL) { Swi_hooks.elem[i].readyFxn(swi); } } #endif /* * Modified Swi_restore(). * No need to check curSet since we just set it. */ if (swiKey == FALSE) { if (Core_getId() == 0) { Swi_schedule(); /* unlocks Swi scheduler on return */ } else { Swi_restoreSMP(); /* interrupt core 0 to do the work */ } } }
static int test_size() { Queue* queue = Queue_new(0); nu_assert_eq_int(0, Queue_size(queue)); int array[] = {1}; Queue_enqueue(queue, &array[0]); nu_assert_eq_int(1, Queue_size(queue)); Queue_dequeue(queue); nu_assert_eq_int(0, Queue_size(queue)); Queue_free(queue); return 0; }
static int test_empty() { Queue* queue = Queue_new(0); nu_assert(Queue_empty(queue)); int array[] = {1}; Queue_enqueue(queue, &array[0]); nu_assert(!Queue_empty(queue)); Queue_dequeue(queue); nu_assert(Queue_empty(queue)); Queue_free(queue); return 0; }
/* * ======== Task_yield ======== */ Void Task_yield() { UInt tskKey, hwiKey; tskKey = Task_disable(); hwiKey = Hwi_disable(); if (Task_module->curQ) { /* move current task to end of curQ */ Queue_enqueue(Task_module->curQ, Queue_dequeue(Task_module->curQ)); } Task_module->curQ = NULL; /* force a Task_switch() */ Task_module->workFlag = 1; Hwi_restore(hwiKey); Log_write3(Task_LM_yield, (UArg)Task_module->curTask, (UArg)(Task_module->curTask->fxn), (UArg)(BIOS_getThreadType())); Task_restore(tskKey); }
// ----------------------------------------------------------------------------- //! \brief Creates a queue node and puts the node in RTOS queue. //! //! \param msgQueue - queue handle. //! \param event - thread's event processing synchronization object that //! queue is associated with. //! \param eventFlag - events to signal with synchronization object associated //! with this pMsg. //! \param sem - thread's event processing semaphore that queue is //! associated with. //! \param pMsg - pointer to message to be queued //! //! \return TRUE if message was queued, FALSE otherwise. // ----------------------------------------------------------------------------- uint8_t NPIUtil_enqueueMsg(Queue_Handle msgQueue, #ifdef ICALL_EVENTS Event_Handle event, uint32_t eventFlags, #else //!ICALL_EVENTS Semaphore_Handle sem, #endif //ICALL_EVENTS uint8_t *pMsg) { queueRec_t *pRec; // Allocated space for queue node. if (pRec = NPIUTIL_MALLOC(sizeof(queueRec_t))) { pRec->pData = pMsg; Queue_enqueue(msgQueue, &pRec->_elem); // Wake up the application thread event handler. #ifdef ICALL_EVENTS if (event) { Event_post(event, eventFlags); } #else //!ICALL_EVENTS if (sem) { Semaphore_post(sem); } #endif //ICALL_EVENTS return TRUE; } // Free the message. NPIUTIL_FREE(pMsg); return FALSE; }
/* * ======== GateMutexPri_insertPri ======== * Inserts the element in order by priority, with higher priority * elements at the head of the queue. */ Void GateMutexPri_insertPri(Queue_Object* queue, Queue_Elem* newElem, Int newPri) { Queue_Elem* qelem; /* Iterate over the queue. */ for (qelem = Queue_head(queue); qelem != (Queue_Elem *)queue; qelem = Queue_next(qelem)) { /* Tasks of equal priority will be FIFO, so '>', not '>='. */ if (newPri > Task_getPri((Task_Handle)qelem)) { /* Place the new element in front of the current qelem. */ Queue_insert(qelem, newElem); return; } } /* * Put the task at the back of the queue if: * 1. The queue was empty. * 2. The task had the lowest priority in the queue. */ Queue_enqueue(queue, newElem); }
Queue_p CPU_enqueue_terminatedQueue(CPU_p cpu, PCB_p pcb) { return Queue_enqueue(CPU_get_terminatedQueue(cpu), pcb); }
/* * ======== GIO_submit ======== */ Int GIO_submit(GIO_Object *obj, Uns cmd, Ptr buf, SizeT *pSize, GIO_AppCallback *appCallback) { IOM_Packet syncPacket; IOM_Packet *packet; SizeT nullSize; Int status; UInt key; Queue_Handle list; Error_Block eb; IOM_Fxns *iomFxns; iomFxns = (IOM_Fxns *)obj->fxns; if (appCallback == NULL) { packet = &syncPacket; } else { list = GIO_Instance_State_freeList(obj); if (obj->freeCount == 0) { return (IOM_ENOPACKETS); } key = Hwi_disable(); obj->freeCount--; packet = Queue_dequeue(list); Hwi_restore(key); } if (pSize == NULL) { nullSize = 0; pSize = &nullSize; } packet->cmd = cmd; packet->addr = buf; packet->size = *pSize; packet->status = IOM_COMPLETED; /* * 'appCallback' will be NULL for synchronous calls. * 'packet->misc' is used in the callback to call asynch callback * or post semaphore (sync). */ packet->misc = (UArg)appCallback; status = iomFxns->mdSubmitChan(obj->mdChan, packet); if ((status == IOM_COMPLETED) || (status < 0)) { if (status == IOM_COMPLETED) { *pSize = packet->size; status = packet->status; } /* if asynch, put packet back on freeList */ if (appCallback != NULL) { key = Hwi_disable(); obj->freeCount++; Queue_enqueue(list, (Queue_Elem *)packet); Hwi_restore(key); } return (status); } /* * call Sync_wait only if synchronous I/O and mdSubmitChan did not * return an error (status < 0) */ if (appCallback == NULL) { Error_init(&eb); if (Sync_wait(obj->sync, obj->timeout, &eb) == Sync_WaitStatus_SUCCESS) { *pSize = packet->size; status = packet->status; } else { *pSize = 0; /* * NOTE: A channel timeout needs special handling. Timeouts are * usually due to some serious underlying device or system state * and may require the channel, or possibly the device,to be reset. * Because the mini-driver may still own the IOM_Packet here * driver's will need to perform timeout processing. We will call * the mini-driver's control fxn with the IOM_CHAN_TIMEDOUT command * code. */ status = iomFxns->mdControlChan(obj->mdChan, IOM_CHAN_TIMEDOUT, NULL); if (status != IOM_COMPLETED) { return (IOM_ETIMEOUTUNREC); /* fatal, may have lost packet */ } return (IOM_ETIMEOUT); } } return (status); }
/* * ======== GIO_Instance_init ======== */ Int GIO_Instance_init(GIO_Object *obj, String name, UInt mode, const GIO_Params *params, Error_Block *eb) { Int i, status; Queue_Handle doneList; Queue_Handle freeList; DEV_Handle device; IOM_Packet *packets; IOM_Fxns *iomFxns; Ptr devp; obj->name = name; obj->numPackets = params->numPackets; obj->doneCount = 0; obj->freeCount = 0; obj->submitCount = 0; obj->mode = mode; obj->model = params->model; obj->timeout = params->timeout; if (params->sync == NULL) { obj->userSync = FALSE; obj->sync = SyncSemThread_Handle_upCast(SyncSemThread_create(NULL, eb)); if (obj->sync == NULL) { return (1); } } else { obj->sync = params->sync; obj->userSync = TRUE; } doneList = GIO_Instance_State_doneList(obj); Queue_construct(Queue_struct(doneList), NULL); freeList = GIO_Instance_State_freeList(obj); Queue_construct(Queue_struct(freeList), NULL); /* allocate packets */ packets = Memory_alloc(NULL, sizeof(IOM_Packet) * (obj->numPackets), 0, eb); if (packets == NULL) { return (2); } obj->packets = packets; obj->freeCount = obj->numPackets; /* * Split the buffer into packets and add to freeList */ for (i = 0; i < obj->numPackets; i++) { Queue_enqueue(freeList, (Queue_Elem *)&packets[i]); } name = DEV_match(name, &device); if (device == NULL) { /* The name was not found */ Error_raise(eb, GIO_E_notFound, obj->name, 0); return (3); } obj->fxns = DEV_getFxns(device); iomFxns = (IOM_Fxns *)obj->fxns; devp = DEV_getDevp(device); status = iomFxns->mdCreateChan(&obj->mdChan, devp, name, mode, params->chanParams, callback, obj); if (status != IOM_COMPLETED) { Error_raise(eb, GIO_E_createFailed, status, 0); return (4); } return (0); }
/* * ======== Event_pend ======== */ UInt Event_pend(Event_Object *event, UInt andMask, UInt orMask, UInt32 timeout) { UInt hwiKey, tskKey; Event_PendElem elem; UInt matchingEvents; Queue_Handle pendQ; Clock_Struct clockStruct; Assert_isTrue(((andMask | orMask) != 0), Event_A_nullEventMasks); Log_write5(Event_LM_pend, (UArg)event, (UArg)event->postedEvents, (UArg)andMask, (UArg)orMask, (IArg)((Int)timeout)); /* * elem is filled in entirely before interrupts are disabled. * This significantly reduces latency at the potential cost of wasted time * if it turns out that there is already an event match. */ /* add Clock event if timeout is not FOREVER nor NO_WAIT */ if (BIOS_clockEnabled && (timeout != BIOS_WAIT_FOREVER) && (timeout != BIOS_NO_WAIT)) { Clock_addI(Clock_handle(&clockStruct), (Clock_FuncPtr)Event_pendTimeout, timeout, (UArg)&elem); elem.tpElem.clock = Clock_handle(&clockStruct); elem.pendState = Event_PendState_CLOCK_WAIT; } else { elem.tpElem.clock = NULL; elem.pendState = Event_PendState_WAIT_FOREVER; } /* fill in this task's Event_PendElem */ elem.andMask = andMask; elem.orMask = orMask; pendQ = Event_Instance_State_pendQ(event); /* get task handle */ elem.tpElem.task = Task_self(); /* Atomically check for a match and block if none */ hwiKey = Hwi_disable(); /* check if events are already available */ matchingEvents = Event_checkEvents(event, andMask, orMask); if (matchingEvents != 0) { /* remove Clock object from Clock Q */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_removeI(elem.tpElem.clock); elem.tpElem.clock = NULL; } Hwi_restore(hwiKey); return (matchingEvents);/* yes, then return with matching bits */ } if (timeout == BIOS_NO_WAIT) { Hwi_restore(hwiKey); return (0); /* No match, no wait */ } Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Task), Event_A_badContext); /* * Verify that THIS core hasn't already disabled the scheduler * so that the Task_restore() call below will indeed block */ Assert_isTrue((Task_enabled()), Event_A_pendTaskDisabled); /* lock scheduler */ tskKey = Task_disable(); /* only one Task allowed!!! */ Assert_isTrue(Queue_empty(pendQ), Event_A_eventInUse); /* leave a pointer for Task_delete() */ elem.tpElem.task->pendElem = (Task_PendElem *)&(elem); /* add it to Event_PendElem queue */ Queue_enqueue(pendQ, (Queue_Elem *)&elem); Task_blockI(elem.tpElem.task); if (BIOS_clockEnabled && (elem.pendState == Event_PendState_CLOCK_WAIT)) { Clock_startI(elem.tpElem.clock); } Hwi_restore(hwiKey); /* unlock task scheduler and block */ Task_restore(tskKey); /* the calling task will switch out here */ /* Here on unblock due to Event_post or Event_pendTimeout */ hwiKey = Hwi_disable(); /* remove Clock object from Clock Q */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_removeI(elem.tpElem.clock); elem.tpElem.clock = NULL; } elem.tpElem.task->pendElem = NULL; Hwi_restore(hwiKey); /* event match? */ if (elem.pendState != Event_PendState_TIMEOUT) { return (elem.matchingEvents); } else { return (0); /* timeout */ } }
Queue_p CPU_enqueue_readyQueue(CPU_p cpu, PCB_p pcb) { return Queue_enqueue(CPU_get_readyQueue(cpu), pcb); }
/* * ======== Semaphore_pend ======== */ Bool Semaphore_pend(Semaphore_Object *sem, UInt timeout) { UInt hwiKey, tskKey; Semaphore_PendElem elem; Queue_Handle pendQ; Clock_Struct clockStruct; Log_write3(Semaphore_LM_pend, (IArg)sem, (UArg)sem->count, (IArg)((Int)timeout)); /* * Consider fast path check for count != 0 here!!! */ /* * elem is filled in entirely before interrupts are disabled. * This significantly reduces latency. */ /* add Clock event if timeout is not FOREVER nor NO_WAIT */ if (BIOS_clockEnabled && (timeout != BIOS_WAIT_FOREVER) && (timeout != BIOS_NO_WAIT)) { Clock_Params clockParams; Clock_Params_init(&clockParams); clockParams.arg = (UArg)&elem; clockParams.startFlag = FALSE; /* will start when necessary, thankyou */ Clock_construct(&clockStruct, (Clock_FuncPtr)Semaphore_pendTimeout, timeout, &clockParams); elem.tpElem.clock = Clock_handle(&clockStruct); elem.pendState = Semaphore_PendState_CLOCK_WAIT; } else { elem.tpElem.clock = NULL; elem.pendState = Semaphore_PendState_WAIT_FOREVER; } pendQ = Semaphore_Instance_State_pendQ(sem); hwiKey = Hwi_disable(); /* check semaphore count */ if (sem->count == 0) { if (timeout == BIOS_NO_WAIT) { Hwi_restore(hwiKey); return (FALSE); } Assert_isTrue((BIOS_getThreadType() == BIOS_ThreadType_Task), Semaphore_A_badContext); /* lock task scheduler */ tskKey = Task_disable(); /* get task handle and block tsk */ elem.tpElem.task = Task_self(); /* leave a pointer for Task_delete() */ elem.tpElem.task->pendElem = (Task_PendElem *)&(elem); Task_blockI(elem.tpElem.task); if (((UInt)sem->mode & 0x2) != 0) { /* if PRIORITY bit is set */ Semaphore_PendElem *tmpElem; Task_Handle tmpTask; UInt selfPri; tmpElem = Queue_head(pendQ); selfPri = Task_getPri(elem.tpElem.task); while (tmpElem != (Semaphore_PendElem *)pendQ) { tmpTask = tmpElem->tpElem.task; /* use '>' here so tasks wait FIFO for same priority */ if (selfPri > Task_getPri(tmpTask)) { break; } else { tmpElem = Queue_next((Queue_Elem *)tmpElem); } } Queue_insert((Queue_Elem *)tmpElem, (Queue_Elem *)&elem); } else { /* put task at the end of the pendQ */ Queue_enqueue(pendQ, (Queue_Elem *)&elem); } /* start Clock if appropriate */ if (BIOS_clockEnabled && (elem.pendState == Semaphore_PendState_CLOCK_WAIT)) { Clock_startI(elem.tpElem.clock); } Hwi_restore(hwiKey); Task_restore(tskKey); /* the calling task will block here */ /* Here on unblock due to Semaphore_post or timeout */ if (Semaphore_supportsEvents && (sem->event != NULL)) { /* synchronize Event state */ hwiKey = Hwi_disable(); Semaphore_eventSync(sem->event, sem->eventId, sem->count); Hwi_restore(hwiKey); } /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_destruct(Clock_struct(elem.tpElem.clock)); } elem.tpElem.task->pendElem = NULL; return ((Bool)(elem.pendState)); } else { --sem->count; if (Semaphore_supportsEvents && (sem->event != NULL)) { /* synchronize Event state */ Semaphore_eventSync(sem->event, sem->eventId, sem->count); } Hwi_restore(hwiKey); /* deconstruct Clock if appropriate */ if (BIOS_clockEnabled && (elem.tpElem.clock != NULL)) { Clock_destruct(Clock_struct(elem.tpElem.clock)); } return (TRUE); } }
/* * ======== Task_setPri ======== */ UInt Task_setPri(Task_Object *tsk, Int priority) { Int oldPri; UInt newMask, tskKey, hwiKey; Queue_Handle newQ; Assert_isTrue((((priority == -1) || (priority > 0) || ((priority == 0 && Task_module->idleTask == NULL))) && (priority < (Int)Task_numPriorities)), Task_A_badPriority); Log_write4(Task_LM_setPri, (UArg)tsk, (UArg)tsk->fxn, (UArg)tsk->priority, (UArg)priority); tskKey = Task_disable(); hwiKey = Hwi_disable(); oldPri = tsk->priority; if (oldPri == priority) { Hwi_restore(hwiKey); Task_restore(tskKey); return (oldPri); } if (priority < 0) { newMask = 0; newQ = Task_Module_State_inactiveQ(); } else { newMask = 1 << priority; newQ = (Queue_Handle)((UInt8 *)(Task_module->readyQ) + (UInt)(priority*(2*sizeof(Ptr)))); } if (tsk->mode == Task_Mode_READY) { Queue_remove((Queue_Elem *)tsk); /* if last task in readyQ, remove corresponding bit in curSet */ if (Queue_empty(tsk->readyQ)) { Task_module->curSet &= ~tsk->mask; } if (Task_module->curTask == tsk) { Task_module->curQ = newQ; /* force a Task_switch() */ /* if no longer maxQ */ /* Put current task at front of its new readyQ */ Queue_insert(((Queue_Elem *)(newQ))->next, (Queue_Elem *)tsk); } else { /* place task at end of its readyQ */ Queue_enqueue(newQ, (Queue_Elem *)tsk); } Task_module->curSet |= newMask; } tsk->priority = priority; tsk->mask = newMask; tsk->readyQ = newQ; if (priority < 0) { Task_module->curQ = NULL; /* force a Task_switch() */ } Task_module->workFlag = 1; Hwi_restore(hwiKey); Task_restore(tskKey); return oldPri; }
/* * ======== insert ======== */ void Queue_insert(Queue_Elem *qelem, Queue_Elem *elem) { Queue_enqueue((Queue_Object *)qelem, elem); }