This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: posix time functions


Here is my first attempt at a patch for this. I would have preferred putting the offset inside the Cyg_Clock class or the Cyg_RealTimeClock class, that way any "implementation" of gettime/settime could use that. However, I assumed you would not want the baggage in Cyg_Clock (even if it is CDL'able, it would end up in every instantiation of Cyg_Clock when configured enabled.) And there doesn't appear to be a "public" interface to the Cyg_RealTimeClock class that posix could call.

I was also wavering if the new term needed to be protected by a semaphore. I decided against it. (Due to the fact that an invalid gettime would have relatively low risk of creating problems combined with relative number of times that the time will be set within an application.) However, if you feel it is necessary, I will add one.

Once this patch gets finalized, the same thing should be done to the uitron interface. I'd be willing to post the code, but I haven't go the slightest idea how to test it.

Are there any other interfaces that can set/get the clock as "calendar time"? I could not find any.

David Brennan

Patch below:
Nick Garnett wrote:

David Brennan <eCos@brennanhome.com> writes:



We discovered a (perhaps) un-documented feature in the eCos posix
clock_settime and clock_gettime functions. Setting the time, changes
the system clock (number of ticks). The system clock should only be
changeable by the interrupt routine which is incrementing it. All
other code should really only have read access.



Hmm, we have also had complaints that clock_settime() doesn't change enough and want it to alter the wallclock time as well. I guess you cannot please everyone.



Is there a chance this
could be changed? That is, if we fix it in the kernel, would that type
of patch be accepted.



A patch that maintains an offet for CLOCK_REALTIME from the main timer and used that when calculating timer timeouts would be fine. Depending on how much gets changed, we might need an assignment for it, though.



I would think that setting the clock and
possibly losing alarms would be something that other people have
noticed before.



To be honest, I don't think that many people call clock_settime(). It's mainly there for completeness.



Index: compat/posix/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/compat/posix/current/ChangeLog,v
retrieving revision 1.48
diff -u -5 -w -r1.48 ChangeLog
--- compat/posix/current/ChangeLog    4 Oct 2004 11:49:19 -0000    1.48
+++ compat/posix/current/ChangeLog    22 Oct 2004 04:02:19 -0000
@@ -1,5 +1,12 @@
+2004-10-01  David Brennan  <eCos@brennanhome.com>
+
+    * cdl/posix.cdl:
+    * tests/timecheck.cxx:
+    * src/time.cxx:  Add capability to keep the real-time clock's ticks
+    monotonically increasing even through clock_settime.
+
2004-10-01  Oyvind Harboe  <oyvind.harboe@zylin.com>

    * src/signal.cxx:  place the CYGBLD_ATTRIB_INIT_PRI such that it
    compiles for gcc 3.4.2 which is more picky about its placement.

Index: compat/posix/current/cdl/posix.cdl
===================================================================
RCS file: /cvs/ecos/ecos/packages/compat/posix/current/cdl/posix.cdl,v
retrieving revision 1.11
diff -u -5 -w -r1.11 posix.cdl
--- compat/posix/current/cdl/posix.cdl    24 Feb 2003 14:08:21 -0000    1.11
+++ compat/posix/current/cdl/posix.cdl    22 Oct 2004 04:02:19 -0000
@@ -150,10 +150,20 @@
        compile          time.cxx
    description      "This component provides configuration controls for
                      the POSIX clocks."
    }

+    cdl_option CYGCFG_POSIX_USE_RELATIVE_REALTIME {
+        display          "Keep real-time clock as relative time"
+        flavor           bool
+        default_value    0
+        description      "
+            This option ensures that the real-time clock will not go
+            backwards if using clock_settime to change the time. Using
+            other access functions can still cause the clock to change."
+    }
+
    # ----------------------------------------------------------------
    # Timers component

cdl_option CYGPKG_POSIX_TIMERS {
display "POSIX timers"
@@ -302,10 +312,11 @@
flavor data
no_define
calculated {
"tests/pthread1 tests/pthread2 tests/pthread3 tests/mutex3 tests/mqueue2"
. ((CYGPKG_POSIX_SIGNALS) ? " tests/mqueue1 tests/signal1 tests/signal2 tests/signal3 tests/sigsetjmp tests/timer1 tests/tm_basic" : "")
+ . ((CYGCFG_POSIX_USE_RELATIVE_REALTIME) ? " tests/timecheck" : "")
}
description "
This option specifies the set of tests for the POSIX package."
}


Index: compat/posix/current/src/time.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/compat/posix/current/src/time.cxx,v
retrieving revision 1.9
diff -u -5 -w -r1.9 time.cxx
--- compat/posix/current/src/time.cxx    31 Jan 2003 11:53:14 -0000    1.9
+++ compat/posix/current/src/time.cxx    22 Oct 2004 04:02:20 -0000
@@ -127,10 +127,13 @@
#define TIMER_ID_COOKIE_MASK (TIMER_ID_COOKIE_INC-1)
static timer_t timer_id_cookie = TIMER_ID_COOKIE_INC;

#endif // ifdef CYGPKG_POSIX_TIMERS

+#ifdef CYGCFG_POSIX_USE_RELATIVE_REALTIME
+static cyg_tick_count real_time_offset = 0;
+#endif
//-----------------------------------------------------------------------------
// new operator to allow us to invoke the constructor on
// posix_timer.alarm_obj.

inline void *operator new(size_t size, cyg_uint8 *ptr) { return (void *)ptr; };
@@ -327,11 +330,15 @@
if( !valid_timespec( tp ) )
TIME_RETURN(EINVAL);
cyg_tick_count ticks = cyg_timespec_to_ticks( tp );


+#ifdef CYGCFG_POSIX_USE_RELATIVE_REALTIME
+ real_time_offset = ticks - Cyg_Clock::real_time_clock->current_value();
+#else
Cyg_Clock::real_time_clock->set_value( ticks );
+#endif
TIME_RETURN(0);
}


//-----------------------------------------------------------------------------
@@ -347,10 +354,14 @@
if( tp == NULL )
TIME_RETURN(EINVAL);
cyg_tick_count ticks = Cyg_Clock::real_time_clock->current_value();


+#ifdef CYGCFG_POSIX_USE_RELATIVE_REALTIME
+    ticks += real_time_offset;
+#endif
+
    cyg_ticks_to_timespec( ticks, tp );

TIME_RETURN(0);
}
--- /dev/null 2004-10-21 21:04:44.477000000 -0700
+++ compat/posix/current/tests/timecheck.cxx 2004-10-21 17:51:20.500094400 -0700
@@ -0,0 +1,177 @@
+//==========================================================================
+//
+// timecheck.cxx
+//
+// Check that setting the time of day acts appropriately
+//
+//==========================================================================
+//####ECOSGPLCOPYRIGHTBEGIN####
+// -------------------------------------------
+// This file is part of eCos, the Embedded Configurable Operating System.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2003 Gary Thomas
+//
+// eCos is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 or (at your option) any later version.
+//
+// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+//
+// You should have received a copy of the GNU General Public License along
+// with eCos; if not, write to the Free Software Foundation, Inc.,
+// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+//
+// As a special exception, if other files instantiate templates or use macros
+// or inline functions from this file, or you compile this file and link it
+// with other works to produce a work based on this file, this file does not
+// by itself cause the resulting work to be covered by the GNU General Public
+// License. However the source code for this file must still be made available
+// in accordance with section (3) of the GNU General Public License.
+//
+// This exception does not invalidate any other reasons why a work based on
+// this file might be covered by the GNU General Public License.
+//
+// -------------------------------------------
+//####ECOSGPLCOPYRIGHTEND####
+//==========================================================================
+//#####DESCRIPTIONBEGIN####
+//
+// Author(s): dmb
+// Contributors: dmb
+// Date: 2004-10-20
+// Description: Tests the Kernel Real Time Clock for correct operation
+// while altering the time of day. Basically the test sets
+// an alarm to go off 1 second in the future. Then the clock is
+// set backwards by 9 seconds. The alarm should still go off in
+// 1 second, giving an apparent delta time of -8 seconds. If the
+// alarm fires in 10 seconds, then the clock_settime function
+// messed with the real time clock. The behavior is controllable
+// with the CYGCFG_POSIX_USE_RELATIVE_REALTIME. This test will
+// fail with the option turned off, (but will not be built).
+//
+//####DESCRIPTIONEND####
+
+
+#include <pkgconf/kernel.h>
+
+#include <time.h>
+
+#include <cyg/infra/testcase.h>
+
+#include <cyg/kernel/clock.hxx>
+#include <cyg/kernel/clock.inl>
+#include <cyg/kernel/kapi.h>
+#include <cyg/kernel/sema.hxx>
+#include <cyg/kernel/thread.hxx>
+#include <cyg/kernel/thread.inl>
+#include <cyg/infra/diag.h>
+
+#define ENDPOINT 10
+
+static cyg_alarm_fn alarmfunc;
+static void alarmfunc( Cyg_Alarm *alarm, CYG_ADDRWORD data )
+{
+ Cyg_Binary_Semaphore *sp = (Cyg_Binary_Semaphore *)data;
+ sp->post();
+}
+
+
+static void entry0( CYG_ADDRWORD data )
+{
+ int i;
+ timespec last_time;
+ timespec this_time;
+ tm my_tm;
+ time_t my_timet;
+
+
+ // Set the time of day to something reasonable
+ my_tm.tm_sec = 0;
+ my_tm.tm_min = 0;
+ my_tm.tm_hour = 8;
+ my_tm.tm_mday = 20;
+ my_tm.tm_mon = 9;
+ my_tm.tm_year = 104;
+ + this_time.tv_sec = mktime( &my_tm );
+ this_time.tv_nsec = 0;
+ + clock_settime(CLOCK_REALTIME, &this_time);
+
+ // Set up variables for the alarm
+ Cyg_Clock *rtc = Cyg_Clock::real_time_clock;
+
+ Cyg_Binary_Semaphore sema;
+
+ Cyg_Alarm alarm( rtc, &alarmfunc, (CYG_ADDRWORD)&sema );
+
+ alarm.initialize( rtc->current_value() + 100, 100 );
+ alarm.enable();
+
+ // Get the current time of day
+ clock_gettime(CLOCK_REALTIME, &last_time);
+ + for ( i = 0; i < ENDPOINT; i++ ) {
+ // Set the time of day backwards by 9 seconds
+ this_time.tv_sec = last_time.tv_sec - 9;
+ this_time.tv_nsec = last_time.tv_nsec;
+ clock_settime(CLOCK_REALTIME, &this_time);
+
+ sema.wait();
+ // Get the current time of day
+ clock_gettime(CLOCK_REALTIME, &this_time);
+ + // Verify it is less than the previous time of day
+ CYG_TEST_CHECK(difftime(this_time.tv_sec,last_time.tv_sec) < 0.0,
+ "When the time was set backwards, the real-time "
+ "went backwards too.");
+
+ // Save the last time that we got
+ last_time = this_time;
+ + // print the current time of day
+ my_timet = this_time.tv_sec;
+ localtime_r( &my_timet, &my_tm );
+ + diag_printf( "INFO<current time %s -- RTC Low is %8d>\n",
+ asctime(&my_tm), rtc->current_value_lo() );
+ }
+
+ CYG_TEST_PASS_FINISH("Clock set check OK");
+}
+
+static char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
+static cyg_handle_t thread_handle;
+static cyg_thread thread;
+
+
+void clocktruth_main( void )
+{
+ CYG_TEST_INIT();
+ cyg_thread_create(3, // Priority - just a number
+ entry0, // entry
+ 0, // index
+ 0, // no name
+ &stack[0], // Stack
+ sizeof(stack), // Size
+ &thread_handle, // Handle
+ &thread // Thread data structure
+ );
+ cyg_thread_resume(thread_handle);
+
+ Cyg_Scheduler::start();
+}
+
+externC void
+cyg_start( void )
+{
+#ifdef CYGSEM_HAL_STOP_CONSTRUCTORS_ON_FLAG
+ cyg_hal_invoke_constructors();
+#endif
+ clocktruth_main();
+}
+
+// EOF timecheck.cxx



-- Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]