Hi,
this is a very raw ugly patch that fix the deadlock when the user would
like to stop the GPS.
The patch is powered enable only when the user require a START command.
I have done some test.
Michael
diff --git a/gps_freerunner.c b/gps_freerunner.c
index 186e592..9cab5a3 100644
--- a/gps_freerunner.c
+++ b/gps_freerunner.c
@@ -19,11 +19,11 @@
#define GPS_DEBUG 0
-#define DFR(...) LOGD(__VA_ARGS__)
-
#if GPS_DEBUG
+# define DFR(...) LOGD(__VA_ARGS__)
# define D(...) LOGD(__VA_ARGS__)
#else
+# define DFR(...) ((void)0)
# define D(...) ((void)0)
#endif
@@ -838,9 +838,11 @@ gps_state_start( GpsState* s )
char cmd = CMD_START;
int ret;
- do { ret=write( s->control[0], &cmd, 1 ); }
+ do { ret = write( s->control[0], &cmd, 1 ); }
while (ret < 0 && errno == EINTR);
+ D("GPS start request");
+
if (ret != 1)
D("%s: could not send CMD_START command: ret=%d: %s",
__FUNCTION__, ret, strerror(errno));
@@ -853,6 +855,8 @@ gps_state_stop( GpsState* s )
char cmd = CMD_STOP;
int ret;
+ D("GPS stop request");
+
do { ret=write( s->control[0], &cmd, 1 ); }
while (ret < 0 && errno == EINTR);
@@ -863,19 +867,18 @@ gps_state_stop( GpsState* s )
static int
-epoll_register( int epoll_fd, int fd )
+epoll_register( int epoll_fd, int fd, struct epoll_event *ev)
{
- struct epoll_event ev;
int ret, flags;
/* important: make the fd non-blocking */
flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, flags | O_NONBLOCK);
- ev.events = EPOLLIN;
- ev.data.fd = fd;
+ ev->events = EPOLLIN;
+ ev->data.fd = fd;
do {
- ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, &ev );
+ ret = epoll_ctl( epoll_fd, EPOLL_CTL_ADD, fd, ev );
} while (ret < 0 && errno == EINTR);
return ret;
}
@@ -900,25 +903,21 @@ gps_state_thread( void* arg )
{
GpsState* state = (GpsState*) arg;
NmeaReader *reader;
- int epoll_fd = epoll_create(2);
- int started = 0;
- int gps_fd = state->fd;
- int control_fd = state->control[1];
+ struct epoll_event ev[2];
+ int epoll_fd = epoll_create(2);
+ int started = 0;
+ int gps_fd = state->fd;
+ int control_fd = state->control[1];
reader = &state->reader;
nmea_reader_init( reader );
// register control file descriptors for polling
- epoll_register( epoll_fd, control_fd );
- epoll_register( epoll_fd, gps_fd );
+ epoll_register( epoll_fd, control_fd, &ev[0] );
D("gps thread running");
- gps_dev_init(gps_fd);
-
- GPS_STATUS_CB(state->callbacks, GPS_STATUS_ENGINE_ON);
-
// now loop
for (;;) {
struct epoll_event events[2];
@@ -930,7 +929,6 @@ gps_state_thread( void* arg )
LOGE("epoll_wait() unexpected error: %s", strerror(errno));
continue;
}
- D("gps thread received %d events", nevents);
for (ne = 0; ne < nevents; ne++) {
if ((events[ne].events & (EPOLLERR|EPOLLHUP)) != 0) {
LOGE("EPOLLERR or EPOLLHUP after epoll_wait() !?");
@@ -956,12 +954,13 @@ gps_state_thread( void* arg )
if (!started) {
D("gps thread starting location_cb=%p", state->callbacks.location_cb);
started = 1;
-
+ gps_dev_init(gps_fd);
gps_dev_start(gps_fd);
GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_BEGIN);
state->init = STATE_START;
+ epoll_register( epoll_fd, gps_fd, &ev[1] );
if ( pthread_create( &state->tmr_thread, NULL, gps_timer_thread, state ) != 0 ) {
LOGE("could not create gps timer thread: %s", strerror(errno));
@@ -979,10 +978,12 @@ gps_state_thread( void* arg )
started = 0;
gps_dev_stop(gps_fd);
+ gps_dev_deinit(gps_fd);
state->init = STATE_INIT;
pthread_join(state->tmr_thread, &dummy);
+ epoll_deregister(epoll_fd, gps_fd);
GPS_STATUS_CB(state->callbacks, GPS_STATUS_SESSION_END);
@@ -991,24 +992,16 @@ gps_state_thread( void* arg )
}
else if (fd == gps_fd)
{
- char buff[32];
- D("gps fd event");
- for (;;) {
- int nn, ret;
-
- ret = read( fd, buff, sizeof(buff) );
- if (ret < 0) {
- if (errno == EINTR)
- continue;
- if (errno != EWOULDBLOCK)
- LOGE("error while reading from gps daemon socket: %s:", strerror(errno));
- break;
- }
+ char buff[1024];
+ int nn, ret;
+
+ ret = read( fd, buff, sizeof(buff) );
+ if (ret > 0) {
D("received %d bytes: %.*s", ret, ret, buff);
for (nn = 0; nn < ret; nn++)
nmea_reader_addc( reader, buff[nn] );
+ D("gps fd event end");
}
- D("gps fd event end");
}
else
{
@@ -1021,8 +1014,6 @@ Exit:
gps_dev_deinit(gps_fd);
- GPS_STATUS_CB(state->callbacks, GPS_STATUS_ENGINE_OFF);
-
return NULL;
}
@@ -1031,30 +1022,12 @@ gps_timer_thread( void* arg )
{
GpsState *state = (GpsState *)arg;
- pthread_mutex_t timer_mtx;
- pthread_cond_t timer_cond;
struct timespec to;
DFR("gps entered timer thread");
- pthread_mutex_init(&timer_mtx, NULL);
- pthread_cond_init(&timer_cond, NULL);
-
do {
- clock_gettime(CLOCK_MONOTONIC, &to);
-
- if (state->fix_freq > 0) {
- to.tv_sec += state->fix_freq;
- } else {
- to.tv_sec++;
- }
-
- pthread_mutex_lock(&timer_mtx);
-
- // binoic specific function - non POSIX */
- pthread_cond_timedwait_monotonic(&timer_cond, &timer_mtx, &to);
-
DFR ("gps timer exp");
GPS_STATE_LOCK_FIX(state);
@@ -1087,14 +1060,10 @@ gps_timer_thread( void* arg )
}
GPS_STATE_UNLOCK_FIX(state);
-
- pthread_mutex_unlock(&timer_mtx);
+ sleep(state->fix_freq);
} while(state->init == STATE_START);
- pthread_mutex_destroy(&timer_mtx);
- pthread_cond_destroy(&timer_cond);
-
DFR("gps timer thread destroyed");
return NULL;
@@ -1255,7 +1224,7 @@ freerunner_gps_set_fix_frequency(int freq)
DFR("%s: called", __FUNCTION__);
- s->fix_freq = freq;
+ s->fix_freq = (freq <= 0) ? 1 : freq;
DFR("gps fix frquency set to %d secs", freq);
}
_______________________________________________
android-freerunner mailing list
[email protected]
http://android.koolu.org/listinfo.cgi/android-freerunner-koolu.org