diff options
author | Eric S. Raymond <esr@thyrsus.com> | 2011-03-25 15:01:49 -0400 |
---|---|---|
committer | Eric S. Raymond <esr@thyrsus.com> | 2011-03-25 15:01:49 -0400 |
commit | a2c2a595f2588a53b7c804e688f459e8a1c5efaf (patch) | |
tree | 687479fc101d84a38a52736bcc3e8ba3df3c4752 /shmexport.c | |
parent | 398195bc3ec704e1deb6281418bb5ed97ef7c0fe (diff) | |
download | gpsd-a2c2a595f2588a53b7c804e688f459e8a1c5efaf.tar.gz |
First cut at shared-memory export. Daemon-side only.
Not configured in by default yet because it produces a strange regression
failure.
Diffstat (limited to 'shmexport.c')
-rw-r--r-- | shmexport.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/shmexport.c b/shmexport.c new file mode 100644 index 00000000..b9c330c4 --- /dev/null +++ b/shmexport.c @@ -0,0 +1,79 @@ +/**************************************************************************** + +NAME + shmexport.c - shared-memory exports from the daemon and how to read them + +DESCRIPTION + + +PERMISSIONS + This file is Copyright (c) 2010 by the GPSD project + BSD terms apply: see the file COPYING in the distribution root for details. + +***************************************************************************/ +#include <stddef.h> +#include <string.h> +#include <errno.h> +#include <sys/time.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#include "gpsd.h" + +#ifdef SHM_EXPORT_ENABLE +bool shm_acquire(struct gps_context_t *context) +/* initialize the shared-memory segment to be used for export */ +{ + int shmid; + + shmid = shmget((key_t)GPSD_KEY, sizeof(struct gps_data_t), (int)(IPC_CREAT|0666)); + if (shmid == -1) { + gpsd_report(LOG_ERROR, "shmget(%ld, %zd, 0666) failed: %s\n", + (long int)GPSD_KEY, + sizeof(struct gps_data_t), + strerror(errno)); + return false; + } + context->shmexport = (char *)shmat(shmid, 0, 0); + /*@ -mustfreefresh */ + if ((int)(long)context->shmexport == -1) { + gpsd_report(LOG_ERROR, "shmat failed: %s\n", strerror(errno)); + context->shmexport = NULL; + return false; + } + gpsd_report(LOG_PROG, "shmat() succeeded, segment %d\n", shmid); + return true; +} + +void shm_release(struct gps_context_t *context) +/* release the shared-memory segment used for export */ +{ + if (context->shmexport != NULL) + (void)shmdt((const void *)context->shmexport); +} + +void shm_update(struct gps_context_t *context, struct gps_data_t *gpsdata) +/* export an update to all listeners */ +{ + if (context->shmexport != NULL) + { + static int tick; + + ++tick; + /* + * Following block of instructions must not be reordered, otherwise + * havoc will ensue. asm volatile("sfence") is a GCCism intended + * to prevent reordering. + */ + ((struct shmexport_t *)context)->bookend2 = tick; + asm volatile("sfence"); + memcpy((void *)(context->shmexport + offsetof(struct shmexport_t, gpsdata)), + (void *)gpsdata, + sizeof(struct gps_data_t)); + asm volatile("sfence"); + ((struct shmexport_t *)context)->bookend1 = tick; + } +} +#endif /* SHM_EXPORT_ENABLE */ + +/* end */ |