Add m_ prefix for GENINT module,
as it is purely internal (no need to prevent user space breakage). It will put more stuff in the global m_ prefix
This commit is contained in:
1 parent
d22c0b05ef
commit
50669a320c
5 files changed
+86
-88
No files matched your search
+6
-6
@@ -574,9 +574,9 @@ typedef struct m_gc_lfmp_thread_s {
|
||||
typedef struct m_gc_s {
|
||||
m_gc_atomic_ticket_ct ticket;
|
||||
m_gc_tid_t max_thread;
|
||||
genint_t thread_alloc;
|
||||
m_genint_t thread_alloc;
|
||||
m_gc_lfmp_thread_ct *thread_data;
|
||||
m_gM_CMEMP00L_list_ct *mempool_list;
|
||||
m_gM_CMEMP00L_list_ct *mempool_list;
|
||||
} m_gc_t[1];
|
||||
|
||||
static inline void
|
||||
@@ -586,7 +586,7 @@ m_gc_init(m_gc_t gc_mem, size_t max_thread)
|
||||
M_ASSERT(max_thread > 0 && max_thread < INT_MAX);
|
||||
|
||||
atomic_init(&gc_mem->ticket, 0UL);
|
||||
genint_init(gc_mem->thread_alloc, (unsigned int) max_thread);
|
||||
m_genint_init(gc_mem->thread_alloc, (unsigned int) max_thread);
|
||||
gc_mem->thread_data = M_MEMORY_REALLOC(m_gc_lfmp_thread_ct, NULL, max_thread);
|
||||
if (gc_mem->thread_data == NULL) {
|
||||
M_MEMORY_FULL(max_thread * sizeof(m_gc_lfmp_thread_ct));
|
||||
@@ -610,7 +610,7 @@ m_gc_clear(m_gc_t gc_mem)
|
||||
}
|
||||
M_MEMORY_FREE(gc_mem->thread_data);
|
||||
gc_mem->thread_data = NULL;
|
||||
genint_clear(gc_mem->thread_alloc);
|
||||
m_genint_clear(gc_mem->thread_alloc);
|
||||
}
|
||||
|
||||
static inline m_gc_tid_t
|
||||
@@ -618,7 +618,7 @@ m_gc_attach_thread(m_gc_t gc_mem)
|
||||
{
|
||||
M_ASSERT(gc_mem != NULL && gc_mem->max_thread > 0);
|
||||
|
||||
unsigned id = genint_pop(gc_mem->thread_alloc);
|
||||
unsigned id = m_genint_pop(gc_mem->thread_alloc);
|
||||
return M_ASSIGN_CAST(m_gc_tid_t, id);
|
||||
}
|
||||
|
||||
@@ -629,7 +629,7 @@ m_gc_detach_thread(m_gc_t gc_mem, m_gc_tid_t id)
|
||||
M_ASSERT(id < gc_mem->max_thread);
|
||||
M_ASSERT(atomic_load(&gc_mem->thread_data[id].ticket) == ULONG_MAX);
|
||||
|
||||
genint_push(gc_mem->thread_alloc, id);
|
||||
m_genint_push(gc_mem->thread_alloc, id);
|
||||
}
|
||||
|
||||
static inline void
|
||||
|
||||
+31
-33
@@ -45,42 +45,40 @@ M_BEGIN_PROTECTED_CODE
|
||||
enough.
|
||||
*/
|
||||
|
||||
// TO DO: We may want a specialization with constant N value.
|
||||
|
||||
// Define the limb size used by genint
|
||||
typedef unsigned long long genint_limb_ct;
|
||||
typedef unsigned long long m_genint_limb_ct;
|
||||
|
||||
/* Define a generator of unique integer (Lock Free) */
|
||||
typedef struct genint_s {
|
||||
unsigned int n; // size of the container
|
||||
unsigned int max; // number of allocated limb - 1
|
||||
genint_limb_ct mask0; // mask of the last limb (constant)
|
||||
genint_limb_ct mask_master; // mask of the master limb that controls others (constant)
|
||||
atomic_ullong master; // master bitfield (which informs if a limb is full or not)
|
||||
atomic_ullong *data; // the bitfield which informs if an integer is used or not
|
||||
} genint_t[1];
|
||||
typedef struct m_genint_s {
|
||||
unsigned int n; // size of the container
|
||||
unsigned int max; // number of allocated limb - 1
|
||||
m_genint_limb_ct mask0; // mask of the last limb (constant)
|
||||
m_genint_limb_ct mask_master; // mask of the master limb that controls others (constant)
|
||||
atomic_ullong master; // master bitfield (which informs if a limb is full or not)
|
||||
atomic_ullong *data; // the bitfield which informs if an integer is used or not
|
||||
} m_genint_t[1];
|
||||
|
||||
// Define the max absolute supported value. It should be 2048 on most implementations.
|
||||
#define GENINT_MAX_ALLOC (M_GEN1NT_LIMBSIZE * (M_GEN1NT_LIMBSIZE - M_GEN1NT_ABA_CPT))
|
||||
#define M_GENINT_MAX_ALLOC (M_GEN1NT_LIMBSIZE * (M_GEN1NT_LIMBSIZE - M_GEN1NT_ABA_CPT))
|
||||
|
||||
// Define the size of a limb in bits.
|
||||
#define M_GEN1NT_LIMBSIZE ((unsigned)(sizeof(genint_limb_ct) * CHAR_BIT))
|
||||
#define M_GEN1NT_LIMBSIZE ((unsigned)(sizeof(m_genint_limb_ct) * CHAR_BIT))
|
||||
|
||||
// Define the contract of a genint
|
||||
#define M_GEN1NT_CONTRACT(s) do { \
|
||||
M_ASSERT (s != NULL); \
|
||||
M_ASSERT (s->n > 0 && s->n <= GENINT_MAX_ALLOC); \
|
||||
M_ASSERT (s->n > 0 && s->n <= M_GENINT_MAX_ALLOC); \
|
||||
M_ASSERT ((s->max+1) * M_GEN1NT_LIMBSIZE >= s->n); \
|
||||
M_ASSERT (s->data != NULL); \
|
||||
} while (0)
|
||||
|
||||
// Define the limb one
|
||||
#define M_GEN1NT_ONE ((genint_limb_ct)1)
|
||||
#define M_GEN1NT_ONE ((m_genint_limb_ct)1)
|
||||
|
||||
#define M_GEN1NT_FULL_MASK ULLONG_MAX
|
||||
|
||||
// Value returned in case of error (not integer available).
|
||||
#define GENINT_ERROR (UINT_MAX)
|
||||
#define M_GENINT_ERROR (UINT_MAX)
|
||||
|
||||
/* 32 bits of the master mask are kept for handling the ABA problem.
|
||||
* NOTE: May be too much. 16 bits should be more than enough. TBC
|
||||
@@ -106,9 +104,9 @@ typedef struct genint_s {
|
||||
* for all threads.
|
||||
*/
|
||||
static inline void
|
||||
genint_init(genint_t s, unsigned int n)
|
||||
m_genint_init(m_genint_t s, unsigned int n)
|
||||
{
|
||||
M_ASSERT (s != NULL && n > 0 && n <= GENINT_MAX_ALLOC);
|
||||
M_ASSERT (s != NULL && n > 0 && n <= M_GENINT_MAX_ALLOC);
|
||||
const size_t alloc = (n + M_GEN1NT_LIMBSIZE - 1) / M_GEN1NT_LIMBSIZE;
|
||||
const unsigned int index = n % M_GEN1NT_LIMBSIZE;
|
||||
atomic_ullong *ptr = M_MEMORY_REALLOC (atomic_ullong, NULL, alloc);
|
||||
@@ -121,15 +119,15 @@ genint_init(genint_t s, unsigned int n)
|
||||
s->max = (unsigned int) (alloc-1);
|
||||
s->mask0 = (index == 0) ? M_GEN1NT_FULL_MASK : ~((M_GEN1NT_ONE<<(M_GEN1NT_LIMBSIZE-index))-1);
|
||||
s->mask_master = (((M_GEN1NT_ONE << alloc) - 1) << (M_GEN1NT_LIMBSIZE-alloc)) >> M_GEN1NT_ABA_CPT;
|
||||
atomic_init (&s->master, (genint_limb_ct)0);
|
||||
atomic_init (&s->master, (m_genint_limb_ct)0);
|
||||
for(unsigned int i = 0; i < alloc; i++)
|
||||
atomic_init(&s->data[i], (genint_limb_ct)0);
|
||||
atomic_init(&s->data[i], (m_genint_limb_ct)0);
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
}
|
||||
|
||||
/* Clear an integer generator (Destructor) */
|
||||
static inline void
|
||||
genint_clear(genint_t s)
|
||||
m_genint_clear(m_genint_t s)
|
||||
{
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
M_MEMORY_FREE(s->data);
|
||||
@@ -138,7 +136,7 @@ genint_clear(genint_t s)
|
||||
|
||||
/* Return the maximum integer that the generator will provide */
|
||||
static inline size_t
|
||||
genint_size(genint_t s)
|
||||
m_genint_size(m_genint_t s)
|
||||
{
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
return s->n;
|
||||
@@ -147,22 +145,22 @@ genint_size(genint_t s)
|
||||
/* Get an unique integer from the integer generator.
|
||||
* NOTE: For a typical case, the amortized cost is one CAS per pop. */
|
||||
static inline unsigned int
|
||||
genint_pop(genint_t s)
|
||||
m_genint_pop(m_genint_t s)
|
||||
{
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
// First read master to see which limb is not full.
|
||||
genint_limb_ct master = atomic_load(&s->master);
|
||||
m_genint_limb_ct master = atomic_load(&s->master);
|
||||
// While master is not full
|
||||
while ((master >> M_GEN1NT_ABA_CPT) != s->mask_master) {
|
||||
// Let's get the index i of the first not full limb according to master.
|
||||
unsigned int i = m_core_clz64(~master);
|
||||
M_ASSERT (i < M_GEN1NT_LIMBSIZE);
|
||||
// Let's compute the mask of this limb representing the limb as being full
|
||||
genint_limb_ct mask = s->mask0;
|
||||
m_genint_limb_ct mask = s->mask0;
|
||||
mask = (i == s->max) ? mask : M_GEN1NT_FULL_MASK;
|
||||
unsigned int bit;
|
||||
// Let's load this limb,
|
||||
genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
m_genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
do {
|
||||
// If it is now full, we have been preempted by another.
|
||||
if (M_UNLIKELY (org == mask))
|
||||
@@ -181,7 +179,7 @@ genint_pop(genint_t s)
|
||||
// If the limb is now full, try to update master
|
||||
if (M_UNLIKELY(next == mask)) {
|
||||
while (true) {
|
||||
genint_limb_ct newMaster;
|
||||
m_genint_limb_ct newMaster;
|
||||
if (next == mask) {
|
||||
newMaster = M_GEN1NT_MASTER_SET(master, i);
|
||||
} else {
|
||||
@@ -201,21 +199,21 @@ genint_pop(genint_t s)
|
||||
master = atomic_load(&s->master);
|
||||
}
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
return GENINT_ERROR; // No more resource available
|
||||
return M_GENINT_ERROR; // No more resource available
|
||||
}
|
||||
|
||||
/* Restore a used integer in the integer generator.
|
||||
* NOTE: For a typical case, the amortized cost is one CAS per pop */
|
||||
static inline void
|
||||
genint_push(genint_t s, unsigned int n)
|
||||
m_genint_push(m_genint_t s, unsigned int n)
|
||||
{
|
||||
M_GEN1NT_CONTRACT(s);
|
||||
M_ASSERT (n < s->n);
|
||||
const unsigned int i = n / M_GEN1NT_LIMBSIZE;
|
||||
const unsigned int bit = M_GEN1NT_LIMBSIZE - 1 - (n % M_GEN1NT_LIMBSIZE);
|
||||
genint_limb_ct master = atomic_load(&s->master);
|
||||
m_genint_limb_ct master = atomic_load(&s->master);
|
||||
// Load the limb
|
||||
genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
m_genint_limb_ct next, org = atomic_load(&s->data[i]);
|
||||
do {
|
||||
M_ASSERT ((org & (M_GEN1NT_ONE << bit)) != 0);
|
||||
// Reset it
|
||||
@@ -223,13 +221,13 @@ genint_push(genint_t s, unsigned int n)
|
||||
// Try to unreserve it.
|
||||
} while (!atomic_compare_exchange_weak (&s->data[i], &org, next));
|
||||
// if the limb was marked as full by master
|
||||
genint_limb_ct mask = s->mask0;
|
||||
m_genint_limb_ct mask = s->mask0;
|
||||
mask = (i == s->max) ? mask : M_GEN1NT_FULL_MASK;
|
||||
if (M_UNLIKELY (next != mask)) {
|
||||
// Let's compute the mask of this limb representing the limb as being full
|
||||
// Let's try to update master to say that this limb is not full
|
||||
while (true) {
|
||||
genint_limb_ct newMaster;
|
||||
m_genint_limb_ct newMaster;
|
||||
if (next == mask) {
|
||||
newMaster = M_GEN1NT_MASTER_SET(master, i);
|
||||
} else {
|
||||
|
||||
+13
-13
@@ -380,7 +380,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
} M_C(name, _atype_ct); \
|
||||
\
|
||||
typedef struct M_C(name, _s) { \
|
||||
genint_t core; \
|
||||
m_genint_t core; \
|
||||
M_C(name, _atype_ct) *buffer; \
|
||||
} shared_t[1]; \
|
||||
\
|
||||
@@ -406,7 +406,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
M_CALL_INIT(oplist, s->buffer[i].x); \
|
||||
atomic_init (&s->buffer[i].cpt, 0U); \
|
||||
} \
|
||||
genint_init(s->core, (unsigned int) n); \
|
||||
m_genint_init(s->core, (unsigned int) n); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(s); \
|
||||
} \
|
||||
\
|
||||
@@ -414,13 +414,13 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _clear)(shared_t s) \
|
||||
{ \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(s); \
|
||||
size_t n = genint_size(s->core); \
|
||||
size_t n = m_genint_size(s->core); \
|
||||
for(size_t i = 0; i < n; i++) { \
|
||||
M_CALL_CLEAR(oplist, s->buffer[i].x); \
|
||||
} \
|
||||
M_CALL_FREE(oplist, s->buffer); \
|
||||
s->buffer = NULL; \
|
||||
genint_clear(s->core); \
|
||||
m_genint_clear(s->core); \
|
||||
} \
|
||||
\
|
||||
static inline void \
|
||||
@@ -428,10 +428,10 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
{ \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(s); \
|
||||
M_ASSERT (it != NULL); \
|
||||
unsigned int idx = genint_pop(s->core); \
|
||||
unsigned int idx = m_genint_pop(s->core); \
|
||||
it->idx = idx; \
|
||||
it->ref = s; \
|
||||
if (M_LIKELY (idx != GENINT_ERROR)) { \
|
||||
if (M_LIKELY (idx != M_GENINT_ERROR)) { \
|
||||
M_ASSERT(atomic_load(&s->buffer[idx].cpt) == 0); \
|
||||
atomic_store(&s->buffer[idx].cpt, 1U); \
|
||||
} \
|
||||
@@ -441,13 +441,13 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
M_C(name, _end_p)(it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL); \
|
||||
return it->idx == GENINT_ERROR; \
|
||||
return it->idx == M_GENINT_ERROR; \
|
||||
} \
|
||||
\
|
||||
static inline type * \
|
||||
M_C(name, _ref)(it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
|
||||
M_ASSERT (it != NULL && it->ref != NULL && it->idx != M_GENINT_ERROR); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(it->ref); \
|
||||
return &it->ref->buffer[it->idx].x; \
|
||||
} \
|
||||
@@ -455,7 +455,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
static inline type const * \
|
||||
M_C(name, _cref)(it_t it) \
|
||||
{ \
|
||||
M_ASSERT (it != NULL && it->ref != NULL && it->idx != GENINT_ERROR); \
|
||||
M_ASSERT (it != NULL && it->ref != NULL && it->idx != M_GENINT_ERROR); \
|
||||
M_SHAR3D_RESOURCE_CONTRACT(it->ref); \
|
||||
return M_CONST_CAST (type, &it->ref->buffer[it->idx].x); \
|
||||
} \
|
||||
@@ -467,12 +467,12 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
M_ASSERT (it != NULL); \
|
||||
M_ASSERT (it->ref == s); \
|
||||
unsigned int idx = it->idx; \
|
||||
if (M_LIKELY (idx != GENINT_ERROR)) { \
|
||||
if (M_LIKELY (idx != M_GENINT_ERROR)) { \
|
||||
unsigned int c = atomic_fetch_sub (&it->ref->buffer[idx].cpt, 1U); \
|
||||
if (c == 1) { \
|
||||
genint_push(it->ref->core, idx); \
|
||||
m_genint_push(it->ref->core, idx); \
|
||||
} \
|
||||
it->idx = GENINT_ERROR; \
|
||||
it->idx = M_GENINT_ERROR; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
@@ -484,7 +484,7 @@ static inline int m_shar3d_integer_cref(int *p) { return *p; }
|
||||
itd->ref = its->ref; \
|
||||
unsigned int idx = its->idx; \
|
||||
itd->idx = idx; \
|
||||
if (M_LIKELY (idx != GENINT_ERROR)) { \
|
||||
if (M_LIKELY (idx != M_GENINT_ERROR)) { \
|
||||
unsigned int c = atomic_fetch_add(&itd->ref->buffer[idx].cpt, 1U); \
|
||||
M_ASSERT (c >= 1); \
|
||||
} \
|
||||
|
||||
+16
-16
@@ -347,7 +347,7 @@ M_BEGIN_PROTECTED_CODE
|
||||
// 2 more buffer than the number of readers are needed
|
||||
#define M_SNAPSH0T_SPMC_EXTRA_BUFFER 2
|
||||
|
||||
#define M_SNAPSH0T_SPMC_MAX_READER (GENINT_MAX_ALLOC-M_SNAPSH0T_SPMC_EXTRA_BUFFER)
|
||||
#define M_SNAPSH0T_SPMC_MAX_READER (M_GENINT_MAX_ALLOC-M_SNAPSH0T_SPMC_EXTRA_BUFFER)
|
||||
|
||||
/* Internal structure to handle SPMC snapshot but return an unique index in the buffer array.
|
||||
- lastNext: last published written index + next flag (format M_SNAPSH0T_SPMC_INT_FLAG)
|
||||
@@ -361,7 +361,7 @@ typedef struct m_snapshot_mrsw_s {
|
||||
unsigned int currentWrite;
|
||||
size_t n_reader;
|
||||
atomic_uint *cptTab;
|
||||
genint_t freeList;
|
||||
m_genint_t freeList;
|
||||
} m_snapshot_mrsw_ct[1];
|
||||
|
||||
// can't check currentWrite due to potential data race on it
|
||||
@@ -391,17 +391,17 @@ m_snapsh0t_mrsw_init(m_snapshot_mrsw_ct s, size_t n)
|
||||
s->cptTab = ptr;
|
||||
for(size_t i = 0; i < n; i++)
|
||||
atomic_init(&s->cptTab[i], 0U);
|
||||
genint_init (s->freeList, (unsigned int) n);
|
||||
m_genint_init (s->freeList, (unsigned int) n);
|
||||
|
||||
// Get a free buffer and set it as available for readers
|
||||
unsigned int w = genint_pop(s->freeList);
|
||||
M_ASSERT (w != GENINT_ERROR);
|
||||
unsigned int w = m_genint_pop(s->freeList);
|
||||
M_ASSERT (w != M_GENINT_ERROR);
|
||||
atomic_store(&s->cptTab[w], 1U);
|
||||
atomic_init(&s->lastNext, M_SNAPSH0T_SPMC_INT_FLAG(w, true));
|
||||
|
||||
// Get working buffer
|
||||
s->currentWrite = genint_pop(s->freeList);
|
||||
M_ASSERT (s->currentWrite != GENINT_ERROR);
|
||||
s->currentWrite = m_genint_pop(s->freeList);
|
||||
M_ASSERT (s->currentWrite != M_GENINT_ERROR);
|
||||
atomic_store(&s->cptTab[s->currentWrite], 1U);
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
@@ -412,7 +412,7 @@ m_snapsh0t_mrsw_clear(m_snapshot_mrsw_ct s)
|
||||
{
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
M_MEMORY_FREE (s->cptTab);
|
||||
genint_clear(s->freeList);
|
||||
m_genint_clear(s->freeList);
|
||||
s->cptTab = NULL;
|
||||
s->n_reader = 0;
|
||||
}
|
||||
@@ -462,8 +462,8 @@ m_snapsh0t_mrsw_write_idx(m_snapshot_mrsw_ct s, unsigned int idx)
|
||||
if (c != 1) {
|
||||
// If someone else keeps a ref on the buffer, we can't reuse it
|
||||
// get another free one.
|
||||
idx = genint_pop(s->freeList);
|
||||
M_ASSERT(idx != GENINT_ERROR);
|
||||
idx = m_genint_pop(s->freeList);
|
||||
M_ASSERT(idx != M_GENINT_ERROR);
|
||||
} else {
|
||||
// No other thread keep track of this buffer.
|
||||
// Reuse it.
|
||||
@@ -491,8 +491,8 @@ m_snapsh0t_mrsw_write_start(m_snapshot_mrsw_ct s)
|
||||
{
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
// Get a new buffer.
|
||||
unsigned int idx = genint_pop(s->freeList);
|
||||
M_ASSERT (idx != GENINT_ERROR);
|
||||
unsigned int idx = m_genint_pop(s->freeList);
|
||||
M_ASSERT (idx != M_GENINT_ERROR);
|
||||
M_ASSERT (idx < s->n_reader + M_SNAPSH0T_SPMC_EXTRA_BUFFER);
|
||||
M_ASSERT (atomic_load(&s->cptTab[idx]) == 0);
|
||||
atomic_store(&s->cptTab[idx], 1U);
|
||||
@@ -517,7 +517,7 @@ m_snapsh0t_mrsw_write_end(m_snapshot_mrsw_ct s, unsigned int idx)
|
||||
unsigned int c = atomic_fetch_sub(&s->cptTab[idx], 1U);
|
||||
M_ASSERT (c != 0 && c <= s->n_reader + 1);
|
||||
if (c == 1) {
|
||||
genint_push(s->freeList, idx);
|
||||
m_genint_push(s->freeList, idx);
|
||||
}
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
@@ -558,7 +558,7 @@ m_snapsh0t_mrsw_read_start(m_snapshot_mrsw_ct s)
|
||||
c = atomic_fetch_sub(&s->cptTab[idx], 1U);
|
||||
M_ASSERT (c != 0 && c <= s->n_reader + 1);
|
||||
if (c == 1) {
|
||||
genint_push(s->freeList, idx);
|
||||
m_genint_push(s->freeList, idx);
|
||||
}
|
||||
}
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
@@ -577,7 +577,7 @@ m_snapsh0t_mrsw_read_end(m_snapshot_mrsw_ct s, unsigned int idx)
|
||||
if (c == 1) {
|
||||
// Buffer no longer used by any reader thread.
|
||||
// Push back index in free list
|
||||
genint_push(s->freeList, idx);
|
||||
m_genint_push(s->freeList, idx);
|
||||
}
|
||||
M_SNAPSH0T_SPMC_INT_CONTRACT(s);
|
||||
}
|
||||
@@ -730,7 +730,7 @@ m_snapsh0t_mrsw_read_end(m_snapshot_mrsw_ct s, unsigned int idx)
|
||||
{ \
|
||||
M_C(name, _mrsw_init)(snap->core, nReader + nWriter -1 ); \
|
||||
unsigned int idx = snap->core->core->currentWrite; \
|
||||
snap->core->core->currentWrite = GENINT_ERROR; \
|
||||
snap->core->core->currentWrite = M_GENINT_ERROR; \
|
||||
m_snapsh0t_mrsw_write_end(snap->core->core, idx); \
|
||||
} \
|
||||
\
|
||||
|
||||
+20
-20
@@ -30,30 +30,30 @@
|
||||
|
||||
static void test(size_t n)
|
||||
{
|
||||
genint_t s;
|
||||
m_genint_t s;
|
||||
size_t i;
|
||||
|
||||
genint_init(s, (unsigned int) n);
|
||||
m_genint_init(s, (unsigned int) n);
|
||||
for(int k = 0; k < 3; k++) {
|
||||
for(size_t j = 0; j< n ; j++) {
|
||||
i = genint_pop(s);
|
||||
i = m_genint_pop(s);
|
||||
assert (i == j);
|
||||
}
|
||||
i = genint_pop(s);
|
||||
assert (i == GENINT_ERROR);
|
||||
assert (genint_pop(s) == GENINT_ERROR);
|
||||
i = m_genint_pop(s);
|
||||
assert (i == M_GENINT_ERROR);
|
||||
assert (m_genint_pop(s) == M_GENINT_ERROR);
|
||||
|
||||
for(size_t j = 0; j< n ; j++) {
|
||||
genint_push(s, (unsigned int) ((j + (size_t) k) % n ));
|
||||
m_genint_push(s, (unsigned int) ((j + (size_t) k) % n ));
|
||||
}
|
||||
}
|
||||
|
||||
genint_clear(s);
|
||||
m_genint_clear(s);
|
||||
}
|
||||
|
||||
/*******************************************************/
|
||||
|
||||
genint_t global;
|
||||
m_genint_t global;
|
||||
atomic_bool tab_g[MAX_N];
|
||||
|
||||
static void conso(void *p)
|
||||
@@ -62,19 +62,19 @@ static void conso(void *p)
|
||||
for(int i = 0; i < 100000; i++) {
|
||||
unsigned int tab[4];
|
||||
for(int j= 0; j < 4; j++) {
|
||||
tab[j] = genint_pop(global);
|
||||
if (tab[j] != GENINT_ERROR) {
|
||||
tab[j] = m_genint_pop(global);
|
||||
if (tab[j] != M_GENINT_ERROR) {
|
||||
assert (tab[j] < n);
|
||||
assert (atomic_load(&tab_g[tab[j]]) == false);
|
||||
atomic_store(&tab_g[tab[j]], true);
|
||||
}
|
||||
}
|
||||
for(int j = 0; j < 4; j++) {
|
||||
if (tab[j] != GENINT_ERROR) {
|
||||
if (tab[j] != M_GENINT_ERROR) {
|
||||
assert (tab[j] < n);
|
||||
assert (atomic_load(&tab_g[tab[j]]) == true);
|
||||
atomic_store(&tab_g[tab[j]], false);
|
||||
genint_push(global, tab[j]);
|
||||
m_genint_push(global, tab[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -84,7 +84,7 @@ static void test2(size_t n)
|
||||
{
|
||||
m_thread_t idx[4];
|
||||
|
||||
genint_init(global, (unsigned int) n);
|
||||
m_genint_init(global, (unsigned int) n);
|
||||
for(int i = 0; i < MAX_N; i++)
|
||||
atomic_init(&tab_g[i], false);
|
||||
|
||||
@@ -95,7 +95,7 @@ static void test2(size_t n)
|
||||
m_thread_join(idx[i]);
|
||||
}
|
||||
|
||||
genint_clear(global);
|
||||
m_genint_clear(global);
|
||||
}
|
||||
|
||||
// In this test, the dimension of the global and the number of threads
|
||||
@@ -104,10 +104,10 @@ static void conso2(void *p)
|
||||
{
|
||||
size_t n = *(size_t*)p;
|
||||
for(int i = 0; i < 1000000; i++) {
|
||||
unsigned int j = genint_pop(global);
|
||||
assert (j != GENINT_ERROR);
|
||||
unsigned int j = m_genint_pop(global);
|
||||
assert (j != M_GENINT_ERROR);
|
||||
assert (j < n);
|
||||
genint_push(global, j);
|
||||
m_genint_push(global, j);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -116,14 +116,14 @@ static void test3(size_t n)
|
||||
m_thread_t idx[MAX_N];
|
||||
assert (n <= MAX_N);
|
||||
|
||||
genint_init(global, (unsigned int) n);
|
||||
m_genint_init(global, (unsigned int) n);
|
||||
for(size_t i = 0; i < n; i++) {
|
||||
m_thread_create (idx[i], conso2, (void*)&n);
|
||||
}
|
||||
for(size_t i = 0; i < n;i++) {
|
||||
m_thread_join(idx[i]);
|
||||
}
|
||||
genint_clear(global);
|
||||
m_genint_clear(global);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
||||
Reference in new issue
Block a user