示例#1
0
文件: thread-sdl.c 项目: ntj/rockbox
unsigned int create_thread(void (*function)(void),
                           void* stack, size_t stack_size,
                           unsigned flags, const char *name)
{
    struct thread_entry *thread;
    SDL_Thread* t;
    SDL_sem *s;

    THREAD_SDL_DEBUGF("Creating thread: (%s)\n", name ? name : "");

    thread = find_empty_thread_slot();
    if (thread == NULL)
    {
        DEBUGF("Failed to find thread slot\n");
        return 0;
    }

    s = SDL_CreateSemaphore(0);
    if (s == NULL)
    {
        DEBUGF("Failed to create semaphore\n");
        return 0;
    }

    t = SDL_CreateThread(runthread, thread);
    if (t == NULL)
    {
        DEBUGF("Failed to create SDL thread\n");
        SDL_DestroySemaphore(s);
        return 0;
    }

    thread->stack = stack;
    thread->stack_size = stack_size;
    thread->name = name;
    thread->state = (flags & CREATE_THREAD_FROZEN) ?
                    STATE_FROZEN : STATE_RUNNING;
    thread->context.start = function;
    thread->context.t = t;
    thread->context.s = s;

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

    return thread->id;
}
示例#2
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);
}
示例#3
0
void init_threads(void)
{
    /* Main thread is already initialized */
    if (cores[CURRENT_CORE].running != &threads[0])
    {
        THREAD_PANICF("Wrong main thread in init_threads: %p\n",
                      cores[CURRENT_CORE].running);
    }

    THREAD_SDL_DEBUGF("First Thread: %d (%s)\n",
            0, THREAD_SDL_GET_NAME(&threads[0]));
}
示例#4
0
/* Initialize SDL threading */
bool thread_sdl_init(void *param)
{
    struct thread_entry *thread;
    int n;

    memset(cores, 0, sizeof(cores));
    memset(threads, 0, sizeof(threads));

    m = SDL_CreateMutex();

    if (SDL_LockMutex(m) == -1)
    {
        fprintf(stderr, "Couldn't lock mutex\n");
        return false;
    }

    /* Initialize all IDs */
    for (n = 0; n < MAXTHREADS; n++)
        threads[n].id = THREAD_ID_INIT(n);

    /* Slot 0 is reserved for the main thread - initialize it here and
       then create the SDL thread - it is possible to have a quick, early
       shutdown try to access the structure. */
    thread = &threads[0];
    thread->stack = (uintptr_t *)"       ";
    thread->stack_size = 8;
    thread->name = "main";
    thread->state = STATE_RUNNING;
    thread->context.s = SDL_CreateSemaphore(0);
    cores[CURRENT_CORE].running = thread;
 
    if (thread->context.s == NULL)
    {
        fprintf(stderr, "Failed to create main semaphore\n");
        return false;
    }

    thread->context.t = SDL_CreateThread(thread_sdl_app_main, param);

    if (thread->context.t == NULL)
    {
        SDL_DestroySemaphore(thread->context.s);
        fprintf(stderr, "Failed to create main thread\n");
        return false;
    }

    THREAD_SDL_DEBUGF("Main thread: %p\n", thread);

    SDL_UnlockMutex(m);
    return true;
}
示例#5
0
文件: thread-sdl.c 项目: ntj/rockbox
int runthread(void *data)
{
    struct thread_entry *current;
    jmp_buf *current_jmpbuf;

    /* Cannot access thread variables before locking the mutex as the
       data structures may not be filled-in yet. */
    SDL_LockMutex(m);
    cores[CURRENT_CORE].running = (struct thread_entry *)data;
    current = cores[CURRENT_CORE].running;
    current_jmpbuf = &thread_jmpbufs[current - threads];

    /* Setup jump for exit */
    if (setjmp(*current_jmpbuf) == 0)
    {
        /* Run the thread routine */
        if (current->state == STATE_FROZEN)
        {
            SDL_UnlockMutex(m);
            SDL_SemWait(current->context.s);
            SDL_LockMutex(m);
            cores[CURRENT_CORE].running = current;
        }

        if (threads_status == THREADS_RUN)
        {
            current->context.start();
            THREAD_SDL_DEBUGF("Thread Done: %d (%s)\n",
                              current - threads, THREAD_SDL_GET_NAME(current));
            /* Thread routine returned - suicide */
        }

        thread_exit();
    }
    else
    {
        /* Unlock and exit */
        SDL_UnlockMutex(m);
    }

    return 0;
}
示例#6
0
文件: thread-sdl.c 项目: ntj/rockbox
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);
}
示例#7
0
文件: thread-sdl.c 项目: ntj/rockbox
/* Initialize SDL threading */
void init_threads(void)
{
    struct thread_entry *thread;
    int n;

    memset(cores, 0, sizeof(cores));
    memset(threads, 0, sizeof(threads));

    m = SDL_CreateMutex();

    if (SDL_LockMutex(m) == -1)
    {
        fprintf(stderr, "Couldn't lock mutex\n");
        return;
    }

    /* Initialize all IDs */
    for (n = 0; n < MAXTHREADS; n++)
        threads[n].id = THREAD_ID_INIT(n);

    /* Slot 0 is reserved for the main thread - initialize it here and
       then create the SDL thread - it is possible to have a quick, early
       shutdown try to access the structure. */
    thread = &threads[0];
    thread->stack = (uintptr_t *)"       ";
    thread->stack_size = 8;
    thread->name = "main";
    thread->state = STATE_RUNNING;
    thread->context.s = SDL_CreateSemaphore(0);
    thread->context.t = NULL; /* NULL for the implicit main thread */
    cores[CURRENT_CORE].running = thread;

    if (thread->context.s == NULL)
    {
        fprintf(stderr, "Failed to create main semaphore\n");
        return;
    }

    /* Tell all threads jump back to their start routines, unlock and exit
       gracefully - we'll check each one in turn for it's status. Threads
       _could_ terminate via remove_thread or multiple threads could exit
       on each unlock but that is safe. */

    /* Setup jump for exit */
    if (setjmp(thread_jmpbufs[0]) == 0)
    {
        THREAD_SDL_DEBUGF("Main thread: %p\n", thread);
        return;
    }

    SDL_UnlockMutex(m);

    /* Set to 'COMMAND_DONE' when other rockbox threads have exited. */
    while (threads_status < THREADS_EXIT_COMMAND_DONE)
        SDL_Delay(10);

    SDL_DestroyMutex(m);

    /* We're the main thead - perform exit - doesn't return. */
    sim_do_exit();
}