/*----------------------------------------------------------------------------* * NAME * SchedTaskQueueGet * * DESCRIPTION * Return the queue identifier for the currently running queue * * RETURNS * task - The current task queue identifier, or _SCHED_TASK_ID if not available. * *----------------------------------------------------------------------------*/ Task SchedTaskQueueGet(void) { uint8 index = GetThreadIndex(); if (index < _SCHED_MAX_SEGMENTS) { return instance->thread[index].currentTask; } else { return _SCHED_TASK_ID; } }
SchedBgint SchedBgintReg(SchedBgintHandler cb, void *context) { SchedBgint irq; uint8 index; irq = _SCHED_BGINT_INVALID; index = GetThreadIndex(); if (index < _SCHED_MAX_SEGMENTS) { ThreadInstanceType *thread; thread = &instance->thread[index]; if (cb != NULL) { uint8 hdlcount; hdlcount = sizeof(instance->bgint) / sizeof(instance->bgint[0]); MutexLock(&instance->bgMutex); irq = 0; while (irq < hdlcount && instance->bgint[irq].handler != NULL) { irq ++; } if (irq < hdlcount) { instance->bgint[irq].qid = thread->currentTask; instance->bgint[irq].handler = cb; instance->bgint[irq].arg = context; instance->bgint[irq].eventHandle = &thread->eventHandle; instance->bgint[irq].eventBit = 1 << irq; } else { irq = _SCHED_BGINT_INVALID; } MutexUnlock(&instance->bgMutex); } else { irq = _SCHED_BGINT_INVALID; } } else { // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, // "SchedBgintReg not called from scheduler thread"); } return irq; }
/*----------------------------------------------------------------------------* * NAME * SchedMessageGet * * DESCRIPTION * Obtains a message from the message queue "q" if one is available. The * calling task must own "q". The message consists of one or both of a * uint16 and a void *. * * If the calling task does not own "q" then the scheduler calls panic(). * * RETURNS * BOOL - true if a message has been obtained from the queue, else false. * If a message is taken from the queue, then "*pmi" and "*pmv" are set to * the "mi" and "mv" passed to SchedMessagePut() respectively. * * "pmi" and "pmv" can be null, in which case the corresponding value from * them message is discarded. * *----------------------------------------------------------------------------*/ bool SchedMessageGet(uint16 *pmi, void **pmv) { bool rv; uint8 index; index = GetThreadIndex(); if (index < _SCHED_MAX_SEGMENTS) { ThreadInstanceType *thread; MessageQueueEntryType *message; TaskDefinitionType *task; int qi; thread = &instance->thread[index]; /* Try to remove message from the base of the message chain. */ qi = QUEUE_EXTRACT_INDEX(thread->currentTask); task = &thread->tasks[qi]; message = task->messageQueueFirst; if (message) { if (pmi) { *pmi = message->event; } if (pmv) { *pmv = message->message; } task->messageQueueFirst = message->next; if (task->messageQueueLast == message) { /* Removed the final element */ task->messageQueueLast = NULL; } --thread->pendingMessages; messageFree(thread, message); rv = TRUE; } else { rv = FALSE; } } else { rv = FALSE; // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, // "SchedMessageGet not called from scheduler thread"); } return rv; }
/*----------------------------------------------------------------------------* * 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"); } } }
/*----------------------------------------------------------------------------* * NAME * SchedTimerCancel * * DESCRIPTION * Attempts to prevent the timer with identifier "eventid" from * occurring. * * RETURNS * BOOL - true if cancelled, false if the event has already occurred. * *----------------------------------------------------------------------------*/ bool SchedTimerCancel(SchedTid tid, uint16 *pmi, void **pmv) { bool rv; if (tid != _SCHED_TID_INVALID) { uint8 index; index = GetThreadIndex(); if (index < _SCHED_MAX_SEGMENTS) { ThreadInstanceType *thread; TimerType *timer; thread = &instance->thread[index]; /* Unlink the timer from the list. */ timer = thread->timer[tid]; if (timer && timer->active) { TimerType *prev, *next; timer->active = FALSE; rv = TRUE; prev = timer->prev; next = timer->next; if ((prev != NULL) && (next != NULL)) { /* In the middle of the list. */ next->prev = prev; prev->next = next; } else if ((prev == NULL) && (next != NULL)) { /* Removing the list head. */ thread->timerList = next; next->prev = NULL; } else if ((prev != NULL) && (next == NULL)) { /* Removing the list tail. */ prev->next = NULL; } else { /* Removing the only active timer. */ thread->timerList = NULL; } if (pmi != NULL) { *pmi = timer->fniarg; } if (pmv != NULL) { *pmv = timer->fnvarg; } timerFree(thread, timer); } else { rv = FALSE; } } else { rv = FALSE; // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, // "SchedTimerCancel not called from scheduler thread"); } } else { rv = FALSE; } return rv; }
/*----------------------------------------------------------------------------* * NAME * SchedTimerSet * * DESCRIPTION * Causes the void function "fn" to be called with the arguments * "fniarg" and "fnvarg" after "delay" has elapsed. * * "delay" must be less than half the range of a Time. * * SchedTimerSet() does nothing with "fniarg" and "fnvarg" except * deliver them via a call to "fn()". (Unless SchedTimerCancel() * is used to prevent delivery.) * * NOTE * The function will be called at or after "delay"; the actual delay will * depend on the timing behaviour of the scheduler's tasks. * * RETURNS * SchedTid - A timer identifier, can be used in SchedTimerCancel(). * *----------------------------------------------------------------------------*/ SchedTid SchedTimerSet(Time delay, void (*fn)(SchedTid timerid, uint16 mi, void *mv), uint16 fniarg, void *fnvarg) { SchedTid tid; uint8 index; index = GetThreadIndex(); if (index < _SCHED_MAX_SEGMENTS) { ThreadInstanceType *thread; TimerType *newTimer; Time when; Time now; uint32 whenWrapCount; thread = &instance->thread[index]; newTimer = timerAlloc(thread); /* Get absolute time of event */ now = TimeGet(NULL); when = TimeAdd(now, delay); if (when < now) { whenWrapCount = 1; } else { whenWrapCount = 0; } /* Build the structure. */ newTimer->when = when; newTimer->wrapCount = whenWrapCount; newTimer->eventFunction = fn; newTimer->fniarg = fniarg; newTimer->fnvarg = fnvarg; newTimer->queue = thread->currentTask; newTimer->active = TRUE; /* Handle timer wrap */ adjust_wrap_count(thread, now); newTimer->wrapCount += thread->currentWrapCount; /* Store struct in time position in the timer list. */ if (thread->timerList == NULL) { newTimer->prev = NULL; newTimer->next = NULL; thread->timerList = newTimer; } else { TimerType *ptr, *prev; ptr = thread->timerList; prev = NULL; /* Determine where to insert element */ while (ptr) { if (((ptr->when > newTimer->when) && (ptr->wrapCount == newTimer->wrapCount)) || (ptr->wrapCount > newTimer->wrapCount)) { break; } else { prev = ptr; ptr = ptr->next; } } newTimer->prev = prev; newTimer->next = ptr; if (prev != NULL) { prev->next = newTimer; } else { thread->timerList = newTimer; } if (ptr != NULL) { ptr->prev = newTimer; } } tid = newTimer->id; } else { tid = _SCHED_TID_INVALID; // Panic(_TECH_FW, _PANIC_FW_UNEXPECTED_VALUE, // "SchedTimerSet not called from scheduler thread"); } return tid; }
static void display_line_log(log_stream_t *p_log, const char *tag, const char *format, va_list arglist) { char line_log[MAX_LINE_LEN]; int written; time_t now = time(NULL); unsigned int th = GetThreadIndex(); struct tm date; int would_print; if (log_initialized) { /* periodically check if log files have been renamed */ if (now - last_time_test > TIME_TEST_FILE) { test_file_names(); last_time_test = now; } } pthread_rwlock_rdlock(&p_log->f_lock); /* if logs are not initalized or the log is a NULL FILE*, * default logging to stderr */ if ((!log_initialized) || ((p_log->log_type != RBH_LOG_SYSLOG) && (p_log->f_log == NULL))) { localtime_r(&now, &date); written = snprintf(line_log, MAX_LINE_LEN, "%.4d/%.2d/%.2d %.2d:%.2d:%.2d %s[%lu/%u] %s%s", 1900 + date.tm_year, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec, log_config.log_process ? "robinhood" : "", (unsigned long)getpid(), th, tag ? tag : "", tag ? " | " : ""); would_print = vsnprintf(line_log + written, MAX_LINE_LEN - written, format, arglist); clean_str(line_log); if (would_print >= MAX_LINE_LEN - written) fprintf(stderr, "%s... <Line truncated. Original size=%u>\n", line_log, would_print); else fprintf(stderr, "%s\n", line_log); } else if (p_log->log_type == RBH_LOG_SYSLOG) { /* add tag to syslog line */ char new_format[MAX_LINE_LEN]; if (tag) snprintf(new_format, MAX_LINE_LEN, "%s | %s", tag, format); else rh_strncpy(new_format, format, MAX_LINE_LEN); vsyslog(log_config.syslog_priority, new_format, arglist); } else { /* log to a file */ localtime_r(&now, &date); written = snprintf(line_log, MAX_LINE_LEN, "%.4d/%.2d/%.2d %.2d:%.2d:%.2d %s%s%s[%lu/%u] %s%s", 1900 + date.tm_year, date.tm_mon + 1, date.tm_mday, date.tm_hour, date.tm_min, date.tm_sec, log_config.log_process ? prog_name : "", log_config.log_host ? "@" : "", log_config.log_host ? machine_name : "", (unsigned long)getpid(), th, tag ? tag : "", tag ? " | " : ""); would_print = vsnprintf(line_log + written, MAX_LINE_LEN - written, format, arglist); clean_str(line_log); if (p_log->f_log != NULL) { if (would_print >= MAX_LINE_LEN - written) fprintf(p_log->f_log, "%s... <Line truncated. Original size=%u>\n", line_log, would_print); else fprintf(p_log->f_log, "%s\n", line_log); } } pthread_rwlock_unlock(&p_log->f_lock); }