summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libgps_shm.c24
-rw-r--r--shmexport.c2
-rw-r--r--www/hacking.html5
3 files changed, 17 insertions, 14 deletions
diff --git a/libgps_shm.c b/libgps_shm.c
index 5a6c2442..f066a7ad 100644
--- a/libgps_shm.c
+++ b/libgps_shm.c
@@ -54,21 +54,29 @@ int gps_shm_read(struct gps_data_t *gpsdata)
int before, after;
struct shmexport_t *shared = (struct shmexport_t *)gpsdata->privdata;
- before = shared->bookend1;
/*
- * The bookend-consistency technique wants this to be a forward copy.
- * But it is not guaranteed, that memcpy() works this way, and some compilers on some platforms
- * are known to implement it as a reverse copy. Notably GCC does
- * this on x64 Atom.
+ * Following block of instructions must not be reordered, otherwise
+ * havoc will ensue. asm volatile("sfence") is a GCCism intended
+ * to prevent reordering.
*
- * The safest thing to do here would be to use a naive C implementation
- * of forward byte copy, but if we did that we'd be sacrificing the
- * superior performance of the asm optimization GCC does for
+ * This is a simple optimistic-concurrency tachnique. We wrote
+ * the second bookend first, then the data, then the first bookend.
+ * Reader copies what it sees in normal order; that way, if we
+ * start to write the segment during the read, the second bookend will
+ * get clobbered first and the data can be detected as bad.
*/
+ before = shared->bookend1;
+#ifndef S_SPLINT_S
+ asm volatile("sfence");
+#endif /* S_SPLINT_S */
(void)memcpy((void *)gpsdata,
(void *)&shared->gpsdata,
sizeof(struct gps_data_t));
+#ifndef S_SPLINT_S
+ asm volatile("sfence");
+#endif /* S_SPLINT_S */
after = shared->bookend2;
+
/*@i1@*/gpsdata->privdata = shared;
return (before == after) ? 0 : -1;
}
diff --git a/shmexport.c b/shmexport.c
index 88d110bd..d881417b 100644
--- a/shmexport.c
+++ b/shmexport.c
@@ -74,7 +74,7 @@ void shm_update(struct gps_context_t *context, struct gps_data_t *gpsdata)
* the second bookend first, then the data, then the first bookend.
* Reader copies what it sees in normal order; that way, if we
* start to write the segment during the read, the second bookend will
- * get clobbered first and the data can be detected bad.
+ * get clobbered first and the data can be detected as bad.
*/
((struct shmexport_t *)context->shmexport)->bookend2 = tick;
#ifndef S_SPLINT_S
diff --git a/www/hacking.html b/www/hacking.html
index 59c79116..dd794f05 100644
--- a/www/hacking.html
+++ b/www/hacking.html
@@ -562,11 +562,6 @@ on weird machines. The regression test should spot these.</p>
an unusual set of data type widths, take a look at bits.h. We've
tried to collect all the architecture dependencies here.</p>
-<p>If you are porting to GCC on x64 Atom or any other compiler/machine
-combination where you suspect memcpy(3) might be implemented by
-reverse rather than forward copy, it may screw up the shared-memory
-export. Read the comment about this in libgps_shm.c and beware.</p>
-
<h2 id="architecture">Architecture and how to hack it</h2>
<p>There are two useful ways to think about the GPSD architecture.