summaryrefslogtreecommitdiff
path: root/libgps_shm.c
diff options
context:
space:
mode:
authorEric S. Raymond <esr@thyrsus.com>2015-03-06 14:39:18 -0500
committerEric S. Raymond <esr@thyrsus.com>2015-03-06 14:39:18 -0500
commit527d0f52feb0f0d48967dbd7b7580cce18fbdbe7 (patch)
tree0c25c23b72e8e2877b7e0ee94088a99a39ff7a43 /libgps_shm.c
parentb852278f33d6b280eed4107301e73ece96080ee5 (diff)
downloadgpsd-527d0f52feb0f0d48967dbd7b7580cce18fbdbe7.tar.gz
Insert memory barriers in libgps_shm_waiting().
Also, make sure it reurns false on timeout. All regression tests pass.
Diffstat (limited to 'libgps_shm.c')
-rw-r--r--libgps_shm.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/libgps_shm.c b/libgps_shm.c
index f55877bf..dc9bcc2c 100644
--- a/libgps_shm.c
+++ b/libgps_shm.c
@@ -77,19 +77,23 @@ bool gps_shm_waiting(const struct gps_data_t *gpsdata, int timeout)
{
volatile struct shmexport_t *shared = (struct shmexport_t *)PRIVATE(gpsdata)->shmseg;
timestamp_t basetime = timestamp();
+ volatile bool newdata = false;
/* busy-waiting sucks, but there's not really an alternative */
for (;;) {
- bool newdata = false;
+ volatile int bookend1, bookend2;
memory_barrier();
- if (shared->bookend1 == shared->bookend2 && shared->bookend1 > PRIVATE(gpsdata)->tick)
- newdata = true;
+ bookend1 = shared->bookend1;
+ memory_barrier();
+ bookend2 = shared->bookend2;
memory_barrier();
+ if (bookend1 == bookend2 && bookend1 > PRIVATE(gpsdata)->tick)
+ newdata = true;
if (newdata || (timestamp() - basetime >= (double)timeout))
break;
}
- return true;
+ return newdata;
}
int gps_shm_read(struct gps_data_t *gpsdata)