On 08/04/16 12:43, Nathan Sidwell wrote:
How about: gcov_t expected; atomic_load (&counter[0], val, ...); gcov_t delta = val == value ? 1 : -1; atomic_add (&counter[1], delta); <-- or atomic_add_fetch if (delta < 0) { /* can we set counter[0]? */ atomic_load (&counter[1], &expected, ...); if (expected < 0) { atomic_store (&counter[0], value, ...); atomic_add (&counter[1], 2, ...); } } atomic_add (&counter[2], 1, ...);
we could do better by using compare_exchange storing value, and detect the race I mentioned:
gcov_t expected, val; atomic_load (&counter[0], &val, ...); gcov_t delta = val == value ? 1 : -1; atomic_add (&counter[1], delta); if (delta < 0) { retry: /* can we set counter[0]? */ atomic_load (&counter[1], &expected, ...); if (expected < 0) { bool stored = atomic_compare_exchange (&counter[0], &val, &value, ...); if (!stored && val != value) goto retry; atomic_add (&counter[1], 2, ...); } } atomic_add (&counter[2], 1, ...); This corrects the off-by one issue. nathan