Add test for int snapshot MRSW

This commit is contained in:
Patrick Pelissier committed 2018-02-17 18:20:25 +01:00
1 parent 3bda360196
commit a4753be5ae
2 files changed
+50 -6

No files matched your search

+19 -6
View File
@@ -284,6 +284,7 @@ typedef struct snapshot_mrsw_int_s {
assert (SNAPSHOTI_MRSW_INT_FLAG_W(atomic_load(&s->lastNext)) \ assert (SNAPSHOTI_MRSW_INT_FLAG_W(atomic_load(&s->lastNext)) \
<= s->n + SNAPSHOTI_MRSW_EXTRA_BUFFER); \ <= s->n + SNAPSHOTI_MRSW_EXTRA_BUFFER); \
assert (s->cptTab != NULL); \ assert (s->cptTab != NULL); \
assert (atomic_load(&s->cptTab[s->currentWrite]) == 1); \
} while (0) } while (0)
static inline void snapshot_mrsw_int_init(snapshot_mrsw_int_t s, size_t n) static inline void snapshot_mrsw_int_init(snapshot_mrsw_int_t s, size_t n)
@@ -303,9 +304,11 @@ static inline void snapshot_mrsw_int_init(snapshot_mrsw_int_t s, size_t n)
genint_init (s->freeList, n); genint_init (s->freeList, n);
// Get a free buffer and set it as available for readers // Get a free buffer and set it as available for readers
unsigned int w = genint_pop(s->freeList); unsigned int w = genint_pop(s->freeList);
atomic_store(&s->cptTab[w], 1);
atomic_init(&s->lastNext, SNAPSHOTI_MRSW_INT_FLAG(w, true)); atomic_init(&s->lastNext, SNAPSHOTI_MRSW_INT_FLAG(w, true));
// Get working buffer // Get working buffer
s->currentWrite = genint_pop(s->freeList); s->currentWrite = genint_pop(s->freeList);
atomic_store(&s->cptTab[s->currentWrite], 1);
SNAPSHOTI_MRSW_INT_CONTRACT(s); SNAPSHOTI_MRSW_INT_CONTRACT(s);
} }
@@ -336,8 +339,17 @@ static inline unsigned int snapshot_mrsw_int_write(snapshot_mrsw_int_t s)
// Reuse previous buffer as it was not used by any reader // Reuse previous buffer as it was not used by any reader
s->currentWrite = SNAPSHOTI_MRSW_INT_FLAG_W(previous); s->currentWrite = SNAPSHOTI_MRSW_INT_FLAG_W(previous);
} else { } else {
// Free the write index
idx = SNAPSHOTI_MRSW_INT_FLAG_W(previous);
unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1);
assert (c != 0 && c <= s->n + 1);
// Get a new buffer. // Get a new buffer.
s->currentWrite = genint_pop(s->freeList); if (c != 1)
idx = genint_pop(s->freeList);
s->currentWrite = idx;
assert (idx < s->n + SNAPSHOTI_MRSW_EXTRA_BUFFER);
assert (atomic_load(&s->cptTab[idx]) == 0);
atomic_store(&s->cptTab[idx], 1);
} }
SNAPSHOTI_MRSW_INT_CONTRACT(s); SNAPSHOTI_MRSW_INT_CONTRACT(s);
return s->currentWrite; return s->currentWrite;
@@ -353,18 +365,19 @@ static inline unsigned int snapshot_mrsw_int_read_start(snapshot_mrsw_int_t s)
unsigned int newNext = SNAPSHOTI_MRSW_INT_FLAG(idx, false); unsigned int newNext = SNAPSHOTI_MRSW_INT_FLAG(idx, false);
// Reserve the index // Reserve the index
unsigned int c = atomic_fetch_add(&s->cptTab[idx], 1); unsigned int c = atomic_fetch_add(&s->cptTab[idx], 1);
assert (c <= s->n); assert (c <= s->n + 1);
// Try to ack it
if (atomic_compare_exchange_weak(&s->lastNext, &previous, newNext)) if (atomic_compare_exchange_weak(&s->lastNext, &previous, newNext))
break; break;
// If we have been preempted by another read thread // If we have been preempted by another read thread
if (idx == SNAPSHOTI_MRSW_INT_FLAG_W(previous)) { if (idx == SNAPSHOTI_MRSW_INT_FLAG_W(previous)) {
// This is still ok // This is still ok if the index has not changed
assert (SNAPSHOTI_MRSW_INT_FLAG_N(previous) == false); assert (SNAPSHOTI_MRSW_INT_FLAG_N(previous) == false);
break; break;
} }
// Free the reserved index // Free the reserved index as we failed it to ack it
c = atomic_fetch_sub(&s->cptTab[idx], 1); c = atomic_fetch_sub(&s->cptTab[idx], 1);
assert (c != 0); assert (c != 0 && c <= s->n+1);
if (c == 1) if (c == 1)
genint_push(s->freeList, idx); genint_push(s->freeList, idx);
} }
@@ -378,7 +391,7 @@ static inline void snapshot_mrsw_int_read_end(snapshot_mrsw_int_t s, unsigned in
assert (idx < s->n + SNAPSHOTI_MRSW_EXTRA_BUFFER); assert (idx < s->n + SNAPSHOTI_MRSW_EXTRA_BUFFER);
// Decrement reference counter of the buffer // Decrement reference counter of the buffer
unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1); unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1);
assert (c != 0); assert (c != 0 && c <= s->n+1);
if (c == 1) { if (c == 1) {
// Buffer no longer used by any reader thread. // Buffer no longer used by any reader thread.
// Push back index in free list // Push back index in free list
+31
View File
@@ -140,10 +140,41 @@ static void test_global(void)
snapshot_data_clear(g_buff); snapshot_data_clear(g_buff);
} }
static void test_mrsw_int(void)
{
snapshot_mrsw_int_t idx;
snapshot_mrsw_int_init(idx, 1);
assert (snapshot_mrsw_int_get_write_idx(idx) == 1);
assert (snapshot_mrsw_int_write(idx) == 0);
assert (snapshot_mrsw_int_write(idx) == 1);
assert (snapshot_mrsw_int_write(idx) == 0);
assert (snapshot_mrsw_int_write(idx) == 1);
assert (snapshot_mrsw_int_read_start(idx) == 0);
snapshot_mrsw_int_read_end(idx, 0);
assert (snapshot_mrsw_int_read_start(idx) == 0);
snapshot_mrsw_int_read_end(idx, 0);
assert (snapshot_mrsw_int_write(idx) == 0);
assert (snapshot_mrsw_int_read_start(idx) == 1);
assert (snapshot_mrsw_int_write(idx) == 2);
assert (snapshot_mrsw_int_write(idx) == 0);
assert (snapshot_mrsw_int_write(idx) == 2);
snapshot_mrsw_int_read_end(idx, 1);
assert (snapshot_mrsw_int_read_start(idx) == 0);
assert (snapshot_mrsw_int_write(idx) == 1);
snapshot_mrsw_int_clear(idx);
}
int main(void) int main(void)
{ {
test_uint(); test_uint();
test_global(); test_global();
test_mrsw_int();
exit(0); exit(0);
} }