diff options
-rw-r--r-- | libgps_shm.c | 24 | ||||
-rw-r--r-- | shmexport.c | 2 | ||||
-rw-r--r-- | www/hacking.html | 5 |
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. |