Make ao_log_data re-entrant as it is used for both sensor and GPS logs
authorKeith Packard <keithp@keithp.com>
Wed, 28 Jul 2010 16:31:09 +0000 (09:31 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 28 Jul 2010 18:19:45 +0000 (11:19 -0700)
commitf2a006fd98045066bdf429cc142d033e9feb0a8f
tree6bd1cdcd24bc7403663eff85b6e0a9c0fedf7710
parent05111d5be4d37bedaaee6415d6ee27347e6a112c
Make ao_log_data re-entrant as it is used for both sensor and GPS logs

Because ao_log_data is called from two different threads, failing to
make it re-entrant would cause the 'log' pointer parameter to get
overwritten if another thread asked to log data while the eeprom was
busy writing out a block.

This would cause the second thread to re-writing data from the first
thread's address, but without re-checksumming the data as the checksum
is computed before the log mutex is taken.

The bug can be seen by log blocks with invalid checksums.

Here's what happens with the ao_gps_tracking_report and ao_log threads:

  ao_gps_tracking_report ao_log

   Writes a bunch of records
   *blocks* in the eeprom flush
sets ao_log_data 'log' to global 'log'
computes checksum for 'log' block
*blocks* on ao_log_mutex
   Wakes up
   sets ao_log_data 'log' to 'gps_log'
   writes remaining records
   'gps_log' is left with svid = 0
   *blocks* on ao_gps_tracking_data
writes data, reading from
the current ao_log_data 'log'
pointer which points at 'gps_log'

Making ao_log_data re-entrant fixes this by ensuring that the 'ao_log'
thread has its own copy of the ao_log_data 'log' parameter.

I made this function take an __xdata restricted pointer so that it
could be passed in the dptr register instead of needing to go on the stack.

Signed-off-by: Keith Packard <keithp@keithp.com>
src/ao.h
src/ao_log.c