arith.c 2.54 KB
Newer Older
1
/*
2 3
 * Aurelio Colosimo for CERN, 2011 -- GNU LGPL v2.1 or later
 * Based on PTPd project v. 2.1.0 (see AUTHORS for details)
4 5
 */

6
#include <limits.h>
7
#include <pptp/pptp.h>
8
#include <pptp/diag.h>
9

10
void int64_to_TimeInternal(Integer64 bigint, TimeInternal *internal)
11
{
12 13 14 15
	uint64_t bigint_val;

	if (bigint.msb < 0)
		pp_printf("BUG: %s doesn't support negatives\n", __func__);
16

17
	bigint_val = bigint.lsb;
18
	bigint_val += ((int64_t)bigint.msb) << 32;
19

20 21 22
	/* Use __div64_32 from library, to avoid libgcc on small targets */
	internal->nanoseconds = __div64_32(&bigint_val, PP_NSEC_PER_SEC);
	internal->seconds = bigint_val;
23 24
}

25
int from_TimeInternal(TimeInternal *internal, Timestamp *external)
26 27 28 29 30
{
	/*
	 * fromInternalTime is only used to convert time given by the system
	 * to a timestamp As a consequence, no negative value can normally
	 * be found in (internal)
31
	 *
32 33 34 35 36
	 * Note that offsets are also represented with TimeInternal structure,
	 * and can be negative, but offset are never convert into Timestamp
	 * so there is no problem here.
	 */

37 38
	if ((internal->seconds & ~INT_MAX) ||
	    (internal->nanoseconds & ~INT_MAX)) {
39 40 41
		/* FIXME diag
		 * DBG("Negative value cannot be converted into timestamp \n");
		 */
42
		return -1;
43 44 45 46 47
	} else {
		external->secondsField.lsb = internal->seconds;
		external->nanosecondsField = internal->nanoseconds;
		external->secondsField.msb = 0;
	}
48
	return 0;
49 50
}

51
int to_TimeInternal(TimeInternal *internal, Timestamp *external)
52 53
{
	/* Program will not run after 2038... */
54
	if (external->secondsField.lsb < INT_MAX) {
55 56
		internal->seconds = external->secondsField.lsb;
		internal->nanoseconds = external->nanosecondsField;
57
		return 0;
58
	} else {
59
		/* FIXME diag
60 61
		DBG("Clock servo canno't be executed : "
		    "seconds field is higher than signed integer (32bits) \n");
62
		*/
63
		return -1;
64 65 66
	}
}

67
static void normalize_TimeInternal(TimeInternal *r)
68
{
69 70
	r->seconds += r->nanoseconds / PP_NSEC_PER_SEC;
	r->nanoseconds -= r->nanoseconds / PP_NSEC_PER_SEC * PP_NSEC_PER_SEC;
71 72

	if (r->seconds > 0 && r->nanoseconds < 0) {
73 74
		r->seconds -= 1;
		r->nanoseconds += PP_NSEC_PER_SEC;
75
	} else if (r->seconds < 0 && r->nanoseconds > 0) {
76 77
		r->seconds += 1;
		r->nanoseconds -= PP_NSEC_PER_SEC;
78 79 80
	}
}

81
void add_TimeInternal(TimeInternal *r, TimeInternal *x, TimeInternal *y)
82 83 84 85
{
	r->seconds = x->seconds + y->seconds;
	r->nanoseconds = x->nanoseconds + y->nanoseconds;

86
	normalize_TimeInternal(r);
87 88
}

89
void sub_TimeInternal(TimeInternal *r, TimeInternal *x, TimeInternal *y)
90 91 92 93
{
	r->seconds = x->seconds - y->seconds;
	r->nanoseconds = x->nanoseconds - y->nanoseconds;

94
	normalize_TimeInternal(r);
95
}