diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2011-03-26 15:57:25 -0400 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2011-03-26 15:57:25 -0400 |
commit | 67146ae418f2308e3da0221ce2d74827c2dab7b7 (patch) | |
tree | 77264e5d0436359f627446c1f93a899820792729 /libgps_shm.c | |
parent | 508f0d14817163182b03489edb4e0d8f12e51bc5 (diff) | |
download | gpsd-67146ae418f2308e3da0221ce2d74827c2dab7b7.tar.gz |
Startlingly, memcpy() is *less* of a problem for the seqlock than I thought.
Diffstat (limited to 'libgps_shm.c')
-rw-r--r-- | libgps_shm.c | 24 |
1 files changed, 16 insertions, 8 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; } |