[LinuxPPS] Re: OK, I found an error, please fix.
Rodolfo Giometti
giometti at enneenne.com
Mon Oct 22 09:32:54 CEST 2007
On Sun, Oct 21, 2007 at 06:00:24PM -0600, clemens at dwf.com wrote:
>
> OK, I found the error.
Good job! :)
> In kapi.c/pps_event, you call pps_add_offset to add any offset that has been
> provided.
>
> The arguments to pps_add_offset are of type pps_ktime, defined as
>
> struct pps_ktime {
> __u64 sec;
> __u32 nsec;
> __u32 flags;
> };
>
> in pps.h .
>
> (1) FIRST PROBLEM: Offset can be negative so it cant be of type pps_ktime.
> If negative, its value has been screwed up by the time you get here.
>
> In pps_add_offset, you add the offset to the time, putting the result back
> in ts->nsec. You then normalize the result if the number of ns has gone
> above NSEC_PER_SEC (this works) or if it goes below ZERO (this doesnt work)
> since ts->nsec is unsigned and the result will never be below ZERO.
>
> (2) SECOND PROBLEM: ts->nsec is UNSIGNED, so the test
>
> } else if (ts->nsec < 0) {
>
> always fails.
>
> In fact, my offset is negative, and Im sure that this is what is biting
> me in the ass. Im not sure how I seem to get several seconds off but Ill worry
> about that when the above is fixed.
>
> Seems you need EITHER to NOT make ktime up out of unsigned's or you need
> a parallel structure with signed variables in it.
>
> Ill wait to see what your solution is.
Since offsets are related with struct timespec which is defined as follow:
struct timespec {
time_t tv_sec; /* seconds */
long tv_nsec; /* nanoseconds */
};
where time_t is long, I suppose the right-thing(C) to do is to use
signed data. So, please, try this patch:
diff --git a/include/linux/pps.h b/include/linux/pps.h
index 5bdb593..1501793 100644
--- a/include/linux/pps.h
+++ b/include/linux/pps.h
@@ -54,8 +54,8 @@
* [David Woodhouse]
*/
struct pps_ktime {
- __u64 sec;
- __u32 nsec;
+ __s64 sec;
+ __s32 nsec;
__u32 flags;
};
#define PPS_TIME_INVALID (1<<0) /* used to specify timeout==NULL */
> AND, I seem to remember some old NTP code where the the IF and ELSE in the
> pps_add_offset normalization were in fact while loops, with the thought that they
> should only be gone thru once, ... but just in case ... they would get the right answer.
About this try this patch:
diff --git a/drivers/pps/kapi.c b/drivers/pps/kapi.c
index 67290d5..3546dab 100644
--- a/drivers/pps/kapi.c
+++ b/drivers/pps/kapi.c
@@ -44,10 +44,11 @@ static DEFINE_IDR(pps_idr);
static void pps_add_offset(struct pps_ktime *ts, struct pps_ktime *offset)
{
ts->nsec += offset->nsec;
- if (ts->nsec >= NSEC_PER_SEC) {
+ while (ts->nsec >= NSEC_PER_SEC) {
ts->nsec -= NSEC_PER_SEC;
ts->sec++;
- } else if (ts->nsec < 0) {
+ }
+ while (ts->nsec < 0) {
ts->nsec += NSEC_PER_SEC;
ts->sec--;
}
Currently I have no time to test these patches, so please, try them
and report if they work. :)
Thanks a lot for your time,
Rodolfo
--
GNU/Linux Solutions e-mail: giometti at enneenne.com
Linux Device Driver giometti at gnudd.com
Embedded Systems giometti at linux.it
UNIX programming phone: +39 349 2432127
More information about the LinuxPPS
mailing list