[PATCH 2/2] kern_ntptime.c: Port to RTEMS

Sebastian Huber sebastian.huber at embedded-brains.de
Tue Feb 8 15:16:22 UTC 2022


Remove previous adjtime() implementation.

Update #2348.
---
 cpukit/include/rtems/score/timecounter.h  |   9 ++
 cpukit/include/sys/timex.h                |   4 +-
 cpukit/posix/src/adjtime.c                |  93 ---------------
 cpukit/score/src/kern_ntptime.c           | 138 ++++++++++++++++++++++
 cpukit/score/src/kern_tc.c                |   6 +-
 spec/build/cpukit/librtemscpu.yml         |   2 +-
 spec/build/testsuites/sptests/grp.yml     |   2 +
 spec/build/testsuites/sptests/spntp01.yml |  19 +++
 testsuites/psxtests/psxtime/test.c        |  10 +-
 testsuites/sptests/spntp01/init.c         | 111 +++++++++++++++++
 10 files changed, 289 insertions(+), 105 deletions(-)
 delete mode 100644 cpukit/posix/src/adjtime.c
 create mode 100644 spec/build/testsuites/sptests/spntp01.yml
 create mode 100644 testsuites/sptests/spntp01/init.c

diff --git a/cpukit/include/rtems/score/timecounter.h b/cpukit/include/rtems/score/timecounter.h
index 39f0dc353e..954da65676 100644
--- a/cpukit/include/rtems/score/timecounter.h
+++ b/cpukit/include/rtems/score/timecounter.h
@@ -270,6 +270,15 @@ void _Timecounter_Set_NTP_update_second(
   Timecounter_NTP_update_second handler
 );
 
+/**
+ * @brief Updates the time adjustment and seconds according to the NTP state.
+ *
+ * @param[in, out] adjustment is the NTP time adjustment.
+ *
+ * @param[in, out] newsec is the number of seconds since Unix epoch.
+ */
+void _Timecounter_NTP_update_second(int64_t *adjustment, time_t *newsec);
+
 /** @} */
 
 #ifdef __cplusplus
diff --git a/cpukit/include/sys/timex.h b/cpukit/include/sys/timex.h
index d2d2012ff5..8e763bb30f 100644
--- a/cpukit/include/sys/timex.h
+++ b/cpukit/include/sys/timex.h
@@ -37,7 +37,7 @@
 
 #define NTP_API		4		/* NTP API version */
 
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__rtems__)
 #include <sys/_timespec.h>
 #endif /* __FreeBSD__ */
 
@@ -153,7 +153,7 @@ struct timex {
 	long	stbcnt;			/* stability limit exceeded (ro) */
 };
 
-#ifdef __FreeBSD__
+#if defined(__FreeBSD__) || defined(__rtems__)
 
 #ifdef _KERNEL
 void	ntp_update_second(int64_t *adjustment, time_t *newsec);
diff --git a/cpukit/posix/src/adjtime.c b/cpukit/posix/src/adjtime.c
deleted file mode 100644
index ec8cb19a2e..0000000000
--- a/cpukit/posix/src/adjtime.c
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- *  @file
- *
- *  @brief Adjust the Time to Synchronize the System Clock
- *  @ingroup POSIXAPI
- */
-
-/*
- *  COPYRIGHT (c) 1989-2014.
- *  On-Line Applications Research Corporation (OAR).
- *
- *  The license and distribution terms for this file may be
- *  found in the file LICENSE in this distribution or at
- *  http://www.rtems.org/license/LICENSE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#define _BSD_SOURCE
-#include <time.h>
-#include <sys/time.h>
-#include <errno.h>
-
-#include <rtems/score/timespec.h>
-#include <rtems/score/threaddispatch.h>
-#include <rtems/score/todimpl.h>
-#include <rtems/config.h>
-#include <rtems/seterr.h>
-
-/**
- * This method was initially added as part of porting NTP to RTEMS.
- * It is a BSD compatability function and now is available on
- * GNU/Linux.
- * 
- * At one point there was a static variable named adjustment
- * used by this implementation.  I don't see any reason for it
- * to be here based upon the GNU/Linux documentation.
- */
-int adjtime(
-  const struct timeval *delta,
-  struct timeval       *olddelta
-)
-{
-  struct timespec delta_as_timespec;
-  Status_Control  status;
-
-  /*
-   * Simple validations
-   */
-  if ( !delta )
-    rtems_set_errno_and_return_minus_one( EINVAL );
-
-  if ( delta->tv_usec >= TOD_MICROSECONDS_PER_SECOND )
-    rtems_set_errno_and_return_minus_one( EINVAL );
-
-  /*
-   * An adjustment of zero is pretty easy.
-   */
-  if ( delta->tv_sec == 0 && delta->tv_usec == 0 )
-    return 0;
-
-  /*
-   * Currently, RTEMS does the adjustment in one movement so there
-   * is no way an adjustment was currently underway.
-   *
-   * Given interest, requirements, and sponsorship, a future
-   * enhancement would be to adjust the time in smaller increments
-   * at each clock tick. Until then, there is no outstanding
-   * adjustment.
-   */
-  if ( olddelta ) {
-    olddelta->tv_sec  = 0;
-    olddelta->tv_usec = 0;
-  }
-
-  /*
-   * convert delta timeval to timespec
-   */
-  delta_as_timespec.tv_sec = delta->tv_sec;
-  delta_as_timespec.tv_nsec = delta->tv_usec * 1000;
-
-  /*
-   * Now apply the adjustment
-   */
-  status = _TOD_Adjust( &delta_as_timespec );
-  if ( status != STATUS_SUCCESSFUL ) {
-    rtems_set_errno_and_return_minus_one( STATUS_GET_POSIX( status ) );
-  }
-
-  return 0;
-}
diff --git a/cpukit/score/src/kern_ntptime.c b/cpukit/score/src/kern_ntptime.c
index 96f14a408b..cb39133408 100644
--- a/cpukit/score/src/kern_ntptime.c
+++ b/cpukit/score/src/kern_ntptime.c
@@ -1,3 +1,12 @@
+/**
+ * @file
+ *
+ * @ingroup RTEMSScoreTimecounter
+ *
+ * @brief This source file contains the implementation of ntp_gettime(),
+ *   ntp_adjtime(), adjtime(), and _Timecounter_NTP_update_second().
+ */
+
 /*-
  ***********************************************************************
  *								       *
@@ -36,6 +45,7 @@ __FBSDID("$FreeBSD$");
 #include "opt_ntp.h"
 
 #include <sys/param.h>
+#ifndef __rtems__
 #include <sys/systm.h>
 #include <sys/sysproto.h>
 #include <sys/eventhandler.h>
@@ -44,12 +54,24 @@ __FBSDID("$FreeBSD$");
 #include <sys/proc.h>
 #include <sys/lock.h>
 #include <sys/mutex.h>
+#endif /* __rtems__ */
 #include <sys/time.h>
 #include <sys/timex.h>
 #include <sys/timetc.h>
 #include <sys/timepps.h>
+#ifndef __rtems__
 #include <sys/syscallsubr.h>
 #include <sys/sysctl.h>
+#else /* __rtems__ */
+#include <rtems/sysinit.h>
+#include <rtems/score/timecounter.h>
+#include <errno.h>
+#include <string.h>
+#define	nanotime(_tsp) _Timecounter_Nanotime(_tsp)
+#define	ntp_update_second _Timecounter_NTP_update_second
+#define	time_uptime _Timecounter_Time_uptime
+struct thread;
+#endif /* __rtems__ */
 
 #ifdef PPS_SYNC
 FEATURE(pps_sync, "Support usage of external PPS signal by kernel PLL");
@@ -148,12 +170,18 @@ typedef int64_t l_fp;
 #define SHIFT_FLL	2		/* FLL loop gain (shift) */
 
 static int time_state = TIME_OK;	/* clock state */
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
 int time_status = STA_UNSYNC;	/* clock status bits */
 static long time_tai;			/* TAI offset (s) */
 static long time_monitor;		/* last time offset scaled (ns) */
 static long time_constant;		/* poll interval (shift) (s) */
 static long time_precision = 1;		/* clock precision (ns) */
 static long time_maxerror = MAXPHASE / 1000; /* maximum error (us) */
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
 long time_esterror = MAXPHASE / 1000; /* estimated error (us) */
 static long time_reftime;		/* uptime at last adjustment (s) */
 static l_fp time_offset;		/* time offset (ns) */
@@ -162,12 +190,24 @@ static l_fp time_adj;			/* tick adjust (ns/s) */
 
 static int64_t time_adjtime;		/* correction from adjtime(2) (usec) */
 
+#ifndef __rtems__
 static struct mtx ntp_lock;
 MTX_SYSINIT(ntp, &ntp_lock, "ntp", MTX_SPIN);
 
 #define	NTP_LOCK()		mtx_lock_spin(&ntp_lock)
 #define	NTP_UNLOCK()		mtx_unlock_spin(&ntp_lock)
 #define	NTP_ASSERT_LOCKED()	mtx_assert(&ntp_lock, MA_OWNED)
+#else /* __rtems__ */
+#define	NTP_LOCK()					\
+    do {						\
+        ISR_lock_Context lock_context;			\
+        _Timecounter_Acquire(&lock_context);
+#define	NTP_UNLOCK()					\
+        _Timecounter_Release(&lock_context);		\
+    } while (0)
+#define	NTP_ASSERT_LOCKED()				\
+    _Assert(_ISR_lock_Is_owner(&_Timecounter_Lock))
+#endif /* __rtems__ */
 
 #ifdef PPS_SYNC
 /*
@@ -273,6 +313,7 @@ ntp_gettime1(struct ntptimeval *ntvp)
  * See the timex.h header file for synopsis and API description.  Note that
  * the TAI offset is returned in the ntvtimeval.tai structure member.
  */
+#ifndef __rtems__
 #ifndef _SYS_SYSPROTO_H_
 struct ntp_gettime_args {
 	struct ntptimeval *ntvp;
@@ -293,7 +334,27 @@ sys_ntp_gettime(struct thread *td, struct ntp_gettime_args *uap)
 	td->td_retval[0] = ntv.time_state;
 	return (copyout(&ntv, uap->ntvp, sizeof(ntv)));
 }
+#else /* __rtems__ */
+int
+ntp_gettime(struct ntptimeval *ntv)
+{
+
+	if (ntv == NULL) {
+		errno = EFAULT;
+		return (-1);
+	}
+
+	ntv = memset(ntv, 0, sizeof(*ntv));
 
+	NTP_LOCK();
+	ntp_gettime1(ntv);
+	NTP_UNLOCK();
+
+	return (ntv->time_state);
+}
+#endif /* __rtems__ */
+
+#ifndef __rtems__
 static int
 ntp_sysctl(SYSCTL_HANDLER_ARGS)
 {
@@ -313,6 +374,7 @@ SYSCTL_NODE(_kern, OID_AUTO, ntp_pll, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
 SYSCTL_PROC(_kern_ntp_pll, OID_AUTO, gettime, CTLTYPE_OPAQUE | CTLFLAG_RD |
     CTLFLAG_MPSAFE, 0, sizeof(struct ntptimeval) , ntp_sysctl, "S,ntptimeval",
     "");
+#endif /* __rtems__ */
 
 #ifdef PPS_SYNC
 SYSCTL_INT(_kern_ntp_pll, OID_AUTO, pps_shiftmax, CTLFLAG_RW,
@@ -337,12 +399,19 @@ SYSCTL_S64(_kern_ntp_pll, OID_AUTO, time_freq, CTLFLAG_RD | CTLFLAG_MPSAFE,
  * the timex.constant structure member has a dual purpose to set the time
  * constant and to set the TAI offset.
  */
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
 int
 kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp)
 {
 	long freq;		/* frequency ns/s) */
 	int modes;		/* mode bits from structure */
+#ifndef __rtems__
 	int error, retval;
+#else /* __rtems__ */
+	int retval;
+#endif /* __rtems__ */
 
 	/*
 	 * Update selected clock variables - only the superuser can
@@ -354,11 +423,13 @@ kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp)
 	 * status words are reset to the initial values at boot.
 	 */
 	modes = ntv->modes;
+#ifndef __rtems__
 	error = 0;
 	if (modes)
 		error = priv_check(td, PRIV_NTP_ADJTIME);
 	if (error != 0)
 		return (error);
+#endif /* __rtems__ */
 	NTP_LOCK();
 	if (modes & MOD_MAXERROR)
 		time_maxerror = ntv->maxerror;
@@ -460,6 +531,16 @@ kern_ntp_adjtime(struct thread *td, struct timex *ntv, int *retvalp)
 	ntv->jitcnt = pps_jitcnt;
 	ntv->stbcnt = pps_stbcnt;
 #endif /* PPS_SYNC */
+#ifdef __rtems__
+	ntv->ppsfreq = 0;
+	ntv->jitter = 0;
+	ntv->shift = 0;
+	ntv->stabil = 0;
+	ntv->jitcnt = 0;
+	ntv->calcnt = 0;
+	ntv->errcnt = 0;
+	ntv->stbcnt = 0;
+#endif /* __rtems__ */
 	retval = ntp_is_time_error(time_status) ? TIME_ERROR : time_state;
 	NTP_UNLOCK();
 
@@ -473,6 +554,7 @@ struct ntp_adjtime_args {
 };
 #endif
 
+#ifndef __rtems__
 int
 sys_ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap)
 {
@@ -490,6 +572,23 @@ sys_ntp_adjtime(struct thread *td, struct ntp_adjtime_args *uap)
 	}
 	return (error);
 }
+#else /* __rtems__ */
+int
+ntp_adjtime(struct timex *ntv)
+{
+	int error;
+	int retval;
+
+	if (ntv == NULL) {
+		errno = EFAULT;
+		return (-1);
+	}
+
+	error = kern_ntp_adjtime(NULL, ntv, &retval);
+	_Assert_Unused_variable_equals(error, 0);
+	return (retval);
+}
+#endif /* __rtems__ */
 
 /*
  * second_overflow() - called after ntp_tick_adjust()
@@ -505,7 +604,11 @@ ntp_update_second(int64_t *adjustment, time_t *newsec)
 	int tickrate;
 	l_fp ftemp;		/* 32/64-bit temporary */
 
+#ifndef __rtems__
 	NTP_LOCK();
+#else /* __rtems__ */
+	NTP_ASSERT_LOCKED();
+#endif /* __rtems__ */
 
 	/*
 	 * On rollover of the second both the nanosecond and microsecond
@@ -628,9 +731,22 @@ ntp_update_second(int64_t *adjustment, time_t *newsec)
 		time_status &= ~STA_PPSSIGNAL;
 #endif /* PPS_SYNC */
 
+#ifndef __rtems__
 	NTP_UNLOCK();
+#endif /* __rtems__ */
+}
+#ifdef __rtems__
+static void
+_NTP_Initialize(void)
+{
+
+	_Timecounter_Set_NTP_update_second(ntp_update_second);
 }
 
+RTEMS_SYSINIT_ITEM(_NTP_Initialize, RTEMS_SYSINIT_DEVICE_DRIVERS,
+    RTEMS_SYSINIT_ORDER_FOURTH);
+#endif /* __rtems__ */
+
 /*
  * hardupdate() - local clock update
  *
@@ -930,6 +1046,7 @@ out:
 }
 #endif /* PPS_SYNC */
 
+#ifndef __rtems__
 #ifndef _SYS_SYSPROTO_H_
 struct adjtime_args {
 	struct timeval *delta;
@@ -958,15 +1075,23 @@ sys_adjtime(struct thread *td, struct adjtime_args *uap)
 
 int
 kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta)
+#else /* __rtems__ */
+static int
+kern_adjtime(const struct timeval *delta, struct timeval *olddelta)
+#endif /* __rtems__ */
 {
 	struct timeval atv;
 	int64_t ltr, ltw;
+#ifndef __rtems__
 	int error;
+#endif /* __rtems__ */
 
 	if (delta != NULL) {
+#ifndef __rtems__
 		error = priv_check(td, PRIV_ADJTIME);
 		if (error != 0)
 			return (error);
+#endif /* __rtems__ */
 		ltw = (int64_t)delta->tv_sec * 1000000 + delta->tv_usec;
 	}
 	NTP_LOCK();
@@ -985,7 +1110,19 @@ kern_adjtime(struct thread *td, struct timeval *delta, struct timeval *olddelta)
 	}
 	return (0);
 }
+#ifdef __rtems__
+int
+adjtime(const struct timeval *delta, struct timeval *olddelta)
+{
+	int error;
+
+	error = kern_adjtime(delta, olddelta);
+	_Assert_Unused_variable_equals(error, 0);
+	return (0);
+}
+#endif /* __rtems__ */
 
+#ifndef __rtems__
 static struct callout resettodr_callout;
 static int resettodr_period = 1800;
 
@@ -1051,3 +1188,4 @@ start_periodic_resettodr(void *arg __unused)
 
 SYSINIT(periodic_resettodr, SI_SUB_LAST, SI_ORDER_MIDDLE,
 	start_periodic_resettodr, NULL);
+#endif /* __rtems__ */
diff --git a/cpukit/score/src/kern_tc.c b/cpukit/score/src/kern_tc.c
index ea7d9ec953..a2b20a18b2 100644
--- a/cpukit/score/src/kern_tc.c
+++ b/cpukit/score/src/kern_tc.c
@@ -135,13 +135,13 @@ atomic_load_ptr(void *ptr)
 	return ((void *)_Atomic_Load_uintptr(ptr, ATOMIC_ORDER_RELAXED));
 }
 
-static Timecounter_NTP_update_second _Timecounter_NTP_update_second;
+static Timecounter_NTP_update_second _Timecounter_NTP_update_second_handler;
 
 void
 _Timecounter_Set_NTP_update_second(Timecounter_NTP_update_second handler)
 {
 
-	_Timecounter_NTP_update_second = handler;
+	_Timecounter_NTP_update_second_handler = handler;
 }
 
 #define	ntp_update_second(a, b) (*ntp_update_second_handler)(a, b)
@@ -1722,7 +1722,7 @@ _Timecounter_Windup(struct bintime *new_boottimebin,
 	bt = th->th_offset;
 	bintime_add(&bt, &th->th_boottime);
 #ifdef __rtems__
-	ntp_update_second_handler = _Timecounter_NTP_update_second;
+	ntp_update_second_handler = _Timecounter_NTP_update_second_handler;
 	if (ntp_update_second_handler != NULL) {
 #endif /* __rtems__ */
 	i = bt.sec - tho->th_microtime.tv_sec;
diff --git a/spec/build/cpukit/librtemscpu.yml b/spec/build/cpukit/librtemscpu.yml
index 7d6dbae0db..c224937348 100644
--- a/spec/build/cpukit/librtemscpu.yml
+++ b/spec/build/cpukit/librtemscpu.yml
@@ -983,7 +983,6 @@ source:
 - cpukit/libtrace/record/record-util.c
 - cpukit/libtrace/record/record.c
 - cpukit/posix/src/_execve.c
-- cpukit/posix/src/adjtime.c
 - cpukit/posix/src/aio_suspend.c
 - cpukit/posix/src/barrierattrdestroy.c
 - cpukit/posix/src/barrierattrgetpshared.c
@@ -1424,6 +1423,7 @@ source:
 - cpukit/score/src/isrisinprogress.c
 - cpukit/score/src/isrvectortable.c
 - cpukit/score/src/iterateoverthreads.c
+- cpukit/score/src/kern_ntptime.c
 - cpukit/score/src/kern_tc.c
 - cpukit/score/src/libatomic.c
 - cpukit/score/src/log2table.c
diff --git a/spec/build/testsuites/sptests/grp.yml b/spec/build/testsuites/sptests/grp.yml
index 740684a0e4..a69a4d20f7 100644
--- a/spec/build/testsuites/sptests/grp.yml
+++ b/spec/build/testsuites/sptests/grp.yml
@@ -337,6 +337,8 @@ links:
   uid: spmutex01
 - role: build-dependency
   uid: spnsext01
+- role: build-dependency
+  uid: spntp01
 - role: build-dependency
   uid: spobjgetnext
 - role: build-dependency
diff --git a/spec/build/testsuites/sptests/spntp01.yml b/spec/build/testsuites/sptests/spntp01.yml
new file mode 100644
index 0000000000..1b6a16f1a1
--- /dev/null
+++ b/spec/build/testsuites/sptests/spntp01.yml
@@ -0,0 +1,19 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+build-type: test-program
+cflags: []
+copyrights:
+- Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de)
+cppflags: []
+cxxflags: []
+enabled-by: true
+features: c cprogram
+includes: []
+ldflags: []
+links: []
+source:
+- testsuites/sptests/spntp01/init.c
+stlib: []
+target: testsuites/sptests/spntp01.exe
+type: build
+use-after: []
+use-before: []
diff --git a/testsuites/psxtests/psxtime/test.c b/testsuites/psxtests/psxtime/test.c
index d9f5537152..f5544b19dd 100644
--- a/testsuites/psxtests/psxtime/test.c
+++ b/testsuites/psxtests/psxtime/test.c
@@ -122,17 +122,15 @@ void test_adjtime(void)
   olddelta.tv_sec = 0;
   olddelta.tv_usec = 0;
 
-  puts( "adjtime - NULL delta - EINVAL" );
+  puts( "adjtime - NULL delta - OK" );
   sc = adjtime( NULL, &olddelta );
-  rtems_test_assert( sc == -1 );
-  rtems_test_assert( errno == EINVAL );
+  rtems_test_assert( sc == 0 );
 
-  puts( "adjtime - delta out of range - EINVAL" );
+  puts( "adjtime - large us delta - OK" );
   delta.tv_sec = 0;
   delta.tv_usec = 1000000000; /* 100 seconds worth */
   sc = adjtime( &delta, &olddelta );
-  rtems_test_assert( sc == -1 );
-  rtems_test_assert( errno == EINVAL );
+  rtems_test_assert( sc == 0 );
 
   puts( "adjtime - delta range of 0 - OK" );
   delta.tv_sec = 0;
diff --git a/testsuites/sptests/spntp01/init.c b/testsuites/sptests/spntp01/init.c
new file mode 100644
index 0000000000..eeee472e9d
--- /dev/null
+++ b/testsuites/sptests/spntp01/init.c
@@ -0,0 +1,111 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2022 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/time.h>
+#include <sys/timex.h>
+#include <errno.h>
+#include <string.h>
+
+#include <rtems/test.h>
+#include <rtems/test-info.h>
+
+const char rtems_test_name[] = "SPNTP 1";
+
+T_TEST_CASE( NTP )
+{
+  struct ntptimeval ntv;
+  struct timex tx;
+  int status;
+
+  errno = 0;
+  status = ntp_gettime( NULL );
+  T_eq_int( status, -1 );
+  T_eq_int( errno, EFAULT );
+
+  memset( &ntv, 0xff, sizeof( ntv ) );
+  status = ntp_gettime( &ntv );
+  T_eq_int( status, TIME_ERROR );
+
+  T_eq_i64( ntv.time.tv_sec, 567993600 );
+  T_eq_long( ntv.time.tv_nsec, 0 );
+  T_eq_long( ntv.maxerror, 500000 );
+  T_eq_long( ntv.esterror, 500000 );
+  T_eq_long( ntv.tai, 0 );
+  T_eq_long( ntv.time_state, TIME_ERROR );
+
+  errno = 0;
+  status = ntp_adjtime( NULL );
+  T_eq_int( status, -1 );
+  T_eq_int( errno, EFAULT );
+
+  memset( &tx, 0xff, sizeof( tx ) );
+  tx.modes = 0;
+  status = ntp_adjtime( &tx );
+  T_eq_int( status, TIME_ERROR );
+  T_eq_uint( tx.modes, 0 );
+  T_eq_long( tx.offset, 0 );
+  T_eq_long( tx.freq, 0 );
+  T_eq_long( tx.maxerror, 500000 );
+  T_eq_long( tx.esterror, 500000 );
+  T_eq_int( tx.status, STA_UNSYNC );
+  T_eq_long( tx.constant, 0 );
+  T_eq_long( tx.precision, 0 );
+  T_eq_long( tx.tolerance, 32500000 );
+  T_eq_long( tx.ppsfreq, 0 );
+  T_eq_long( tx.jitter, 0 );
+  T_eq_int( tx.shift, 0 );
+  T_eq_long( tx.stabil, 0 );
+  T_eq_long( tx.jitcnt, 0 );
+  T_eq_long( tx.calcnt, 0 );
+  T_eq_long( tx.errcnt, 0 );
+  T_eq_long( tx.stbcnt, 0 );
+
+  status = adjtime( NULL,  NULL );
+  T_eq_int( status, 0 );
+}
+
+static rtems_task Init( rtems_task_argument argument )
+{
+  rtems_test_run( argument, TEST_STATE );
+}
+
+#define CONFIGURE_APPLICATION_NEEDS_SIMPLE_CONSOLE_DRIVER
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
-- 
2.26.2



More information about the devel mailing list