コード例 #1
0
/* Up the semaphore's count and release any thread waiting at the head of the
 * queue. The count is saturated to the value of the 'max' parameter specified
 * in 'semaphore_init'. */
void semaphore_release(struct semaphore *s)
{
    unsigned int result = THREAD_NONE;

    int oldlevel = disable_irq_save();
    corelock_lock(&s->cl);

    struct thread_entry *thread = WQ_THREAD_FIRST(&s->queue);
    if(LIKELY(thread != NULL))
    {
        /* a thread was queued - wake it up and keep count at 0 */
        KERNEL_ASSERT(s->count == 0,
            "semaphore_release->threads queued but count=%d!\n", s->count);
        result = wakeup_thread(thread, WAKEUP_DEFAULT);
    }
    else
    {
        int count = s->count;
        if(count < s->max)
        {
            /* nothing waiting - up it */
            s->count = count + 1;
        }
    }

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

#if defined(HAVE_PRIORITY_SCHEDULING) && defined(is_thread_context)
    /* No thread switch if not thread context */
    if((result & THREAD_SWITCH) && is_thread_context())
        switch_thread();
#endif
    (void)result;
}
コード例 #2
0
ファイル: mutex.c プロジェクト: Brandon7357/rockbox
/* Release ownership of a mutex object - only owning thread must call this */
void mutex_unlock(struct mutex *m)
{
    /* unlocker not being the owner is an unlocking violation */
    KERNEL_ASSERT(m->blocker.thread == __running_self_entry(),
                  "mutex_unlock->wrong thread (%s != %s)\n",
                  m->blocker.thread->name,
                  __running_self_entry()->name);

    if(m->recursion > 0)
    {
        /* this thread still owns lock */
        m->recursion--;
        return;
    }

    /* lock out other cores */
    corelock_lock(&m->cl);

    /* transfer to next queued thread if any */
    struct thread_entry *thread = WQ_THREAD_FIRST(&m->queue);
    if(LIKELY(thread == NULL))
    {
        /* no threads waiting - open the lock */
        m->blocker.thread = NULL;
        corelock_unlock(&m->cl);
        return;
    }

    const int oldlevel = disable_irq_save();
    /* Tranfer of owning thread is handled in the wakeup protocol
     * if priorities are enabled otherwise just set it from the
     * queue head. */
#ifndef HAVE_PRIORITY_SCHEDULING
    m->blocker.thread = thread;
#endif
    unsigned int result = wakeup_thread(thread, WAKEUP_TRANSFER);
    restore_irq(oldlevel);

    corelock_unlock(&m->cl);

#ifdef HAVE_PRIORITY_SCHEDULING
    if(result & THREAD_SWITCH)
        switch_thread();
#endif
    (void)result;
}