Skip to content

Commit

Permalink
Name atomic primitives as Scm_* instead of reusing AO_*
Browse files Browse the repository at this point in the history
As we'll use more atomic primitives, it's easier to use our
own vocabulary rather than sticking to libatomic_ops'.
  • Loading branch information
shirok committed Nov 6, 2024
1 parent 080b174 commit d791643
Show file tree
Hide file tree
Showing 9 changed files with 62 additions and 55 deletions.
1 change: 1 addition & 0 deletions src/box.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#define LIBGAUCHE_BODY
#include "gauche.h"
#include "gauche/priv/configP.h"
#include "gauche/priv/boxP.h"

/* Srfi-195 extends box type to allow muliple values. We use separate
types for single-value box and multi-value box, for we want to optimize
Expand Down
24 changes: 12 additions & 12 deletions src/dispatch.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static ScmObj mhash_probe(const mhash *h, ScmClass *k, int nargs)
/* Need to strip 'const', because of C11 error
http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_459 */
ScmAtomicVar *loc = (ScmAtomicVar*)&h->bins[j];
ScmWord w = SCM_WORD(AO_load(loc));
ScmWord w = SCM_WORD(Scm_AtomicLoad(loc));
if (w == 0) break;
if (w != 1) {
mhash_entry *e = (mhash_entry*)w;
Expand All @@ -190,7 +190,7 @@ static mhash *mhash_insert_1(mhash *h, ScmClass *k, int nargs, ScmMethod *m)
ScmObj ltail = SCM_NIL, ntail = SCM_NIL;
int i = 0;
for (; i < h->size; i++) {
ScmWord w = SCM_WORD(AO_load(&h->bins[j]));
ScmWord w = SCM_WORD(Scm_AtomicLoad(&h->bins[j]));
if (w == 0) { /* end of chain */
if (free_slot < 0) free_slot = j;
break;
Expand All @@ -216,7 +216,7 @@ static mhash *mhash_insert_1(mhash *h, ScmClass *k, int nargs, ScmMethod *m)
e->nargs = nargs;
e->leaves = SCM_METHOD_LEAF_P(m)? Scm_Cons(SCM_OBJ(m), ltail) : ltail;
e->nonleaves = SCM_METHOD_LEAF_P(m) ? ntail : Scm_Cons(SCM_OBJ(m), ntail);
AO_store_full(&h->bins[free_slot], (ScmAtomicWord)e);
Scm_AtomicStoreFull(&h->bins[free_slot], (ScmAtomicWord)e);
h->num_entries++;
return h;
}
Expand Down Expand Up @@ -253,7 +253,7 @@ static mhash *mhash_delete(mhash *h, ScmClass *k, int nargs, ScmMethod *m)

int i = 0;
for (; i < h->size; i++) {
ScmWord w = SCM_WORD(AO_load(&h->bins[j]));
ScmWord w = SCM_WORD(Scm_AtomicLoad(&h->bins[j]));
if (w == 0) break;
if (w == 1) continue;
mhash_entry *e = (mhash_entry*)w;
Expand All @@ -273,14 +273,14 @@ static mhash *mhash_delete(mhash *h, ScmClass *k, int nargs, ScmMethod *m)

if (SCM_NULLP(ml) && SCM_NULLP(ml)) {
h->num_entries--;
AO_store(&h->bins[j], 1); /* mark as deleted */
Scm_AtomicStore(&h->bins[j], 1); /* mark as deleted */
} else {
mhash_entry *e = SCM_NEW(mhash_entry);
e->klass = k;
e->nargs = nargs;
e->leaves = ml;
e->nonleaves = mn;
AO_store_full(&h->bins[j], (ScmAtomicWord)e);
Scm_AtomicStoreFull(&h->bins[j], (ScmAtomicWord)e);
}
break;
}
Expand Down Expand Up @@ -365,24 +365,24 @@ ScmMethodDispatcher *Scm__BuildMethodDispatcher(ScmObj methods, int axis)

void Scm__MethodDispatcherAdd(ScmMethodDispatcher *dis, ScmMethod *m)
{
mhash *h = (mhash*)AO_load(&dis->methodHash);
mhash *h = (mhash*)Scm_AtomicLoad(&dis->methodHash);
mhash *h2 = add_method_to_dispatcher(h, dis->axis, m);
if (h != h2) AO_store(&dis->methodHash, (ScmAtomicWord)h2);
if (h != h2) Scm_AtomicStore(&dis->methodHash, (ScmAtomicWord)h2);
}

void Scm__MethodDispatcherDelete(ScmMethodDispatcher *dis, ScmMethod *m)
{
mhash *h = (mhash*)AO_load(&dis->methodHash);
mhash *h = (mhash*)Scm_AtomicLoad(&dis->methodHash);
mhash *h2 = delete_method_from_dispatcher(h, dis->axis, m);
if (h != h2) AO_store(&dis->methodHash, (ScmAtomicWord)h2);
if (h != h2) Scm_AtomicStore(&dis->methodHash, (ScmAtomicWord)h2);
}

ScmObj Scm__MethodDispatcherLookup(ScmMethodDispatcher *dis,
ScmClass **typev, int argc)
{
if (dis->axis <= argc) {
ScmClass *selector = typev[dis->axis];
mhash *h = (mhash*)AO_load(&dis->methodHash);
mhash *h = (mhash*)Scm_AtomicLoad(&dis->methodHash);
return mhash_probe(h, selector, argc);
} else {
return SCM_FALSE;
Expand All @@ -395,7 +395,7 @@ ScmObj Scm__MethodDispatcherInfo(const ScmMethodDispatcher *dis)
/* Need to strip 'const', because of C11 error
http://www.open-std.org/jtc1/sc22/wg14/www/docs/summary.htm#dr_459 */
ScmAtomicVar *loc = (ScmAtomicVar*)&dis->methodHash;
const mhash *mh = (const mhash*)AO_load(loc);
const mhash *mh = (const mhash*)Scm_AtomicLoad(loc);
SCM_APPEND1(h, t, SCM_MAKE_KEYWORD("axis"));
SCM_APPEND1(h, t, SCM_MAKE_INT(dis->axis));
SCM_APPEND1(h, t, SCM_MAKE_KEYWORD("num-entries"));
Expand Down
30 changes: 18 additions & 12 deletions src/gauche/priv/atomicP.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,12 @@
typedef ScmWord ScmAtomicWord;
typedef volatile _Atomic ScmAtomicWord ScmAtomicVar;

/* We disguise with AO_ operations for now. */
#define AO_store_full(loc, val) atomic_store(loc, val)
#define AO_store(loc, val) atomic_store(loc, val)
#define AO_load(loc) atomic_load(loc)
#define AO_compare_and_swap_full(loc, oldval, newval) \
#define Scm_AtomicStore(loc, val) atomic_store(loc, val)
#define Scm_AtomicStoreFull(loc, val) atomic_store(loc, val)
#define Scm_AtomicLoad(loc) atomic_load(loc)
#define Scm_AtomicCompareAndSwap(loc, oldval, newval) \
atomic_compare_exchange_strong(loc, &oldval, newval)
#define AO_nop_full() atomic_thread_fence(__ATOMIC_SEQ_CST)
#define Scm_AtomicThreadFence() atomic_thread_fence(__ATOMIC_SEQ_CST)

# else /* GC_BUILTIN_ATOMIC && !HAVE_STDATOMIC_H */
/*
Expand All @@ -40,13 +39,13 @@ typedef volatile _Atomic ScmAtomicWord ScmAtomicVar;
typedef ScmWord ScmAtomicWord;
typedef volatile ScmAtomicWord ScmAtomicVar;

#define AO_store_full(loc, val) __atomic_store_n(loc, val, __ATOMIC_SEQ_CST)
#define AO_store(loc, val) __atomic_store_n(loc, val, __ATOMIC_SEQ_CST)
#define AO_load(loc) __atomic_load_n(loc, __ATOMIC_SEQ_CST)
#define AO_compare_and_swap_full(loc, oldval, newval) \
__atomic_compare_exchange_n(loc, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
#define AO_nop_full() __atomic_thread_fence(__ATOMIC_SEQ_CST)

#define Scm_AtomicStore(loc, val) __atomic_store_n(loc, val, __ATOMIC_SEQ_CST)
#define Scm_AtomicStoreFull(loc, val) __atomic_store_n(loc, val, __ATOMIC_SEQ_CST)
#define Scm_AtomicLoad(loc) __atomic_load(loc, __ATOMIC_SEQ_CST)
#define Scm_AtomicCompareAndSwap(loc, oldval, newval) \
__atomic_compare_exchange_n(loc, &oldval, newval, 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)
#define Scm_AtomicThreadFence() __atomic_thread_fence(__ATOMIC_SEQ_CST)

# endif /* GC_BUILTIN_ATOMIC && !HAVE_STDATOMIC_H */

Expand Down Expand Up @@ -104,6 +103,13 @@ typedef volatile ScmAtomicWord ScmAtomicVar;
typedef AO_t ScmAtomicWord;
typedef volatile AO_t ScmAtomicVar;

#define Scm_AtomicStore(loc, val) AO_store(loc, val)
#define Scm_AtomicStoreFull(loc, val) AO_store_full(loc, val)
#define Scm_AtomicLoad(loc) AO_load(loc)
#define Scm_AtomicCompareAndSwap(loc, oldval, newval) \
AO_compare_and_swap_full(loc, oldval, newval)
#define Scm_AtomicThreadFence() AO_nop_full()

#endif

#endif /*GAUCHE_PRIV_ATOMICP_H*/
2 changes: 1 addition & 1 deletion src/hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -1330,7 +1330,7 @@ static u_long legacy_flonum_hash(double f)
two_pow_63 = ldexp(1.0, 63);
minus_two_pow_63 = -ldexp(1.0, 63);
two_pow_32 = ldexp(1.0, 32);
AO_nop_full();
Scm_AtomicThreadFence();
initialized = TRUE;
}
/* This condition eliminates NaN as well. */
Expand Down
10 changes: 5 additions & 5 deletions src/lazy.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ static ScmObj force_exc_handler(ScmObj *argv, int argc, void *data)
SCM_INTERNAL_MUTEX_LOCK(c->mutex);
if (c->state == SCM_PROMISE_UNFORCED) {
c->code = argv[0]; /* condition object */
AO_nop_full();
Scm_AtomicThreadFence();
c->state = SCM_PROMISE_EXCEPTION;
}
SCM_INTERNAL_MUTEX_UNLOCK(c->mutex);
Expand All @@ -190,7 +190,7 @@ static ScmObj force_cc(ScmObj result, void **data)
See srfi-45 for the details. */
ScmPromiseContent *cc = SCM_PROMISE(result)->content;
c->code = cc->code;
AO_nop_full();
Scm_AtomicThreadFence();
c->state = cc->state;
SCM_PROMISE(result)->content = c;
} else {
Expand All @@ -199,7 +199,7 @@ static ScmObj force_cc(ScmObj result, void **data)
one from writing (lazy 3). So play safe. */
SCM_ASSERT(SCM_LISTP(result));
c->code = result;
AO_nop_full();
Scm_AtomicThreadFence();
c->state = SCM_PROMISE_FORCED;
}
}
Expand Down Expand Up @@ -635,7 +635,7 @@ ScmObj Scm_ForceLazyPair(volatile ScmLazyPair *obj)
ScmAtomicWord zero = 0; /* Need to use C11 intrinsic */

do {
if (AO_compare_and_swap_full(&lp->owner, zero, SCM_WORD(vm))) {
if (Scm_AtomicCompareAndSwap(&lp->owner, zero, SCM_WORD(vm))) {
/* Here we own the lazy pair. */
volatile ScmObj item = lp->data.item;
volatile ScmObj attrs = SCM_NIL;
Expand All @@ -648,7 +648,7 @@ ScmObj Scm_ForceLazyPair(volatile ScmLazyPair *obj)
lp->data.item = generator_to_lazy_pair(lp->data.generator);
lp->data.generator = attrs;
lp->owner = XPAIR_DESC();
AO_nop_full();
Scm_AtomicThreadFence();
SCM_SET_CAR_UNCHECKED(obj, item); /* Overwrite LazyPair tag */
} SCM_WHEN_ERROR {
lp->owner = (ScmAtomicWord)0; /*NB: See above about error handling*/
Expand Down
10 changes: 5 additions & 5 deletions src/libbox.scm
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@
(c "SCM_CLASS_DEFAULT_CPL")
()
(printer (let* ([b::ScmSharedBox* (SCM_SHARED_BOX obj)]
[cnt::ScmAtomicWord (AO_load (& (-> b counter)))])
[cnt::ScmAtomicWord (Scm_AtomicLoad (& (-> b counter)))])
(Scm_Printf port "#<shared-box[%d]<%d>"
(-> b numValues) cnt)
(dotimes [i (-> b numValues)]
Expand Down Expand Up @@ -195,23 +195,23 @@
(- numVals 1))))]
[i::int 0])
(SCM_SET_CLASS z (& Scm_SharedBoxClass))
(AO_store (& (-> z counter)) (cast ScmAtomicWord initial-count))
(Scm_AtomicStore (& (-> z counter)) (cast ScmAtomicWord initial-count))
(set! (-> z numValues) numVals)
(dolist [v values]
(set! (aref (-> z values) (post++ i)) v))
(return (SCM_OBJ z))))

;; API
(define-cproc shared-box-count (cb::<shared-box>)
(let* ([v::ScmAtomicWord (AO_load (& (-> cb counter)))])
(let* ([v::ScmAtomicWord (Scm_AtomicLoad (& (-> cb counter)))])
;; NB: We might need an api to convert ScmAtomicWord to Scheme integer.
(return (Scm_MakeInteger (cast long v)))))

;; API
(define-cproc shared-box-inc! (cb::<shared-box>
:optional (delta::<fixnum> 1))
(for ()
(let* ([v::ScmAtomicWord (AO_load (& (-> cb counter)))]
(let* ([v::ScmAtomicWord (Scm_AtomicLoad (& (-> cb counter)))]
[vv::ScmAtomicWord (+ v delta)])
(when (AO_compare_and_swap_full (& (-> cb counter)) v vv)
(when (Scm_AtomicCompareAndSwap (& (-> cb counter)) v vv)
(return (Scm_MakeInteger (cast long v)))))))
32 changes: 16 additions & 16 deletions src/memo.c
Original file line number Diff line number Diff line change
Expand Up @@ -154,12 +154,12 @@ static _Bool memo_equalv(ScmObj *keys, int nkeys, ScmAtomicVar *entry_keys)
int rest_keys;
int fixed_keys = get_numkeys(nkeys, &rest_keys);
for (int i = 0; i < fixed_keys; i++) {
ScmObj k = (ScmObj)AO_load(entry_keys+i);
ScmObj k = (ScmObj)Scm_AtomicLoad(entry_keys+i);
if (!equal_1(keys[i], k)) return FALSE;
}
if (rest_keys) {
ScmObj rest = keys[fixed_keys], rp;
ScmObj entry_rest = (ScmObj)AO_load(entry_keys+fixed_keys);
ScmObj entry_rest = (ScmObj)Scm_AtomicLoad(entry_keys+fixed_keys);
SCM_FOR_EACH(rp, rest) {
if (!SCM_PAIRP(entry_rest)) return FALSE;
if (!equal_1(SCM_CAR(rp), SCM_CAR(entry_rest))) return FALSE;
Expand Down Expand Up @@ -189,7 +189,7 @@ ScmObj Scm_MemoTableGetv(ScmMemoTable *tab, ScmObj *keys, int nkeys)
for (u_long i = 0; i < st->capacity / 2; i++) {
u_long k = (hashv+i) % st->capacity;
u_long idx = k * tab->entry_size;
ScmAtomicWord entry_hdr = AO_load(&st->vec[idx]);
ScmAtomicWord entry_hdr = Scm_AtomicLoad(&st->vec[idx]);
if (entry_hdr == 0) return SCM_UNBOUND; /* not found */
if ((entry_hdr & 0x01) == 0
|| entry_hdr != hashv_hdr) {
Expand Down Expand Up @@ -233,10 +233,10 @@ static inline void insert_entry(ScmMemoTable *tab, ScmMemoTableStorage *st,
{
int num_keys = get_total_numkeys(tab->num_keys);
for (int ik = 0; ik < num_keys; ik++) {
AO_store(&st->vec[entry_index+1+ik], (ScmAtomicWord)keys[ik]);
Scm_AtomicStore(&st->vec[entry_index+1+ik], (ScmAtomicWord)keys[ik]);
}
AO_store(&st->vec[entry_index+1+num_keys], (ScmAtomicWord)val);
AO_store_full(&st->vec[entry_index], hashv_hdr);
Scm_AtomicStore(&st->vec[entry_index+1+num_keys], (ScmAtomicWord)val);
Scm_AtomicStoreFull(&st->vec[entry_index], hashv_hdr);
}

/* returns TRUE on success, FALSE on failure */
Expand All @@ -248,10 +248,10 @@ static int search_and_insert(ScmMemoTable *tab, ScmMemoTableStorage *st,
for (u_long i = 0; i < st->capacity / 2; i++) {
u_long k = (hashv+i) % st->capacity;
u_long idx = k * tab->entry_size;
ScmAtomicWord entry_hdr = AO_load(&st->vec[idx]);
ScmAtomicWord entry_hdr = Scm_AtomicLoad(&st->vec[idx]);
if (entry_hdr == 0) {
/* The table doesn't have the key. Try to claim this entry. */
if (AO_compare_and_swap_full(&st->vec[idx], entry_hdr,
if (Scm_AtomicCompareAndSwap(&st->vec[idx], entry_hdr,
(ScmAtomicWord)vm)) {
insert_entry(tab, st, idx, hashv_hdr, keys, val);
return TRUE;
Expand Down Expand Up @@ -281,8 +281,8 @@ static int search_and_insert(ScmMemoTable *tab, ScmMemoTableStorage *st,
the value is 0 and gone to mark the header invalid. If it
happens, this insertion is ignored. It's ok because of
idempotency. */
AO_store_full(&st->vec[idx+1+get_total_numkeys(tab->num_keys)],
(ScmAtomicWord)val);
Scm_AtomicStoreFull(&st->vec[idx+1+get_total_numkeys(tab->num_keys)],
(ScmAtomicWord)val);
return TRUE;
}
}
Expand All @@ -305,15 +305,15 @@ static void extend_table(ScmMemoTable *tab)
costs extra time to re-compute that result. */
for (u_long i = 0; i < orig_st->capacity; i++) {
u_long idx = i * tab->entry_size;
ScmAtomicWord entry_hdr = AO_load(&orig_st->vec[idx]);
ScmAtomicWord entry_hdr = Scm_AtomicLoad(&orig_st->vec[idx]);
if ((entry_hdr & 0x01) == 0) {
/* unused, invalid, or someone is working on it. */
continue;
}
for (int k = 0; k < num_keys; k++) {
keys[k] = SCM_OBJ(AO_load(&orig_st->vec[idx+1+k]));
keys[k] = SCM_OBJ(Scm_AtomicLoad(&orig_st->vec[idx+1+k]));
}
ScmObj val = SCM_OBJ(AO_load(&orig_st->vec[idx+1+num_keys]));
ScmObj val = SCM_OBJ(Scm_AtomicLoad(&orig_st->vec[idx+1+num_keys]));
if (!search_and_insert(tab, new_st, entry_hdr, keys, val, self)) {
Scm_Panic("memo table overflow double fault");
}
Expand Down Expand Up @@ -396,16 +396,16 @@ void Scm__MemoTableDump(ScmMemoTable *tab, ScmPort *port)
tab->storage->vec[i]);
int valid = tab->storage->vec[i] & 0x01;
for (int j = 0; j < fixed_keys; j++) {
ScmAtomicWord key = AO_load(&tab->storage->vec[i+1+j]);
ScmAtomicWord key = Scm_AtomicLoad(&tab->storage->vec[i+1+j]);
dump_1(key, valid, port);
}
if (rest_keys) {
ScmAtomicWord keys = AO_load(&tab->storage->vec[i+1+fixed_keys]);
ScmAtomicWord keys = Scm_AtomicLoad(&tab->storage->vec[i+1+fixed_keys]);
dump_1(keys, valid, port);
}

ScmAtomicWord value =
AO_load(&tab->storage->vec[i+1+fixed_keys+rest_keys]);
Scm_AtomicLoad(&tab->storage->vec[i+1+fixed_keys+rest_keys]);
dump_1(value, valid, port);
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/mmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ static int pax_active_p()
SCM_ASSERT(ptr != NULL);
int r = mprotect(ptr, pagesize, PROT_WRITE|PROT_EXEC);
(void)munmap(ptr, pagesize);
AO_store_full(&result_cache, (r < 0));
Scm_AtomicStoreFull(&result_cache, (r < 0));
}
return result_cache;
}
Expand Down
6 changes: 3 additions & 3 deletions src/system.c
Original file line number Diff line number Diff line change
Expand Up @@ -3081,7 +3081,7 @@ int Scm__WinMutexLock(HANDLE mutex)
int Scm__WinFastLockInit(ScmInternalFastlock *spin)
{
*spin = SCM_NEW(struct win_spinlock_rec);
AO_store(&(*spin)->lock_state, 0);
Scm_AtomicStore(&(*spin)->lock_state, 0);
return 0;
}

Expand All @@ -3090,7 +3090,7 @@ int Scm__WinFastLockLock(ScmInternalFastlock spin)
/* spin may be NULL when FASTLOCK_LOCK is called on already-closed port. */
if (spin != NULL) {
ScmAtomicVar idle = 0;
while (!AO_compare_and_swap_full(&spin->lock_state, idle, 1)) {
while (!Scm_AtomicCompareAndSwap(&spin->lock_state, idle, 1)) {
/* idle might be changed */
idle = 0;
/* it might be slow */
Expand All @@ -3104,7 +3104,7 @@ int Scm__WinFastLockUnlock(ScmInternalFastlock spin)
{
/* spin may be NULL when FASTLOCK_LOCK is called on already-closed port. */
if (spin != NULL) {
AO_store_full(&spin->lock_state, 0);
Scm_AtomicStoreFull(&spin->lock_state, 0);
}
return 0;
}
Expand Down

0 comments on commit d791643

Please sign in to comment.