Example #1
0
/* Enables queue_send on the specified queue - caller allocates the extra
 * data structure. Only queues which are taken to be owned by a thread should
 * enable this however an official owner is not compulsory but must be
 * specified for priority inheritance to operate.
 *
 * Use of queue_wait(_w_tmo) by multiple threads on a queue using synchronous
 * messages results in an undefined order of message replies or possible default
 * replies if two or more waits happen before a reply is done.
 */
void queue_enable_queue_send(struct event_queue *q,
                             struct queue_sender_list *send,
                             unsigned int owner_id)
{
    int oldlevel = disable_irq_save();
    corelock_lock(&q->cl);

    if(send != NULL && q->send == NULL)
    {
        memset(send, 0, sizeof(*send));
#ifdef HAVE_PRIORITY_SCHEDULING
        send->blocker.wakeup_protocol = wakeup_priority_protocol_release;
        send->blocker.priority = PRIORITY_IDLE;
        if(owner_id != 0)
        {
            send->blocker.thread = thread_id_entry(owner_id);
            q->blocker_p = &send->blocker;
        }
#endif
        q->send = send;
    }

    corelock_unlock(&q->cl);
    restore_irq(oldlevel);

    (void)owner_id;
}
Example #2
0
void thread_exit(void)
{
    remove_thread(THREAD_ID_CURRENT);
    /* This should never and must never be reached - if it is, the
     * state is corrupted */
    THREAD_PANICF("thread_exit->K:*R",
                  thread_id_entry(THREAD_ID_CURRENT));
    while (1);
}
Example #3
0
void remove_thread(unsigned int thread_id)
#endif
{
    struct thread_entry *current = cores[CURRENT_CORE].running;
    struct thread_entry *thread = thread_id_entry(thread_id);

    SDL_Thread *t;
    SDL_sem *s;

    if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id)
        return;

    int oldlevel = disable_irq_save();

    t = thread->context.t;
    s = thread->context.s;
    thread->context.t = NULL;

    if (thread != current)
    {
        switch (thread->state)
        {
        case STATE_BLOCKED:
        case STATE_BLOCKED_W_TMO:
            /* Remove thread from object it's waiting on */
            remove_from_list_l(thread->bqp, thread);

#ifdef HAVE_WAKEUP_EXT_CB
            if (thread->wakeup_ext_cb != NULL)
                thread->wakeup_ext_cb(thread);
#endif
            break;
        }

        SDL_SemPost(s);
    }

    THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n",
        thread - threads, THREAD_SDL_GET_NAME(thread));

    new_thread_id(thread->id, thread);
    thread->state = STATE_KILLED;
    thread_queue_wake(&thread->queue);

    SDL_DestroySemaphore(s);

    if (thread == current)
    {
        /* Do a graceful exit - perform the longjmp back into the thread
           function to return */
        restore_irq(oldlevel);
        longjmp(thread_jmpbufs[current - threads], 1);
    }

    SDL_KillThread(t);
    restore_irq(oldlevel);
}
Example #4
0
void thread_thaw(unsigned int thread_id)
{
    struct thread_entry *thread = thread_id_entry(thread_id);

    if (thread->id == thread_id && thread->state == STATE_FROZEN)
    {
        thread->state = STATE_RUNNING;
        SDL_SemPost(thread->context.s);
    }
}
Example #5
0
void lcd_remote_on(void)
{
    /* Only wake the remote thread if it's in the blocked state. */
    struct thread_entry *rc_thread = thread_id_entry(remote_thread_id);
    if (rc_thread->state == STATE_BLOCKED || (rc_status & RC_FORCE_DETECT))
    {
        rc_status &= ~RC_FORCE_DETECT;
        rc_status &= ~RC_POWER_OFF;
        semaphore_release(&rc_thread_wakeup);
    }
}
void thread_wait(unsigned int thread_id)
{
    struct thread_entry *current = cores[CURRENT_CORE].running;
    struct thread_entry *thread = thread_id_entry(thread_id);

    if (thread->id == thread_id && thread->state != STATE_KILLED)
    {
        current->bqp = &thread->queue;
        block_thread(current);
        switch_thread();
    }
}
Example #7
0
File: ata.c Project: Megaco/rockbox
static void ata_lock_lock(struct ata_lock *l)
{
    struct thread_entry * const current =
        thread_id_entry(THREAD_ID_CURRENT);

    if (current == l->thread)
    {
        l->count++;
        return;
    }

    corelock_lock(&l->cl);

    IF_PRIO( current->skip_count = -1; )

    while (l->locked != 0)
Example #8
0
void remove_thread(unsigned int thread_id)
#endif
{
    struct thread_entry *current = cores[CURRENT_CORE].running;
    struct thread_entry *thread = thread_id_entry(thread_id);

    SDL_Thread *t;
    SDL_sem *s;

    if (thread_id != THREAD_ID_CURRENT && thread->id != thread_id)
        return;

    int oldlevel = disable_irq_save();

    t = thread->context.t;
    s = thread->context.s;

    /* Wait the last thread here and keep this one or SDL will leak it since
     * it doesn't free its own library allocations unless a wait is performed.
     * Such behavior guards against the memory being invalid by the time
     * SDL_WaitThread is reached and also against two different threads having
     * the same pointer. It also makes SDL_WaitThread a non-concurrent function.
     *
     * However, see more below about SDL_KillThread.
     */
    SDL_WaitThread(thread->context.told, NULL);

    thread->context.t = NULL;
    thread->context.s = NULL;
    thread->context.told = t;

    if (thread != current)
    {
        switch (thread->state)
        {
        case STATE_BLOCKED:
        case STATE_BLOCKED_W_TMO:
            /* Remove thread from object it's waiting on */
            remove_from_list_l(thread->bqp, thread);

#ifdef HAVE_WAKEUP_EXT_CB
            if (thread->wakeup_ext_cb != NULL)
                thread->wakeup_ext_cb(thread);
#endif
            break;
        }

        SDL_SemPost(s);
    }

    THREAD_SDL_DEBUGF("Removing thread: %d (%s)\n",
                      thread - threads, THREAD_SDL_GET_NAME(thread));

    new_thread_id(thread->id, thread);
    thread->state = STATE_KILLED;
    thread_queue_wake(&thread->queue);

    SDL_DestroySemaphore(s);

    if (thread == current)
    {
        /* Do a graceful exit - perform the longjmp back into the thread
           function to return */
        restore_irq(oldlevel);
        longjmp(thread_jmpbufs[current - threads], 1);
    }

    /* SDL_KillThread frees the old pointer too because it uses SDL_WaitThread
     * to wait for the host to remove it. */
    thread->context.told = NULL;
    SDL_KillThread(t);
    restore_irq(oldlevel);
}