diff options
-rw-r--r-- | gpsd.h-tail | 16 | ||||
-rw-r--r-- | gpsmon.c | 18 | ||||
-rw-r--r-- | libgpsd_core.c | 21 | ||||
-rw-r--r-- | ppsthread.c | 53 | ||||
-rw-r--r-- | ppsthread.h | 47 |
5 files changed, 104 insertions, 51 deletions
diff --git a/gpsd.h-tail b/gpsd.h-tail index 0be3877b..318ebf37 100644 --- a/gpsd.h-tail +++ b/gpsd.h-tail @@ -9,6 +9,7 @@ #include <stdint.h> #include <stdarg.h> #include "gps.h" +#include "ppsthread.h" #include "compiler.h" /* @@ -499,12 +500,7 @@ struct gps_device_t { volatile /*@null@*/ struct shmTime *shm_pps; # endif /* PPS_ENABLE */ #endif /* NTP_ENABLE */ - volatile struct { - timestamp_t real; - /* clock must be a timespec as it is in nSec and - * a timestamp_t will lose precision */ - struct timespec clock; /* system clock time when last fix received */ - } last_fixtime; /* so updates happen once */ + volatile struct pps_fixtime_t last_fixtime; /* so updates happen once */ #ifdef PPS_ENABLE #if defined(HAVE_SYS_TIMEPPS_H) pps_handle_t kernelpps_handle; @@ -513,8 +509,7 @@ struct gps_device_t { /*@null@*/ char *(*thread_report_hook)(struct gps_device_t *, struct timedelta_t *); /*@null@*/ void (*thread_wrap_hook)(struct gps_device_t *); - volatile struct timedelta_t ppslast; - volatile int ppscount; + struct pps_state_t pps_state; #endif /* PPS_ENABLE */ double mag_var; /* magnetic variation in degrees */ bool back_to_nmea; /* back to NMEA on revert? */ @@ -971,13 +966,8 @@ extern void pps_early_init(struct gps_context_t *); extern void timespec_str(const struct timespec *, /*@out@*/char *, int); #define TIMESPEC_LEN 22 /* required length of a timespec buffer */ -#ifdef PPS_ENABLE -extern void pps_thread_stash_fixtime(struct gps_device_t *, - timestamp_t, struct timespec); -#endif /* PPS_ENABLE */ extern void pps_thread_activate(struct gps_device_t *); extern void pps_thread_deactivate(struct gps_device_t *); -extern int pps_thread_lastpps(struct gps_device_t *, struct timedelta_t *); extern void errout_reset(struct gpsd_errout_t *errout); @@ -249,7 +249,19 @@ void pps_update(WINDOW *win, int y, int x) /*@-type -noeffect@*/ /* splint is confused about struct timespec */ struct timedelta_t ppstimes; - if (pps_thread_lastpps(&session, &ppstimes) > 0) { + int status = pps_thread_lastpps(&session.pps_state, &ppstimes); + + if (status == PPS_LOCK_ERR) { + char errbuf[BUFSIZ] = "unknown error"; + (void)strerror_r(errno, errbuf,(int) sizeof(errbuf)); + gpsd_report(&session.context->errout, LOG_ERROR, + "PPS: pthread_mutex_unlock() : %s\n", errbuf); + } else if (status == PPS_LOCK_ERR) { + char errbuf[BUFSIZ] = "unknown error"; + (void)strerror_r(errno, errbuf,(int) sizeof(errbuf)); + gpsd_report(&session.context->errout, LOG_ERROR, + "PPS: pthread_mutex_lock() : %s\n", errbuf); + } else { /* NOTE: can not use double here due to precision requirements */ struct timespec timedelta; (void)wmove(win, y, x); @@ -790,9 +802,9 @@ static void gpsmon_hook(struct gps_device_t *device, gps_mask_t changed UNUSED) "------------------- PPS offset: %.20s ------\n ", timedelta_str); /* coverity[missing_lock] */ - session.ppslast = noclobber.pps; + session.pps_state.ppslast = noclobber.pps; /* coverity[missing_lock] */ - session.ppscount++; + session.pps_state.ppscount++; } } else diff --git a/libgpsd_core.c b/libgpsd_core.c index 7fae7006..d9db154a 100644 --- a/libgpsd_core.c +++ b/libgpsd_core.c @@ -307,8 +307,7 @@ void gpsd_init(struct gps_device_t *session, struct gps_context_t *context, /*@i2@*/session->last_fixtime.clock.tv_sec = 0; /*@i2@*/session->last_fixtime.clock.tv_nsec = 0; #ifdef PPS_ENABLE - memset( (void *)&session->ppslast, 0, sizeof(session->ppslast)); - session->ppscount = 0; + memset((void *)&session->pps_state, 0, sizeof(session->pps_state)); #endif /* PPS_ENABLE */ /*@ -mayaliasunique @*/ @@ -406,8 +405,7 @@ void gpsd_clear(struct gps_device_t *session) /*@i2@*/session->last_fixtime.clock.tv_sec = 0; /*@i2@*/session->last_fixtime.clock.tv_nsec = 0; #ifdef PPS_ENABLE - memset( (void *)&session->ppslast, 0, sizeof(session->ppslast)); - session->ppscount = 0; + memset((void *)&session->pps_state, 0, sizeof(session->pps_state)); #endif /* PPS_ENABLE */ session->opentime = timestamp(); @@ -1619,6 +1617,7 @@ void ntp_latch(struct gps_device_t *device, struct timedelta_t /*@out@*/*td) /* latch the fact that we've saved a fix */ { double fix_time, integral, fractional; + int status; /* this should be an invariant of the way this function is called */ assert(isnan(device->newdata.time)==0); @@ -1648,8 +1647,20 @@ void ntp_latch(struct gps_device_t *device, struct timedelta_t /*@out@*/*td) #ifdef PPS_ENABLE /* thread-safe update */ /*@-compdef@*/ - pps_thread_stash_fixtime(device, device->newdata.time, td->clock); + status = pps_thread_stash_fixtime(&device->last_fixtime, + device->newdata.time, td->clock); /*@+compdef@*/ + if (status == PPS_LOCK_ERR) { + char errbuf[BUFSIZ] = "unknown error"; + (void)strerror_r(errno, errbuf,(int) sizeof(errbuf)); + gpsd_report(&device->context->errout, LOG_ERROR, + "PPS: pthread_mutex_unlock() : %s\n", errbuf); + } else if (status == PPS_LOCK_ERR) { + char errbuf[BUFSIZ] = "unknown error"; + (void)strerror_r(errno, errbuf,(int) sizeof(errbuf)); + gpsd_report(&device->context->errout, LOG_ERROR, + "PPS: pthread_mutex_lock() : %s\n", errbuf); + } #endif /* PPS_ENABLE */ } #endif /* NTP_ENABLE */ diff --git a/ppsthread.c b/ppsthread.c index 73d1cfdc..52512bc8 100644 --- a/ppsthread.c +++ b/ppsthread.c @@ -704,9 +704,9 @@ static /*@null@*/ void *gpsd_ppsmonitor(void *arg) } /*@ +unrecog @*/ /*@-type@*/ /* splint is confused about struct timespec */ - session->ppslast = ppstimes; + session->pps_state.ppslast = ppstimes; /*@+type@*/ - session->ppscount++; + session->pps_state.ppscount++; /*@ -unrecog (splint has no pthread declarations as yet) @*/ pthread_err = pthread_mutex_unlock(&ppslast_mutex); if ( 0 != pthread_err ) { @@ -787,33 +787,31 @@ void pps_thread_deactivate(struct gps_device_t *session) /*@+nullstate +mustfreeonly@*/ } -void pps_thread_stash_fixtime(struct gps_device_t *session, +int pps_thread_stash_fixtime(volatile struct pps_fixtime_t *last_fixtime, timestamp_t realtime, struct timespec clocktime) /* thread-safe update of last fix time - only way we pass data in */ { + int ret = PPS_THREAD_OK; + /*@ -unrecog (splint has no pthread declarations as yet) @*/ int pthread_err = pthread_mutex_lock(&ppslast_mutex); - if ( 0 != pthread_err ) { - char errbuf[BUFSIZ] = "unknown error"; - (void)strerror_r(errno, errbuf, (int)sizeof(errbuf)); - gpsd_report(&session->context->errout, LOG_ERROR, - "PPS: pthread_mutex_lock() : %s\n", errbuf); - } + if ( 0 != pthread_err ) + ret = PPS_LOCK_ERR; + else { /*@ +unrecog @*/ - session->last_fixtime.real = realtime; - session->last_fixtime.clock = clocktime; + last_fixtime->real = realtime; + last_fixtime->clock = clocktime; + } /*@ -unrecog (splint has no pthread declarations as yet) @*/ pthread_err = pthread_mutex_unlock(&ppslast_mutex); - if ( 0 != pthread_err ) { - char errbuf[BUFSIZ] = "unknown error"; - (void)strerror_r(errno, errbuf, (int)sizeof(errbuf)); - gpsd_report(&session->context->errout, LOG_ERROR, - "PPS: pthread_mutex_unlock() : %s\n", errbuf); - } + if ( 0 != pthread_err ) + ret = PPS_UNLOCK_ERR; /*@ +unrecog @*/ + + return ret; } -int pps_thread_lastpps(struct gps_device_t *session, struct timedelta_t *td) +int pps_thread_lastpps(struct pps_state_t *pps_state, struct timedelta_t *td) /* return the delta at the time of the last PPS - only way we pass data out */ { volatile int ret; @@ -822,22 +820,17 @@ int pps_thread_lastpps(struct gps_device_t *session, struct timedelta_t *td) /*@ -unrecog (splint has no pthread declarations as yet) @*/ pthread_err = pthread_mutex_lock(&ppslast_mutex); - if ( 0 != pthread_err ) { - char errbuf[BUFSIZ] = "unknown error"; - (void)strerror_r(errno, errbuf,(int) sizeof(errbuf)); - gpsd_report(&session->context->errout, LOG_ERROR, - "PPS: pthread_mutex_lock() : %s\n", errbuf); + if ( 0 != pthread_err ) + ret = PPS_LOCK_ERR; + else { + /*@ +unrecog @*/ + *td = pps_state->ppslast; + ret = pps_state->ppscount; } - /*@ +unrecog @*/ - *td = session->ppslast; - ret = session->ppscount; /*@ -unrecog (splint has no pthread declarations as yet) @*/ pthread_err = pthread_mutex_unlock(&ppslast_mutex); if ( 0 != pthread_err ) { - char errbuf[BUFSIZ] = "unknown error"; - (void)strerror_r(errno, errbuf, (int)sizeof(errbuf)); - gpsd_report(&session->context->errout, LOG_ERROR, - "PPS: pthread_mutex_unlock() : %s\n", errbuf); + ret = PPS_UNLOCK_ERR; } /*@ +unrecog @*/ diff --git a/ppsthread.h b/ppsthread.h new file mode 100644 index 00000000..ae7bd886 --- /dev/null +++ b/ppsthread.h @@ -0,0 +1,47 @@ +/* + * This file is Copyright (c) 2015 by the GPSD project + * BSD terms apply: see the file COPYING in the distribution root for details. + */ + +#ifndef PPSTHREAD_H +#define PPSTHREAD_H + +#include <stdbool.h> +#include <time.h> +#include <sys/time.h> +#include <sys/ipc.h> +#include <sys/shm.h> + +#ifndef HAVE_TIMEDELTA + +struct timedelta_t { + struct timespec real; + struct timespec clock; +}; + +#define HAVE_TIMEDELTA +#endif /* HAVE_TIMEDELTA */ + +struct pps_state_t { + volatile struct timedelta_t ppslast; + volatile int ppscount; +}; + +struct pps_fixtime_t { + timestamp_t real; + /* clock must be a timespec as it is in nSec and + * a timestamp_t will lose precision */ + struct timespec clock; /* system clock time when last fix received */ +}; + +#define PPS_THREAD_OK 0 +#define PPS_LOCK_ERR -1 +#define PPS_UNLOCK_ERR -2 + +extern int pps_thread_stash_fixtime(volatile struct pps_fixtime_t *, + timestamp_t, struct timespec); +extern int pps_thread_lastpps(struct pps_state_t *, struct timedelta_t *); + +#endif /* PPSTHREAD_H */ + +/* end */ |