Back to index

lightning-sunbird  0.9+nobinonly
Functions | Variables
prulock.c File Reference
#include "primpl.h"

Go to the source code of this file.

Functions

void _PR_InitLocks (void)
void _PR_IntsOn (_PRCPU *cpu)
void _PR_UnblockLockWaiter (PRLock *lock)
 PR_IMPLEMENT (PRLock *)
 PR_IMPLEMENT (void)
 PR_IMPLEMENT (PRStatus)
 PR_IMPLEMENT (PRBool)

Variables

PRThreadsuspendAllThread

Function Documentation

Definition at line 51 of file prulock.c.

Here is the caller graph for this function:

void _PR_IntsOn ( _PRCPU cpu)

Definition at line 60 of file prulock.c.

{
    PRUintn missed, pri, i;
    _PRInterruptTable *it;
    PRThread *me;

    PR_ASSERT(cpu);   /* Global threads don't have CPUs */
    PR_ASSERT(_PR_MD_GET_INTSOFF() > 0);
       me = _PR_MD_CURRENT_THREAD();
#if !defined(XP_MAC)
    PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
#endif

    /*
    ** Process delayed interrupts. This logic is kinda scary because we
    ** need to avoid losing an interrupt (it's ok to delay an interrupt
    ** until later).
    **
    ** There are two missed state words. _pr_ints.where indicates to the
    ** interrupt handler which state word is currently safe for
    ** modification.
    **
    ** This code scans both interrupt state words, using the where flag
    ** to indicate to the interrupt which state word is safe for writing.
    ** If an interrupt comes in during a scan the other word will be
    ** modified. This modification will be noticed during the next
    ** iteration of the loop or during the next call to this routine.
    */
    for (i = 0; i < 2; i++) {
        cpu->where = (1 - i);
        missed = cpu->u.missed[i];
        if (missed != 0) {
            cpu->u.missed[i] = 0;
            for (it = _pr_interruptTable; it->name; it++) {
                if (missed & it->missed_bit) {
#ifndef XP_MAC
                    PR_LOG(_pr_sched_lm, PR_LOG_MIN,
                           ("IntsOn[0]: %s intr", it->name));
#endif
                    (*it->handler)();
                }
            }
        }
    }

    if (cpu->u.missed[3] != 0) {
        _PRCPU *cpu;

              _PR_THREAD_LOCK(me);
        me->state = _PR_RUNNABLE;
        pri = me->priority;

        cpu = me->cpu;
              _PR_RUNQ_LOCK(cpu);
        _PR_ADD_RUNQ(me, cpu, pri);
              _PR_RUNQ_UNLOCK(cpu);
              _PR_THREAD_UNLOCK(me);
        _PR_MD_SWITCH_CONTEXT(me);
    }
}

Here is the call graph for this function:

Definition at line 126 of file prulock.c.

{
    PRThread *t = NULL;
    PRThread *me;
    PRCList *q;

    q = lock->waitQ.next;
    PR_ASSERT(q != &lock->waitQ);
    while (q != &lock->waitQ) {
        /* Unblock first waiter */
        t = _PR_THREAD_CONDQ_PTR(q);

              /* 
              ** We are about to change the thread's state to runnable and for local
              ** threads, we are going to assign a cpu to it.  So, protect thread's
              ** data structure.
              */
        _PR_THREAD_LOCK(t);

        if (t->flags & _PR_SUSPENDING) {
            q = q->next;
            _PR_THREAD_UNLOCK(t);
            continue;
        }

        /* Found a runnable thread */
           PR_ASSERT(t->state == _PR_LOCK_WAIT);
           PR_ASSERT(t->wait.lock == lock);
        t->wait.lock = 0;
        PR_REMOVE_LINK(&t->waitQLinks);         /* take it off lock's waitQ */

              /*
              ** If this is a native thread, nothing else to do except to wake it
              ** up by calling the machine dependent wakeup routine.
              **
              ** If this is a local thread, we need to assign it a cpu and
              ** put the thread on that cpu's run queue.  There are two cases to
              ** take care of.  If the currently running thread is also a local
              ** thread, we just assign our own cpu to that thread and put it on
              ** the cpu's run queue.  If the the currently running thread is a
              ** native thread, we assign the primordial cpu to it (on NT,
              ** MD_WAKEUP handles the cpu assignment).  
              */
              
        if ( !_PR_IS_NATIVE_THREAD(t) ) {

            t->state = _PR_RUNNABLE;

            me = _PR_MD_CURRENT_THREAD();

            _PR_AddThreadToRunQ(me, t);
            _PR_THREAD_UNLOCK(t);
        } else {
            t->state = _PR_RUNNING;
            _PR_THREAD_UNLOCK(t);
        }
        _PR_MD_WAKEUP_WAITER(t);
        break;
    }
    return;
}

Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 191 of file prulock.c.

{
    PRLock *lock;

    if (!_pr_initialized) _PR_ImplicitInitialization();

    lock = PR_NEWZAP(PRLock);
    if (lock) {
        if (_PR_MD_NEW_LOCK(&lock->ilock) == PR_FAILURE) {
              PR_DELETE(lock);
              return(NULL);
       }
        PR_INIT_CLIST(&lock->links);
        PR_INIT_CLIST(&lock->waitQ);
    }
    return lock;
}

Here is the call graph for this function:

Definition at line 214 of file prulock.c.

{
    PR_ASSERT(lock->owner == 0);
       _PR_MD_FREE_LOCK(&lock->ilock);
    PR_DELETE(lock);
}

Definition at line 336 of file prulock.c.

{
    PRCList *q;
    PRThreadPriority pri, boost;
    PRIntn is;
    PRThread *me = _PR_MD_CURRENT_THREAD();

    PR_ASSERT(lock != NULL);
    PR_ASSERT(lock->owner == me);
    PR_ASSERT(me != suspendAllThread); 
#if !defined(XP_MAC)
    PR_ASSERT(!(me->flags & _PR_IDLE_THREAD));
#endif
    if (lock->owner != me) {
        return PR_FAILURE;
    }

#ifdef _PR_GLOBAL_THREADS_ONLY 
    lock->owner = 0;
    _PR_MD_UNLOCK(&lock->ilock);
    return PR_SUCCESS;
#else  /* _PR_GLOBAL_THREADS_ONLY */

       if (_native_threads_only) {
              lock->owner = 0;
              _PR_MD_UNLOCK(&lock->ilock);
              return PR_SUCCESS;
       }

    if (!_PR_IS_NATIVE_THREAD(me))
       _PR_INTSOFF(is);
    _PR_LOCK_LOCK(lock);

       /* Remove the lock from the owning thread's lock list */
    PR_REMOVE_LINK(&lock->links);
    pri = lock->priority;
    boost = lock->boostPriority;
    if (boost > pri) {
        /*
        ** We received a priority boost during the time we held the lock.
        ** We need to figure out what priority to move to by scanning
        ** down our list of lock's that we are still holding and using
        ** the highest boosted priority found.
        */
        q = me->lockList.next;
        while (q != &me->lockList) {
            PRLock *ll = _PR_LOCK_PTR(q);
            if (ll->boostPriority > pri) {
                pri = ll->boostPriority;
            }
            q = q->next;
        }
        if (pri != me->priority) {
            _PR_SetThreadPriority(me, pri);
        }
    }

    /* Unblock the first waiting thread */
    q = lock->waitQ.next;
    if (q != &lock->waitQ)
        _PR_UnblockLockWaiter(lock);
    lock->boostPriority = PR_PRIORITY_LOW;
    lock->owner = 0;
    _PR_LOCK_UNLOCK(lock);
    if (!_PR_IS_NATIVE_THREAD(me))
       _PR_INTSON(is);
    return PR_SUCCESS;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

Here is the call graph for this function:

Definition at line 411 of file prulock.c.

{
    PRThread *me = _PR_MD_CURRENT_THREAD();
    PRBool rv = PR_FALSE;
    PRIntn is;

#ifdef _PR_GLOBAL_THREADS_ONLY 
    is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
    if (is == 0) {
        lock->owner = me;
        return PR_TRUE;
    }
    return PR_FALSE;
#else  /* _PR_GLOBAL_THREADS_ONLY */

#ifndef _PR_LOCAL_THREADS_ONLY
       if (_native_threads_only) {
              is = _PR_MD_TEST_AND_LOCK(&lock->ilock);
              if (is == 0) {
                     lock->owner = me;
                     return PR_TRUE;
              }
       return PR_FALSE;
       }
#endif

    if (!_PR_IS_NATIVE_THREAD(me))
       _PR_INTSOFF(is);

    _PR_LOCK_LOCK(lock);
    if (lock->owner == 0) {
        /* Just got the lock */
        lock->owner = me;
        lock->priority = me->priority;
              /* Add the granted lock to this owning thread's lock list */
        PR_APPEND_LINK(&lock->links, &me->lockList);
        rv = PR_TRUE;
    }
    _PR_LOCK_UNLOCK(lock);

    if (!_PR_IS_NATIVE_THREAD(me))
       _PR_INTSON(is);
    return rv;
#endif  /* _PR_GLOBAL_THREADS_ONLY */
}

Variable Documentation

Definition at line 87 of file pruthr.c.