Skip to content

Commit 3075506

Browse files
committed
Adding atomic pair
1 parent 48c06ce commit 3075506

File tree

4 files changed

+88
-2
lines changed

4 files changed

+88
-2
lines changed

src/CMakeLists.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,35 @@ IF(MSYS OR (NOT MSVC AND WIN32))
126126
ENDIF()
127127

128128
IF(NOT WIN32)
129+
if (HAVE_STDATOMIC_H)
130+
CHECK_C_SOURCE_COMPILES(
131+
"#include <stdatomic.h>
132+
#include <stddef.h>
133+
typedef struct {
134+
void *a;
135+
void *b;
136+
} cas16_t;
137+
typedef _Atomic cas16_t atomic_cas16_t;
138+
int main()
139+
{
140+
cas16_t v = { NULL, NULL };
141+
atomic_cas16_t a;
142+
atomic_init(&a, v);
143+
atomic_exchange(&a, v);
144+
return 0;
145+
}
146+
"
147+
CAS16_WORKS)
148+
ELSE()
149+
# TODO libatomic_ops?
150+
SET(CAS16_WORKS TRUE)
151+
ENDIF()
152+
IF (CAS16_WORKS)
153+
MESSAGE(STATUS "CAS16 works ... yes")
154+
ELSE()
155+
MESSAGE(STATUS "CAS16 works ... no")
156+
ENDIF()
157+
129158
IF (NOT ${SAGITTARIUS_OS} STREQUAL "qnx")
130159
TARGET_LINK_LIBRARIES(sagittarius pthread)
131160
ENDIF()
@@ -142,6 +171,10 @@ IF(NOT WIN32)
142171
IF (${SAGITTARIUS_OS} STREQUAL "linux")
143172
# for clock_gettime
144173
TARGET_LINK_LIBRARIES(sagittarius rt)
174+
# for CAS16
175+
IF (NOT CAS16_WORKS)
176+
TARGET_LINK_LIBRARIES(sagittarius atomic)
177+
ENDIF()
145178
ENDIF()
146179
# linux needs this
147180
TARGET_LINK_LIBRARIES(sagittarius m)

src/atomic.c

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "sagittarius/private/atomic.h"
3131
#include "sagittarius/private/error.h"
3232
#include "sagittarius/private/library.h"
33+
#include "sagittarius/private/pair.h"
3334
#include "sagittarius/private/port.h"
3435
#include "sagittarius/private/symbol.h"
3536
#include "sagittarius/private/writer.h"
@@ -288,6 +289,14 @@ SgObject Sg_MakeAtomic(SgObject obj)
288289
return SG_OBJ(a);
289290
}
290291

292+
SgObject Sg_MakeAtomicPair(SgObject car, SgObject cdr)
293+
{
294+
SgAtomic *a = make_atomic(SG_ATOMIC_PAIR);
295+
pair_t v = { car, cdr };
296+
atomic_init(&SG_ATOMIC_REF_PAIR(a), v);
297+
return SG_OBJ(a);
298+
}
299+
291300
SgObject Sg_MakeAtomicFixnum(long n)
292301
{
293302
SgAtomic *a = make_atomic(SG_ATOMIC_FIXNUM);
@@ -301,6 +310,9 @@ SgObject Sg_AtomicLoad(volatile SgAtomic *o, SgMemoryOrder order)
301310
if (SG_ATOMIC_FIXNUM_P(o)) {
302311
long v = atomic_load_explicit(&SG_ATOMIC_REF_FIXNUM(o), order);
303312
return SG_MAKE_INT(v);
313+
} else if (SG_ATOMIC_PAIR_P(o)) {
314+
pair_t v = atomic_load_explicit(&SG_ATOMIC_REF_PAIR(o), order);
315+
return Sg_Cons(v.car, v.cdr);
304316
} else {
305317
object_t v = atomic_load_explicit(&SG_ATOMIC_REF_OBJECT(o), order);
306318
return SG_OBJ(v);
@@ -314,6 +326,12 @@ void Sg_AtomicStore(volatile SgAtomic *o, SgObject v, SgMemoryOrder order)
314326
Sg_Error(UC("fixnum is required for atomic-fixnum but got %A"), v);
315327
}
316328
atomic_store_explicit(&SG_ATOMIC_REF_FIXNUM(o), SG_INT_VALUE(v), order);
329+
} else if (SG_ATOMIC_PAIR_P(o)) {
330+
if (!SG_PAIRP(v)) {
331+
Sg_Error(UC("pair is required for atomic-pair but got %A"), v);
332+
}
333+
pair_t v2 = { .car = SG_CAR(v), .cdr = SG_CDR(v) };
334+
atomic_store_explicit(&SG_ATOMIC_REF_PAIR(o), v2, order);
317335
} else {
318336
atomic_store_explicit(&SG_ATOMIC_REF_OBJECT(o), (object_t)v, order);
319337
}
@@ -328,6 +346,13 @@ SgObject Sg_AtomicExchange(volatile SgAtomic *o, SgObject v, SgMemoryOrder order
328346
long vl = SG_INT_VALUE(v);
329347
long l = atomic_exchange_explicit(&SG_ATOMIC_REF_FIXNUM(o), vl, order);
330348
return SG_MAKE_INT(l);
349+
} else if (SG_ATOMIC_PAIR_P(o)) {
350+
if (!SG_PAIRP(v)) {
351+
Sg_Error(UC("pair is required for atomic-pair but got %A"), v);
352+
}
353+
pair_t v2 = { .car = SG_CAR(v), .cdr = SG_CDR(v) };
354+
pair_t r = atomic_exchange_explicit(&SG_ATOMIC_REF_PAIR(o), v2, order);
355+
return Sg_Cons(r.car, r.cdr);
331356
} else {
332357
object_t r = atomic_exchange_explicit(&SG_ATOMIC_REF_OBJECT(o),
333358
(object_t)v, order);
@@ -400,15 +425,25 @@ int Sg_AtomicCompareAndSwap(volatile SgAtomic *o, SgObject e, SgObject v,
400425
}
401426
{
402427
long ev = SG_INT_VALUE(e);
403-
return atomic_compare_exchange_strong_explicit(&(o->reference.fixnum),
428+
return atomic_compare_exchange_strong_explicit(&SG_ATOMIC_REF_FIXNUM(o),
404429
&ev,
405430
SG_INT_VALUE(v),
406431
success, failure);
407432
}
433+
case SG_ATOMIC_PAIR:
434+
if (!SG_PAIRP(e) && !SG_PAIRP(v)) {
435+
Sg_Error(UC("atomic_pair must take pair but got %S and %S"), e, v);
436+
}
437+
{
438+
pair_t ev = { .car = SG_CAR(e), .cdr = SG_CDR(e) };
439+
pair_t vv = { .car = SG_CAR(v), .cdr = SG_CDR(v) };
440+
return atomic_compare_exchange_strong_explicit(&SG_ATOMIC_REF_PAIR(o),
441+
&ev, vv, success, failure);
442+
}
408443
default:
409444
{
410445
object_t ev = (object_t)e;
411-
return atomic_compare_exchange_strong_explicit(&(o->reference.object),
446+
return atomic_compare_exchange_strong_explicit(&SG_ATOMIC_REF_OBJECT(o),
412447
&ev, (object_t)v,
413448
success, failure);
414449
}

src/lib_atomic.stub

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
<sagittarius/private/atomic.h>))
3636

3737
(define-type <atomic> "SgAtomic*" )
38+
(define-type <atomic-pair> "SgAtomic*" "atomic-pair"
39+
"SG_ATOMIC_PAIR_P" "SG_ATOMIC")
3840
(define-type <atomic-fixnum> "SgAtomic*" "atomic-fixnum"
3941
"SG_ATOMIC_FIXNUM_P" "SG_ATOMIC")
4042
(define-type <memory-order> "SgMemoryOrder" "memory-order"
@@ -46,9 +48,11 @@
4648
(define-c-proc memory-order? (obj) ::<boolean> Sg_MemoryOrderP)
4749

4850
(define-c-proc make-atomic (obj) Sg_MakeAtomic)
51+
(define-c-proc make-atomic-pair (a d) Sg_MakeAtomicPair)
4952
(define-c-proc make-atomic-fixnum (n::<fixnum>) Sg_MakeAtomicFixnum)
5053

5154
(define-c-proc atomic? (obj) ::<boolean> SG_ATOMICP)
55+
(define-c-proc atomic-pair? (obj) ::<boolean> SG_ATOMIC_PAIR_P)
5256
(define-c-proc atomic-fixnum? (obj) ::<boolean> SG_ATOMIC_FIXNUM_P)
5357

5458
(define-c-proc atomic-load (a::<atomic> :optional (order::<memory-order> (default-memory-order))) Sg_AtomicLoad)

src/sagittarius/private/atomic.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,16 @@
3333
#include "sagittariusdefs.h"
3434
#include "clos.h"
3535

36+
typedef struct {
37+
SgObject car;
38+
SgObject cdr;
39+
} pair_t;
40+
3641
#ifdef HAVE_STDATOMIC_H
3742
# include <stdatomic.h>
3843

44+
typedef _Atomic pair_t atomic_pair_t;
45+
3946
# ifdef HAVE_ATOMIC_INTPTR_T
4047
typedef atomic_intptr_t atomic_object_t;
4148
typedef intptr_t object_t;
@@ -49,6 +56,7 @@ typedef size_t object_t;
4956
/* We define only what we need here */
5057
typedef long atomic_long;
5158
typedef intptr_t atomic_object_t;
59+
typedef pair_t atomic_pair_t;
5260
typedef intptr_t object_t;
5361

5462
typedef enum memory_order {
@@ -64,6 +72,7 @@ typedef enum memory_order {
6472
typedef memory_order SgMemoryOrder;
6573
typedef enum {
6674
SG_ATOMIC_FIXNUM,
75+
SG_ATOMIC_PAIR,
6776
SG_ATOMIC_OBJECT
6877
} SgAtomicType;
6978

@@ -73,6 +82,7 @@ typedef struct SgAtomicRefRec
7382
SgAtomicType type;
7483
union {
7584
atomic_long fixnum;
85+
atomic_pair_t pair;
7686
atomic_object_t object;
7787
} reference;
7888

@@ -86,16 +96,20 @@ SG_CLASS_DECL(Sg_AtomicClass);
8696
#define SG_ATOMIC_TYPE(obj) SG_ATOMIC(obj)->type
8797
#define SG_ATOMIC_FIXNUM_P(obj) \
8898
(SG_ATOMICP(obj) && SG_ATOMIC_TYPE(obj) == SG_ATOMIC_FIXNUM)
99+
#define SG_ATOMIC_PAIR_P(obj) \
100+
(SG_ATOMICP(obj) && SG_ATOMIC_TYPE(obj) == SG_ATOMIC_PAIR)
89101
#define SG_ATOMIC_OBJECT_P(obj) \
90102
(SG_ATOMICP(obj) && SG_ATOMIC_TYPE(obj) == SG_ATOMIC_OBJECT)
91103
#define SG_ATOMIC_REF_FIXNUM(obj) SG_ATOMIC(obj)->reference.fixnum
104+
#define SG_ATOMIC_REF_PAIR(obj) SG_ATOMIC(obj)->reference.pair
92105
#define SG_ATOMIC_REF_OBJECT(obj) SG_ATOMIC(obj)->reference.object
93106

94107
SG_CDECL_BEGIN
95108

96109
SG_EXTERN int Sg_MemoryOrderP(SgObject o);
97110

98111
SG_EXTERN SgObject Sg_MakeAtomic(SgObject obj);
112+
SG_EXTERN SgObject Sg_MakeAtomicPair(SgObject car, SgObject cdr);
99113
SG_EXTERN SgObject Sg_MakeAtomicFixnum(long n);
100114
SG_EXTERN SgObject Sg_AtomicLoad(volatile SgAtomic *o, SgMemoryOrder order);
101115
SG_EXTERN void Sg_AtomicStore(volatile SgAtomic *o, SgObject v,

0 commit comments

Comments
 (0)