Example #1
0
void
runtime_lock(Lock *l)
{
    M *m;
    uintptr v;
    uint32 i, spin;

    m = runtime_m();
    if(m->locks++ < 0)
        runtime_throw("runtime_lock: lock count");

    // Speculative grab for lock.
    if(runtime_casp((void**)&l->key, nil, (void*)LOCKED))
        return;

    if(m->waitsema == 0)
        m->waitsema = runtime_semacreate();

    // On uniprocessor's, no point spinning.
    // On multiprocessors, spin for ACTIVE_SPIN attempts.
    spin = 0;
    if(runtime_ncpu > 1)
        spin = ACTIVE_SPIN;

    for(i=0;; i++) {
        v = (uintptr)runtime_atomicloadp((void**)&l->key);
        if((v&LOCKED) == 0) {
unlocked:
            if(runtime_casp((void**)&l->key, (void*)v, (void*)(v|LOCKED)))
                return;
            i = 0;
        }
        if(i<spin)
            runtime_procyield(ACTIVE_SPIN_CNT);
        else if(i<spin+PASSIVE_SPIN)
            runtime_osyield();
        else {
            // Someone else has it.
            // l->waitm points to a linked list of M's waiting
            // for this lock, chained through m->nextwaitm.
            // Queue this M.
            for(;;) {
                m->nextwaitm = (void*)(v&~LOCKED);
                if(runtime_casp((void**)&l->key, (void*)v, (void*)((uintptr)m|LOCKED)))
                    break;
                v = (uintptr)runtime_atomicloadp((void**)&l->key);
                if((v&LOCKED) == 0)
                    goto unlocked;
            }
            if(v&LOCKED) {
                // Queued.  Wait.
                runtime_semasleep(-1);
                i = 0;
            }
        }
    }
}
Example #2
0
void
runtime_unlock(Lock *l)
{
    uintptr v;
    M *mp;

    if(--runtime_m()->locks < 0)
        runtime_throw("runtime_unlock: lock count");

    for(;;) {
        v = (uintptr)runtime_atomicloadp((void**)&l->key);
        if(v == LOCKED) {
            if(runtime_casp((void**)&l->key, (void*)LOCKED, nil))
                break;
        } else {
            // Other M's are waiting for the lock.
            // Dequeue an M.
            mp = (void*)(v&~LOCKED);
            if(runtime_casp((void**)&l->key, (void*)v, mp->nextwaitm)) {
                // Dequeued an M.  Wake it.
                runtime_semawakeup(mp);
                break;
            }
        }
    }
}
Example #3
0
File: go-cgo.c Project: Lao16/gcc
int64
runtime_NumCgoCall (void)
{
  int64 ret;
  M* m;

  ret = 0;
  for (m = runtime_atomicloadp (&runtime_allm); m != NULL; m = m->alllink)
    ret += m->ncgocall;
  return ret;
}
Example #4
0
void
runtime_notewakeup(Note *n)
{
    M *mp;

    do
        mp = runtime_atomicloadp((void**)&n->key);
    while(!runtime_casp((void**)&n->key, mp, (void*)LOCKED));

    // Successfully set waitm to LOCKED.
    // What was it before?
    if(mp == nil) {
        // Nothing was waiting.  Done.
    } else if(mp == (M*)LOCKED) {
        // Two notewakeups!  Not allowed.
        runtime_throw("notewakeup - double wakeup");
    } else {
        // Must be the waiting m.  Wake it up.
        runtime_semawakeup(mp);
    }
}
Example #5
0
void
runtime_notetsleep(Note *n, int64 ns)
{
    M *m;
    M *mp;
    int64 deadline, now;

    if(ns < 0) {
        runtime_notesleep(n);
        return;
    }

    m = runtime_m();
    if(m->waitsema == 0)
        m->waitsema = runtime_semacreate();

    // Register for wakeup on n->waitm.
    if(!runtime_casp((void**)&n->key, nil, m)) {  // must be LOCKED (got wakeup already)
        if(n->key != LOCKED)
            runtime_throw("notetsleep - waitm out of sync");
        return;
    }

    if(m->profilehz > 0)
        runtime_setprof(false);
    deadline = runtime_nanotime() + ns;
    for(;;) {
        // Registered.  Sleep.
        if(runtime_semasleep(ns) >= 0) {
            // Acquired semaphore, semawakeup unregistered us.
            // Done.
            if(m->profilehz > 0)
                runtime_setprof(true);
            return;
        }

        // Interrupted or timed out.  Still registered.  Semaphore not acquired.
        now = runtime_nanotime();
        if(now >= deadline)
            break;

        // Deadline hasn't arrived.  Keep sleeping.
        ns = deadline - now;
    }

    if(m->profilehz > 0)
        runtime_setprof(true);

    // Deadline arrived.  Still registered.  Semaphore not acquired.
    // Want to give up and return, but have to unregister first,
    // so that any notewakeup racing with the return does not
    // try to grant us the semaphore when we don't expect it.
    for(;;) {
        mp = runtime_atomicloadp((void**)&n->key);
        if(mp == m) {
            // No wakeup yet; unregister if possible.
            if(runtime_casp((void**)&n->key, mp, nil))
                return;
        } else if(mp == (M*)LOCKED) {
            // Wakeup happened so semaphore is available.
            // Grab it to avoid getting out of sync.
            if(runtime_semasleep(-1) < 0)
                runtime_throw("runtime: unable to acquire - semaphore out of sync");
            return;
        } else {
            runtime_throw("runtime: unexpected waitm - semaphore out of sync");
        }
    }
}