[M3devel] cas/casp?
Tony Hosking
hosking at cs.purdue.edu
Fri Dec 18 19:32:57 CET 2009
Hold your horses. I am in the middle of working up a more portable "Atomic" interface along the following lines. We can choose to implement with compiler intrinsics like Word/LongWord (if available), but otherwise will provide a call interface. I envision instantiating for ADDRESS, CHAR, and Word.T. This means CAS/CASP will go away.
GENERIC INTERFACE Atomic(Rep);
IMPORT RTMachine;
TYPE T = Rep.T;
PROCEDURE MemoryFence();
(* Guarantees explicit memory ordering for otherwise unordered atomics, and
for other memory references wrt atomics. Not useful for ordering
ordinary memory references, since those may not race and, if they don't
race, always appear to be ordered. *)
PROCEDURE CompilerFence();
(* Ensures that prior memory operations appear in the instruction stream
before subsequent ones, i.e. the compiler is not allowed to reorder
around this. This really has only implementation-defined semantics, but
it seems to be useful in ensuring ordering with respect to signal
handlers and the like. *)
PROCEDURE Store(VAR var: T; val: T); (* No ordering guarantees. *)
PROCEDURE StoreRelease(VAR var: T; val: T);
PROCEDURE Load(READONLY var: T): T; (* No ordering guarantees. *)
PROCEDURE LoadAcquire(READONLY var: T): T;
TYPE Order = { Raw, Acquire, Release, Ordered };
(* "Raw" ==> This operation is unordered, and may become visible to other
threads in an order that is constrained only by ordering constraints
on other operations.
"Release" ==> All prior memory operations (including ordinary
assignments) become visible to a an acquire operation on the same
object that sees the resulting value.
"Acquire" ==> See above.
"Ordered" ==> Both acquire and release ordering properties.*)
CONST HasCas = RTMachine.HasCas;
CONST HasWaitFreeCas = RTMachine.HasWaitFreeCas;
PROCEDURE Cas(VAR var: T; old, new: T; order := Ordered): T;
(* Most architectures provide a way to return the old value. On those that
do not, it can be emulated with an additional load, at the expense of
wait-freedom or spurious failure. *)
CONST HasWeakCas = RTMachine.HasWeakCas;
PROCEDURE WeakCas(VAR var: T; old, new: T; order := Ordered): T;
(* Similar to "Cas", but may fail spuriously, and must be wait-free, if
provided. *)
CONST HasFetchAdd = RTMachine.HasFetchAdd;
PROCEDURE FetchAdd(VAR var; incr: T; order := Raw): T;
CONST HasFetchOr = RTMachine.HasFetchOr;
PROCEDURE FetchOr(VAR var; mask: T; order := Raw): T;
CONST HasFetchAnd = RTMachine.HasFetchAnd;
PROCEDURE FetchOr(VAR var; mask: T; order := Raw): T;
END Atomic.
On 18 Dec 2009, at 13:04, Jay K wrote:
> Tony is this right?
>
>
> conceptually:
>
>
> result := CAS(VAR destination, compare, exchange)
>
>
> old := destination
> if old := compare then
> destination = exchange
> return old
>
>
> bool result := CASP(VAR destination, compare, exchange)
> P for predicate aka returning bool
>
>
> old := destination
> if old = compare then
> destination := exchange
> return true
> return false
>
>
> I'm pretty sure it is.
>
>
> I'll have this for 16 bit and 32 bit values shortly, for now requiring
> a recent Microsoft compiler and it generates function calls.
> But inlining should be easy enough.
> And then 8bit and 64bit.
>
>
> Also this will probably not work on 386 or 486 but require Pentium or somesuch.
> I don't know when various instructions were introduced but I know
> 386 is much poorer here than modern processors.
>
>
> I assume only support int8, uint8, int16, uint16, int32, uint32, int64, uint64, size_t, ptrdiff_t
> and not e.g. floating point.
>
>
> - Jay
More information about the M3devel
mailing list