Hoernchen has uploaded this change for review.
libosmo_emb: type-safe tearfree_u64_t wrapper for LDRD/STRD access
Although types are frowned upon because memorizing all differerent flavors
of void* is the usual way to get acquainted with any mature C code base
some heretics decided to introduce generics in C11, which can be used to
make aligned access (which guarantees tear-free/restartable 64 bit access
on cortex m4) less exciting.
Change-Id: I458bfaf53e27c51882c7a8c1326e51d12943b0bb
---
M ccid_common/cuart.h
M ccid_host/libosmo_emb.h
M sysmoOCTSIM/libosmo_emb.c
M sysmoOCTSIM/libosmo_emb.h
4 files changed, 45 insertions(+), 20 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-ccid-firmware refs/changes/84/42784/1
diff --git a/ccid_common/cuart.h b/ccid_common/cuart.h
index a53dc18..d31d2d9 100644
--- a/ccid_common/cuart.h
+++ b/ccid_common/cuart.h
@@ -102,7 +102,7 @@
uint32_t wtime_etu;
/* deadline in jiffies (ms) for card response timeout, 0 = inactive.
* Set from IRQ context, checked from main loop */
- volatile uint64_t wtime_deadline __attribute__((aligned(8)));
+ tearfree_u64_t wtime_deadline;
/* expected number of bytes, for timeout */
uint32_t current_wtime_byte;
diff --git a/ccid_host/libosmo_emb.h b/ccid_host/libosmo_emb.h
index ffc0324..e811dd3 100644
--- a/ccid_host/libosmo_emb.h
+++ b/ccid_host/libosmo_emb.h
@@ -1,15 +1,23 @@
#pragma once
-/* Host-side jiffies emulation */
+/* Host-side jiffies emulation
+ * On the host every access is a plain memory access; the typed wrapper exists
+ * only purely for type compatibility with code shared with the embedded target. */
#include <stdint.h>
+#include <stdalign.h>
-static inline uint64_t ldrd_u64(const volatile uint64_t *p)
-{
- return *p;
-}
-static inline void strd_u64(volatile uint64_t *p, uint64_t v)
-{
- *p = v;
-}
+typedef struct {
+ alignas(8) volatile uint64_t _v;
+} tearfree_u64_t;
+
+static inline uint64_t _ldrd_u64(const tearfree_u64_t *p) { return p->_v; }
+static inline void _strd_u64(tearfree_u64_t *p, uint64_t v) { p->_v = v; }
+
+#define ldrd_u64(p) _Generic((p), \
+ tearfree_u64_t *: _ldrd_u64, \
+ const tearfree_u64_t *: _ldrd_u64)(p)
+
+#define strd_u64(p, v) _Generic((p), \
+ tearfree_u64_t *: _strd_u64)((p), (v))
uint64_t get_jiffies(void);
diff --git a/sysmoOCTSIM/libosmo_emb.c b/sysmoOCTSIM/libosmo_emb.c
index e96f88e..731268b 100644
--- a/sysmoOCTSIM/libosmo_emb.c
+++ b/sysmoOCTSIM/libosmo_emb.c
@@ -17,7 +17,7 @@
#include "driver_init.h"
#include "libosmo_emb.h"
-volatile uint64_t jiffies __attribute__((aligned(8)));
+tearfree_u64_t jiffies;
uint64_t get_jiffies(void)
{
@@ -31,7 +31,7 @@
void SysTick_Handler(void)
{
- jiffies++;
+ jiffies._v++;
}
int _gettimeofday(struct timeval *tv, void *tz)
diff --git a/sysmoOCTSIM/libosmo_emb.h b/sysmoOCTSIM/libosmo_emb.h
index 4b576c6..705982c 100644
--- a/sysmoOCTSIM/libosmo_emb.h
+++ b/sysmoOCTSIM/libosmo_emb.h
@@ -7,42 +7,59 @@
*
* Worst-case outcome is being off by one tick (1 ms) which is irrelevant
* for the timeout use-case.
+ *
+ * To enforce the alignment requirement the underlying
+ * uint64_t is wrapped in a struct with 8-byte
+ * alignment via alignas(8) + _Generic to ensure types.
*/
#include <stdint.h>
+#include <stdalign.h>
+
+typedef struct {
+ alignas(8) volatile uint64_t _v;
+} tearfree_u64_t;
#if defined(__arm__)
-static inline uint64_t ldrd_u64(const volatile uint64_t *p)
+static inline uint64_t _ldrd_u64(const tearfree_u64_t *p)
{
uint32_t lo, hi;
__asm__ volatile(
"ldrd %0, %1, [%2]\n"
: "=&r"(lo), "=&r"(hi)
- : "r"(p)
+ : "r"(&p->_v)
: "memory");
return ((uint64_t)hi << 32) | lo;
}
-static inline void strd_u64(volatile uint64_t *p, uint64_t v)
+static inline void _strd_u64(tearfree_u64_t *p, uint64_t v)
{
uint32_t lo = (uint32_t)v;
uint32_t hi = (uint32_t)(v >> 32);
__asm__ volatile(
"strd %1, %2, [%0]\n"
- : : "r"(p), "r"(lo), "r"(hi)
+ : : "r"(&p->_v), "r"(lo), "r"(hi)
: "memory");
}
#else
/* host */
-static inline uint64_t ldrd_u64(const volatile uint64_t *p)
+static inline uint64_t _ldrd_u64(const tearfree_u64_t *p)
{
- return *p;
+ return p->_v;
}
-static inline void strd_u64(volatile uint64_t *p, uint64_t v)
+static inline void _strd_u64(tearfree_u64_t *p, uint64_t v)
{
- *p = v;
+ p->_v = v;
}
#endif
+/* _Generic ensures matched types or bust */
+#define ldrd_u64(p) _Generic((p), \
+ tearfree_u64_t *: _ldrd_u64, \
+ const tearfree_u64_t *: _ldrd_u64)(p)
+
+#define strd_u64(p, v) _Generic((p), \
+ tearfree_u64_t *: _strd_u64)((p), (v))
+
uint64_t get_jiffies(void);
void store_jiffies(uint64_t j);
To view, visit change 42784. To unsubscribe, or for help writing mail filters, visit settings.