root/src/pkg/runtime/atomic_arm.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. runtime·xadd
  2. runtime·xchg
  3. runtime·xchgp
  4. runtime·procyield
  5. runtime·atomicload
  6. runtime·atomicloadp
  7. runtime·atomicstorep
  8. runtime·atomicstore
  9. runtime·cas64
  10. runtime·xadd64
  11. runtime·xchg64
  12. runtime·atomicload64
  13. runtime·atomicstore64

// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

#include "runtime.h"
#include "arch_GOARCH.h"
#include "../../cmd/ld/textflag.h"

static struct {
        Lock l;
        byte pad[CacheLineSize-sizeof(Lock)];
} locktab[57];

#define LOCK(addr) (&locktab[((uintptr)(addr)>>3)%nelem(locktab)].l)

// Atomic add and return new value.
#pragma textflag NOSPLIT
uint32
runtime·xadd(uint32 volatile *val, int32 delta)
{
        uint32 oval, nval;

        for(;;){
                oval = *val;
                nval = oval + delta;
                if(runtime·cas(val, oval, nval))
                        return nval;
        }
}

#pragma textflag NOSPLIT
uint32
runtime·xchg(uint32 volatile* addr, uint32 v)
{
        uint32 old;

        for(;;) {
                old = *addr;
                if(runtime·cas(addr, old, v))
                        return old;
        }
}

#pragma textflag NOSPLIT
void*
runtime·xchgp(void* volatile* addr, void* v)
{
        void *old;

        for(;;) {
                old = *addr;
                if(runtime·casp(addr, old, v))
                        return old;
        }
}

#pragma textflag NOSPLIT
void
runtime·procyield(uint32 cnt)
{
        uint32 volatile i;

        for(i = 0; i < cnt; i++) {
        }
}

#pragma textflag NOSPLIT
uint32
runtime·atomicload(uint32 volatile* addr)
{
        return runtime·xadd(addr, 0);
}

#pragma textflag NOSPLIT
void*
runtime·atomicloadp(void* volatile* addr)
{
        return (void*)runtime·xadd((uint32 volatile*)addr, 0);
}

#pragma textflag NOSPLIT
void
runtime·atomicstorep(void* volatile* addr, void* v)
{
        void *old;

        for(;;) {
                old = *addr;
                if(runtime·casp(addr, old, v))
                        return;
        }
}

#pragma textflag NOSPLIT
void
runtime·atomicstore(uint32 volatile* addr, uint32 v)
{
        uint32 old;
        
        for(;;) {
                old = *addr;
                if(runtime·cas(addr, old, v))
                        return;
        }
}

#pragma textflag NOSPLIT
bool
runtime·cas64(uint64 volatile *addr, uint64 old, uint64 new)
{
        bool res;
        
        runtime·lock(LOCK(addr));
        if(*addr == old) {
                *addr = new;
                res = true;
        } else {
                res = false;
        }
        runtime·unlock(LOCK(addr));
        return res;
}

#pragma textflag NOSPLIT
uint64
runtime·xadd64(uint64 volatile *addr, int64 delta)
{
        uint64 res;
        
        runtime·lock(LOCK(addr));
        res = *addr + delta;
        *addr = res;
        runtime·unlock(LOCK(addr));
        return res;
}

#pragma textflag NOSPLIT
uint64
runtime·xchg64(uint64 volatile *addr, uint64 v)
{
        uint64 res;

        runtime·lock(LOCK(addr));
        res = *addr;
        *addr = v;
        runtime·unlock(LOCK(addr));
        return res;
}

#pragma textflag NOSPLIT
uint64
runtime·atomicload64(uint64 volatile *addr)
{
        uint64 res;
        
        runtime·lock(LOCK(addr));
        res = *addr;
        runtime·unlock(LOCK(addr));
        return res;
}

#pragma textflag NOSPLIT
void
runtime·atomicstore64(uint64 volatile *addr, uint64 v)
{
        runtime·lock(LOCK(addr));
        *addr = v;
        runtime·unlock(LOCK(addr));
}

/* [<][>][^][v][top][bottom][index][help] */