Counters.Mod 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. (* Atomic counters *)
  2. (* Copyright (C) Florian Negele *)
  3. (** Provides a counter type with the following atomic operations. *)
  4. MODULE Counters;
  5. IMPORT CPU;
  6. (** Represents an atomic counter. *)
  7. TYPE Counter* = RECORD value := 0: SIZE END;
  8. (** Represents an atomic counter aligned for optimal cache behavior. *)
  9. TYPE AlignedCounter* = RECORD {ALIGNED (CPU.CacheLineSize)} (Counter) END;
  10. (** Returns the current value of an atomic counter. *)
  11. PROCEDURE Read- (VAR counter: Counter): SIZE;
  12. BEGIN {UNCOOPERATIVE, UNCHECKED} RETURN CAS (counter.value, 0, 0);
  13. END Read;
  14. (** Atomically increments the value of an atomic counter by the specified amount and returns its previous value. *)
  15. PROCEDURE Increment- (VAR counter: Counter; amount: SIZE): SIZE;
  16. VAR value: SIZE;
  17. BEGIN {UNCOOPERATIVE, UNCHECKED}
  18. LOOP
  19. value := CAS (counter.value, 0, 0);
  20. IF CAS (counter.value, value, value + amount) = value THEN EXIT END;
  21. CPU.Backoff;
  22. END;
  23. RETURN value;
  24. END Increment;
  25. (** 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. *)
  26. PROCEDURE Decrement- (VAR counter: Counter; amount: SIZE): SIZE;
  27. VAR value: SIZE;
  28. BEGIN {UNCOOPERATIVE, UNCHECKED}
  29. LOOP
  30. value := CAS (counter.value, 0, 0);
  31. IF value < amount THEN EXIT END;
  32. IF CAS (counter.value, value, value - amount) = value THEN EXIT END;
  33. CPU.Backoff;
  34. END;
  35. RETURN value;
  36. END Decrement;
  37. (** Atomically increments the value of an atomic counter. *)
  38. PROCEDURE Inc- (VAR counter: Counter);
  39. VAR value: SIZE;
  40. BEGIN {UNCOOPERATIVE, UNCHECKED}
  41. LOOP
  42. value := CAS (counter.value, 0, 0);
  43. ASSERT (value # MAX (SIZE));
  44. IF CAS (counter.value, value, value + 1) = value THEN EXIT END;
  45. CPU.Backoff;
  46. END;
  47. END Inc;
  48. (** Atomically decrements the value of an atomic counter. *)
  49. PROCEDURE Dec- (VAR counter: Counter);
  50. VAR value: SIZE;
  51. BEGIN {UNCOOPERATIVE, UNCHECKED}
  52. LOOP
  53. value := CAS (counter.value, 0, 0);
  54. ASSERT (value # MIN (SIZE));
  55. IF CAS (counter.value, value, value - 1) = value THEN EXIT END;
  56. CPU.Backoff;
  57. END;
  58. END Dec;
  59. END Counters.