Example #1
0
/*----------------------------------------------------------------------------*
 *  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;
    }
}
Example #2
0
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;
}
Example #3
0
/*----------------------------------------------------------------------------*
 *  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;
}
Example #4
0
/*----------------------------------------------------------------------------*
 *  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");
        }
    }
}
Example #5
0
/*----------------------------------------------------------------------------*
 *  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;
}
Example #6
0
/*----------------------------------------------------------------------------*
 *  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;
}
Example #7
0
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);
}