BOOL UtMsgSend (HANDLE Dest, PVOID Data, DWORD Size){ PMessage m;PBUFMSG bm;DWORD xx; /*PUTHREAD*/ RunningThread = (PUTHREAD)Dest; if(RunningThread->isWaiting){ m = (PMessage)malloc(sizeof(Message)); m->Buffer = Data; m->SizeBuffer = (PDWORD)Size; InsertTailList(&RunningThread->MessageQueue , &m->Link); InterlockedIncrement(&RunningThread->nMessages); RunningThread->isWaiting = 0; EventSet(&RunningThread->ev); } else{ bm = (PBUFMSG)malloc(sizeof(BUFMSG)); bm->Buffer = Data; bm->nSize = (PDWORD)Size; bm->Thread = (PHANDLE)Dest; InsertTailList(&QMSG , &bm->Link); InterlockedIncrement(&nMsg); if(RunningThread->isWaiting) EventSet(&RunningThread->ev); } return TRUE; }
int sock_server_init_epoll(int &listenfd , uint16_t server_port) { listenfd = sock_server_init(listenfd, server_port); EventSet(&g_Events[MAX_EVENTS], listenfd, AcceptConn, &g_Events[MAX_EVENTS]); EventAdd(listenfd, EPOLLIN|EPOLLET, &g_Events[MAX_EVENTS]); return listenfd; }
int AcceptConn(int fd, int evetns, void *arg) { struct sockaddr_in sin; socklen_t len = sizeof(struct sockaddr_in); int clientfd, index; if((clientfd = accept( fd, (struct sockaddr * )&sin, &len)) == -1 ) { perror("accept"); return -1; } do{ for(index = 0; index < MAX_EVENTS; index++) { if(g_Events[index].status == 0)//not in list { break; } if(index == MAX_EVENTS) { perror("achieve MAX_EVENTS"); break; } if(fcntl(clientfd, F_SETFL, O_NONBLOCK) < 0) break; EventSet(&g_Events[index] , clientfd, RecvData, &g_Events[index]); EventAdd(g_epollfd, EPOLLIN|EPOLLET, &g_Events[index]); printf("new connection[%s:%d] at [time:%d]\n", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port),(int) g_Events[index].last_active); }//for }while(0); }
/*----------------------------------------------------------------------------* * NAME * SchedStop * * DESCRIPTION * Stop the scheduler in order to make the Sched() function return. * This is usually called from within a scheduler task like a demo-program * * RETURNS * void * *----------------------------------------------------------------------------*/ void SchedStop(void) { GENINFO(("SchedStop() called\n")); // _FUNC_ENTER(); /* Set flag to interrupt the Sched loop and wake it if it's * sleeping */ EventSet(&instance->eventHandle, STOP_REQ_EVENT); }
/*----------------------------------------------------------------------------* * NAME * SchedBgintSet * * DESCRIPTION * Set background interrupt. * * RETURNS * void. * *----------------------------------------------------------------------------*/ void SchedBgintSet(SchedBgint irq) { if (irq < BGINT_COUNT) { BgIntType *bgint; bgint = &instance->bgint[irq]; EventSet(bgint->eventHandle, bgint->eventBit); } else { /* Invalid bgint */ // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, "Invalid SchedBgint"); } }
int SendData(int fd, int events, void *arg) { struct myevent_s *ev = (struct myevent_s *)arg; int writeback = p_write_to_p(fd, "Hi this is server"); ev->len = 0; EventDel(g_epollfd, ev); if(writeback > 0) { EventSet(ev, fd, RecvData, ev); EventAdd(g_epollfd, EPOLLIN|EPOLLET, ev); } else { close(ev->fd); printf("send error %s , fd %d\n", strerror(errno), fd ); } }
NvResult CNvThreadingLinux::EventCreate(Handle *puEventHandle, bool bManual, bool bSet) { *puEventHandle = NV_HANDLE_INVALID; CConditionData *pCond = new CConditionData; if (!pCond) { return RESULT_OUT_OF_HANDLES; } pCond->manual = bManual; if (pthread_mutex_init(&pCond->mutex, NULL)) { delete pCond; return RESULT_OUT_OF_HANDLES; } if (pthread_cond_init(&pCond->condition, NULL)) { pthread_mutex_destroy(&pCond->mutex); delete pCond; return RESULT_OUT_OF_HANDLES; } *puEventHandle = (Handle)pCond; if (bSet) { EventSet(*puEventHandle); } else { EventReset(*puEventHandle); } return RESULT_OK; }
int RecvData(int fd, int events, void *arg) { struct myevent_s *ev = (struct myevent_s *)arg; int readback = p_read_from_p(fd); EventDel(g_epollfd, ev); if(readback > 0 ) { ev->len = readback; EventSet(ev, fd, SendData, ev); EventAdd(g_epollfd, EPOLLOUT|EPOLLET, ev); } else if(readback == 0) { close(ev->fd); printf("close fd %d gracefully\n", fd); } else { close(ev->fd); printf("recv error %s fd %d \n", strerror(errno), fd); } return readback; }
/*----------------------------------------------------------------------------* * 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; } } }
/*----------------------------------------------------------------------------* * NAME * do_put_message * * DESCRIPTION * Does the actual work of SchedMessagePut(). * * RETURNS * - * *----------------------------------------------------------------------------*/ static void do_put_message(Task dst, uint16 mi, void *mv) { ThreadInstanceType *src_thread; Task currentTask; uint16 qi; uint8 src_index, dest_index; src_index = GetThreadIndex(); if (src_index < _SCHED_MAX_SEGMENTS) { src_thread = &instance->thread[src_index]; currentTask = src_thread->currentTask; } else { src_thread = NULL; currentTask = _SCHED_TASK_ID; } /* Get segment and task index */ dest_index = QUEUE_EXTRACT_SEGMENT(dst); qi = QUEUE_EXTRACT_INDEX(dst); if (dest_index < _SCHED_MAX_SEGMENTS) { /* this message is destined for another sched task */ MessageQueueEntryType *message; ThreadInstanceType *dest_thread = &instance->thread[dest_index]; if (!dest_thread->inUse || (qi >= dest_thread->numberOfTasks)) { /* Task index is out-of-bounds */ GENERROR(("dest_thread->numberOfTasks=%d,qi=%d\n", dest_thread->numberOfTasks, qi)); GENERROR(("Invalid receiver task")); return; // Panic(_TECH_FW, _PANIC_FW_UNKNOWN_TASK, "Invalid receiver task"); } /* Package the message for queue storage. */ if (currentTask != _SCHED_TASK_ID) { message = messageAlloc(src_thread); } else { message = pnew(MessageQueueEntryType); } message->next = NULL; message->event = mi; message->sender = currentTask; message->message = mv; if (src_index == dest_index) { /* message to the calling thread */ TaskDefinitionType *task; task = &dest_thread->tasks[qi]; /* Store the message on the end of the task's message chain. */ if (task->messageQueueLast == NULL) { task->messageQueueFirst = message; task->messageQueueLast = message; } else { task->messageQueueLast->next = message; task->messageQueueLast = message; } dest_thread->pendingMessages++; } else { /* message to another thread than the calling */ message->receiver = qi; MutexLock(&dest_thread->qMutex); if (dest_thread->extMsgQueueLast == NULL) { dest_thread->extMsgQueueFirst = message; dest_thread->extMsgQueueLast = message; } else { dest_thread->extMsgQueueLast->next = message; dest_thread->extMsgQueueLast = message; } MutexUnlock(&dest_thread->qMutex); EventSet(&dest_thread->eventHandle, EXT_MSG_EVENT); } } else { /* this message is destined for an external receiver */ if (externalSend != NULL) { /* Message flagged for remote scheduler/thread thingy */ externalSend(dst, mi, mv); } else { /* Not handler for this segment! */ // Panic(_TECH_FW, _PANIC_FW_UNKNOWN_TASK, // "Invalid destination queue or no external send function registered"); } } }