// WHERE: 0 <= start && start < strlen(s); // EFFECT: for each member m of tn that matches s[start,) // add the concatenation of sb and m to q // DETAILS: the sb should have the same string as before afetr // the function returns void tnode_lookup_generalized(tnode *tn, char *s, size_t start, struct strbuf *sb, Queue q) { REQUIRES(is_tnode(tn)); REQUIRES(s != NULL && 0 <= start && start < strlen(s)); REQUIRES(is_strbuf(sb)); REQUIRES(is_Queue(q)); if (s[start] == '*') { if (tn == NULL) return; tnode_lookup_generalized(tn->left, s, start, sb, q); tnode_lookup_generalized(tn->right, s, start, sb, q); if (s[start + 1] == '\0' && tn->is_end) { strbuf_push(sb, s[start]); Queue_insert(q, strbuf_str(sb)); strbuf_pop(sb); return; } else if (s[start + 1] == '\0') { tnode_lookup_generalized(tn->middle, s, start, sb, q); } else { ASSERT(s[start + 1] != '\n'); strbuf_push(sb, s[start]); tnode_lookup_generalized(tn->middle, s, start, sb, q); tnode_lookup_generalized(tn->middle, s, start + 1, sb, q); strbuf_pop(sb); } } else { if (tn == NULL) return; if (s[i] < tn->c) { tnode_lookup_generalized(T->left, s, i, sb, q); return; } else if (s[i] > tn->c) { tnode_lookup_generalize(T->right, s, i, sb, q); return; } else if (s[i+1] == '\0') { strbuf_push(sb, s[i]); Queue_insert(q, sb); strbuf_pop(sb); return; } tnode_lookup(T->middle, s, i+1); } ENSURES(is_Queue(q)); }
/* * ======== 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); }
/* * ======== 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; }