VOID PrinterThread(UT_ARGUMENT outFile) { do { EventWait(&ResultEvent); if (end == 0) printf("%s", line); EventSignal(&FreeEvent); } while (end == 0); }
BOOL UtMsgRcv (PVOID Data, PDWORD Size, PHANDLE Sender){ PLIST_ENTRY List; PUTHREAD RunningThread = (PUTHREAD)UtSelf(); if(RunningThread->nMessages == 0){ if(nMsg == 0){ EventInit(RunningThread->ev , FALSE); EventWait(RunningThread->ev); }else{ PMessage m = (PMessage)RemoveHeadList(&QMSG); Data = m->Buffer; Size = m->SizeBuffer; InterlockedIncrement(&nMsg); if(Sender != NULL) Sender = (PHANDLE)RunningThread; return TRUE; } } List = RunningThread->MessageQueue.Flink; PMessage msg = (PMessage)CONTAINING_RECORD(List , Message, Link); if(msg->SizeBuffer > Size){ Size = msg->SizeBuffer; return FALSE; } RemoveHeadList(&RunningThread->MessageQueue); Data = msg->Buffer; Size = msg->SizeBuffer; if(Sender != NULL) Sender = (PHANDLE)RunningThread; return TRUE; }
VOID WriterThread(UT_ARGUMENT outFile) { FILE * f = fopen((const char *)outFile, "w+"); assert(f != NULL); do { EventWait(&ResultEvent); if (end == 0) fputs(line, f); EventSignal(&FreeEvent); } while (end == 0); fclose(f); }
VOID ReaderThread(UT_ARGUMENT inFile) { FILE * f = fopen((const char *)inFile, "r"); assert(f != NULL); do { EventWait(&FreeEvent); if (fgets(line, 256, f) == NULL) end = 1; EventSignal(&LineEvent); } while (end == 0); fclose(f); }
VOID FilterThread(UT_ARGUMENT arg) { char c = (char)arg; do { EventWait(&LineEvent); if (end == 1 || strchr(line, c) != NULL) { EventSignal(&ResultEvent); } else { EventSignal(&FreeEvent); } } while (end == 0); }
/*----------------------------------------------------------------------------* * NAME * Sched * * DESCRIPTION * Starts the scheduler. The function will not return until * SchedStop() has been called. * * The data parameter is the scheduler context returned by the * SchedInit() function. * * RETURNS * void * *----------------------------------------------------------------------------*/ void Sched(void *data) { uint8 i; uint32 eventBits; Result result; uint16 readThreadIdVector; int8 name[8] = "sched-x"; SchedulerInstanceType *inst = (SchedulerInstanceType *) data; /* Create scheduler threads */ for (i = 0; i < _SCHED_MAX_SEGMENTS; i++) { if (inst->thread[i].inUse) { name[6] = '0' + i; if (ThreadCreate(SchedLoop, &inst->thread[i], inst->thread[i].stackSize, inst->thread[i].priority, name, &(inst->thread[i].thread_handle)) != _RESULT_SUCCESS) { // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, "Thread creation failed"); } } } /* Start scheduler threads */ for (i = 0; i < _SCHED_MAX_SEGMENTS; i++) { if (inst->thread[i].inUse) { EventSet(&inst->thread[i].eventHandle, START_EVENT); } } /* The following handles scheduler shutdown and task deinit. * The shutdown sequence first signals all threads to stop * their scheduler loop. Then it signals all threads to run * their task deinit functions. * * Shutdown is successfull if all threads respond to stop and deinit * requests. Missing responses will cause the shutdown sequence to * be aborted and the incident will be logged. The Sched() function * will then return immediately. No panics will be generated. * * If shutdown is disabled the Sched() function will block forever. */ /* * Block until told to exit from SchedStop(). Or block forever if * shutdown is disabled. */ result = EventWait(&inst->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if ((result != _RESULT_SUCCESS) || (eventBits != STOP_REQ_EVENT)) { GENERROR(("Failure in wait for task stop request")); return; } /* Signal all threads to stop their scheduler loop */ for (i = 0; i < _SCHED_MAX_SEGMENTS; i ++) { if (inst->thread[i].inUse) { EventSet(&inst->thread[i].eventHandle, STOP_REQ_EVENT); } } /* Block until all threads are stopped. */ eventBits = 0; readThreadIdVector = 0; while (readThreadIdVector != instance->threadIdVector) { result = EventWait(&inst->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if ((result == _RESULT_SUCCESS) && (STOP_CFM_EVENT & eventBits)) { readThreadIdVector |= THREAD_ID_MASK & eventBits; } else if (result != _RESULT_SUCCESS) { GENERROR(("Failure in wait for thread stop confirm")); return; } } /* signal all threads to run their task deinit */ for (i = 0; i < _SCHED_MAX_SEGMENTS; i ++) { if (inst->thread[i].inUse) { EventSet(&inst->thread[i].eventHandle, DEINIT_REQ_EVENT); } } /* block until all threads have completed task deinit */ eventBits = 0; readThreadIdVector = 0; while (readThreadIdVector != instance->threadIdVector) { result = EventWait(&inst->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if ((result == _RESULT_SUCCESS) && (DEINIT_CFM_EVENT & eventBits)) { readThreadIdVector |= THREAD_ID_MASK & eventBits; } else if (result != _RESULT_SUCCESS) { GENERROR(("Failure in wait for thread deinit confirm")); return; } } }
/*----------------------------------------------------------------------------* * NAME * SchedLoop * * DESCRIPTION * The main function of the background task scheduler. This * invokes tasks as messages become available for them and * delivers timed event calls. * * * RETURNS * void * *----------------------------------------------------------------------------*/ void SchedLoop(void *data) { ThreadInstanceType *thread; uint32 eventBits, timeout; uint32 eventBitsOther; Time now; TimerType *timer; uint16 i; Result result; thread = (ThreadInstanceType *) data; result = EventWait(&thread->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if (result != _RESULT_SUCCESS) { // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, "Event wait failed"); } eventBitsOther = (eventBits & ~START_EVENT); if (eventBitsOther) { /* If thread is signalled from another thread, by a message put, * then pass this signal to our self. */ EventSet(&thread->eventHandle, eventBitsOther); } /* make sure the Sched loop continues until interrupted */ thread->schedRunning = TRUE; /* Tasks' initialisation functions. */ for (i = 0; i < thread->numberOfTasks; i ++) { thread->currentTask = (Task) (i | (thread->id << _SCHED_QUEUE_SEGMENT_SHIFT)); if (thread->tasks[i].initFunction) { thread->tasks[i].initFunction(&(thread->tasks[i].instanceDataPointer)); } thread->currentTask = _SCHED_TASK_ID; } i = 0; while (thread->schedRunning) { if (thread->pendingMessages > 0) { /* Consider each task in turn. */ while (1) { TaskDefinitionType *task; if (i >= thread->numberOfTasks) { i = 0; } task = &thread->tasks[i]; if (task->messageQueueFirst) { thread->currentTask = (int) (i | (thread->id << _SCHED_QUEUE_SEGMENT_SHIFT)); task->handlerFunction(&(task->instanceDataPointer)); thread->currentTask = _SCHED_TASK_ID; i++; break; } else { i++; } } } /* if no internal messages wait for external event or a timer to to expire */ if (thread->pendingMessages == 0) { /* Currently there is no messages on any of the Scheduler task queues. Wait for a timer or an external event to occur */ if (thread->timerList != NULL) { now = TimeGet(NULL); if (thread->timerList->wrapCount > thread->currentWrapCount) { timeout = (_SCHED_TIME_MAX - now + thread->timerList->when); /* Avoid rounding to zero in division below. */ timeout += 999; } else { if (now < thread->timerList->when) { timeout = TimeSub(thread->timerList->when, now); /* Avoid rounding to zero in division below. */ timeout += 999; } else { timeout = 0; } } timeout /= 1000; if (timeout >= _EVENT_WAIT_INFINITE) { timeout = _EVENT_WAIT_INFINITE - 1; } } else { timeout = _EVENT_WAIT_INFINITE; } } else { timeout = 0; } if (EventWait(&thread->eventHandle, (uint16) timeout, &eventBits) == _RESULT_SUCCESS) { /* background interrupt */ SchedBgint vector; vector = (SchedBgint) (eventBits & BG_INT_MASK); /* Are any background interrupts set? */ if (vector) { uint32 j; j = 0; do { BgIntType *bgint; bgint = &instance->bgint[j]; /* Check if this bgint is set */ if (vector & bgint->eventBit) { /* Clear the bit so the bgint is accounted for. */ vector &= ~bgint->eventBit; thread->currentTask = bgint->qid; bgint->handler(bgint->arg); thread->currentTask = _SCHED_TASK_ID; } j++; } while (vector); } /* a message arriving from outside */ if (EXT_MSG_EVENT & eventBits) { SchedTaskId qi; MessageQueueEntryType *message; MutexLock(&thread->qMutex); while (thread->extMsgQueueFirst != NULL) { /* remove from ext queue */ message = thread->extMsgQueueFirst; thread->extMsgQueueFirst = message->next; message->next = NULL; qi = message->receiver; /* ...store the on the end of the task's message chain. */ if (thread->tasks[qi].messageQueueLast == NULL) { thread->tasks[qi].messageQueueFirst = message; thread->tasks[qi].messageQueueLast = message; } else { thread->tasks[qi].messageQueueLast->next = message; thread->tasks[qi].messageQueueLast = message; } thread->pendingMessages++; } /* At this point the external queue is empty. */ thread->extMsgQueueLast = NULL; MutexUnlock(&thread->qMutex); } /* a sched stop req */ if (STOP_REQ_EVENT & eventBits) { /* return stop cfm and break out of scheduler loop */ thread->schedRunning = FALSE; EventSet(&instance->eventHandle, STOP_CFM_EVENT | (0x0001 << (uint32) thread->id)); break; } } while (thread->timerList) { /* Now, back to timed events. */ now = TimeGet(NULL); /* Handle timer wrap */ adjust_wrap_count(thread, now); if (thread->timerList->wrapCount > thread->currentWrapCount) { /* The earliest deadline is more than 1 wrapCount in the future. */ break; } else { if ((thread->timerList->when > now) && (thread->timerList->wrapCount == thread->currentWrapCount)) { break; } else { /* Run the timed event function. */ timer = thread->timerList; timer->active = FALSE; thread->timerList = timer->next; if (thread->timerList != NULL) { thread->timerList->prev = NULL; } thread->currentTask = timer->queue; timer->eventFunction(timer->id, timer->fniarg, timer->fnvarg); thread->currentTask = _SCHED_TASK_ID; timerFree(thread, timer); } } } } /* while (thread->schedRunning) */ /* wait for deinit req event */ while (1) { eventBits = 0; result = EventWait(&thread->eventHandle, _EVENT_WAIT_INFINITE, &eventBits); if ((result == _RESULT_SUCCESS) && (DEINIT_REQ_EVENT & eventBits)) { SchedTaskId qi; MessageQueueEntryType *message; /* * Pull any messages off the external queue and * put them on the relevant task queue. These may * be put here after we stopped because the sender * had not received its stop event yet. */ while (thread->extMsgQueueFirst != NULL) { /* remove from ext queue */ message = thread->extMsgQueueFirst; thread->extMsgQueueFirst = message->next; message->next = NULL; qi = message->receiver; /* ...store the on the end of the task's message chain. */ if (thread->tasks[qi].messageQueueLast == NULL) { thread->tasks[qi].messageQueueFirst = message; thread->tasks[qi].messageQueueLast = message; } else { thread->tasks[qi].messageQueueLast->next = message; thread->tasks[qi].messageQueueLast = message; } thread->pendingMessages++; } /* deinit all tasks in this scheduler thread and * return deinit cfm */ SchedInstanceTaskDeinit(thread); EventSet(&instance->eventHandle, DEINIT_CFM_EVENT | (0x0001 << (uint32) thread->id)); return; } else if (result != _RESULT_SUCCESS) { GENERROR(("Failure in wait for thread deinit req")); return; } } }
EXPORT extern void MdsEventWait(char *name, char *buf, int size, int *retSize) { EventWait(name, buf, size, retSize); }
BOOL UtMsgRcv (PVOID Data, PDWORD Size, PHANDLE Sender){ PLIST_ENTRY List , AUXQMSG , Entry; /*PUTHREAD */RunningThread = (PUTHREAD)UtSelf(); if(RunningThread->nMessages == 0){ Entry = QMSG.Flink; AUXQMSG = QMSG.Flink; do{ PBUFMSG m = CONTAINING_RECORD(AUXQMSG , BUFMSG , Link); if(m->Thread == (HANDLE)RunningThread){ RemoveHeadList(&QMSG); Data = m->Buffer; SaveValue = (DWORD)m->Buffer; Size = m->nSize; InterlockedDecrement(&nMsg); if(Sender != NULL) ClientId = m->Thread; return TRUE; } AUXQMSG = AUXQMSG->Flink; }while(AUXQMSG != Entry->Blink); ((PUTHREAD)UtSelf())->isWaiting = 1; EventWait(&RunningThread->ev); } RunningThread = (PUTHREAD)UtSelf(); if(RunningThread->nMessages == 0){ Entry = QMSG.Flink; AUXQMSG = QMSG.Flink; do{ PBUFMSG m = CONTAINING_RECORD(AUXQMSG , BUFMSG , Link); if(m->Thread == (HANDLE)RunningThread){ RemoveHeadList(&QMSG); Data = m->Buffer; SaveValue = (DWORD)m->Buffer; Size = m->nSize; InterlockedDecrement(&nMsg); if(Sender != NULL) ClientId = m->Thread; return TRUE; } AUXQMSG = AUXQMSG->Flink; }while(AUXQMSG != Entry->Blink); } List = RunningThread->MessageQueue.Flink; PMessage msg = (PMessage)CONTAINING_RECORD(List , Message, Link); if(msg->SizeBuffer > Size){ Size = msg->SizeBuffer; return FALSE; } InterlockedDecrement(&RunningThread->nMessages); RemoveHeadList(&RunningThread->MessageQueue); Data = msg->Buffer; SaveValue = (DWORD)msg->Buffer; Size = msg->SizeBuffer; if(Sender != NULL) Sender = (PHANDLE)RunningThread; return TRUE; }