123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- (* Atomic counters *)
- (* Copyright (C) Florian Negele *)
- (** Provides a counter type with the following atomic operations. *)
- MODULE Counters;
- IMPORT CPU;
- (** Represents an atomic counter. *)
- TYPE Counter* = RECORD value := 0: SIZE END;
- (** Represents an atomic counter aligned for optimal cache behavior. *)
- TYPE AlignedCounter* = RECORD {ALIGNED (CPU.CacheLineSize)} (Counter) END;
- (** Returns the current value of an atomic counter. *)
- PROCEDURE Read- (VAR counter: Counter): SIZE;
- BEGIN {UNCOOPERATIVE, UNCHECKED} RETURN CAS (counter.value, 0, 0);
- END Read;
- (** Atomically increments the value of an atomic counter by the specified amount and returns its previous value. *)
- PROCEDURE Increment- (VAR counter: Counter; amount: SIZE): SIZE;
- VAR value: SIZE;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- LOOP
- value := CAS (counter.value, 0, 0);
- IF CAS (counter.value, value, value + amount) = value THEN EXIT END;
- CPU.Backoff;
- END;
- RETURN value;
- END Increment;
- (** Atomically decrements the value of an atomic counter by the specified amount and returns either its previous value or zero if the counter cannot be decremented. *)
- PROCEDURE Decrement- (VAR counter: Counter; amount: SIZE): SIZE;
- VAR value: SIZE;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- LOOP
- value := CAS (counter.value, 0, 0);
- IF value < amount THEN EXIT END;
- IF CAS (counter.value, value, value - amount) = value THEN EXIT END;
- CPU.Backoff;
- END;
- RETURN value;
- END Decrement;
- (** Atomically increments the value of an atomic counter. *)
- PROCEDURE Inc- (VAR counter: Counter);
- VAR value: SIZE;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- LOOP
- value := CAS (counter.value, 0, 0);
- ASSERT (value # MAX (SIZE));
- IF CAS (counter.value, value, value + 1) = value THEN EXIT END;
- CPU.Backoff;
- END;
- END Inc;
- (** Atomically decrements the value of an atomic counter. *)
- PROCEDURE Dec- (VAR counter: Counter);
- VAR value: SIZE;
- BEGIN {UNCOOPERATIVE, UNCHECKED}
- LOOP
- value := CAS (counter.value, 0, 0);
- ASSERT (value # MIN (SIZE));
- IF CAS (counter.value, value, value - 1) = value THEN EXIT END;
- CPU.Backoff;
- END;
- END Dec;
- END Counters.
|