(x) ok in MAC
( ) ok in linux
--- TOTimer --- A single-threaded timer feature set
### content
- general infos
- release information
- simple TOTimer usage info
- overall-basics
- toticker01
- testing
-/-
### general infos
The code is in programming language C !
(Folders inc/ & src/, synonym for C feature: TOTimer
,totickerXX.c files in src/ are JUST examples and MUST be replaced by your own toticker C-file
in your own projects with TOTimer {mayB it helps in the first steps in linux}
)
At first no "Additional Support" for other programming languages.
Hint: In programming language CPP you had multiple options. One - many
programmers should say a good - possibility to use timers is in using a part
of the boost libraries; boost asio. As far as i known it is - of course -
another technique; you start timers and asynchron actions and call a
run-function which is then blocking; not like TOTimer which is a polling
feature.
Conventions in reading this readme and comments and so on:
- if writing about a 'user' I do mean usually the software which uses this
feature; a function of the software which uses totimer_setAstartTimer()
for instance.
-/-
For function-overview see readme-section in totimer.c.
TOTimer in main is to create timers in a single-thread environment
( hence: i.e. _without_ using locks like a mutex or a semaphore; this could
be an advantage - makes something easier to handle, some other parts more
difficult. Adv.: When you had to handle multiple tasks in a single-threaded
environment you may have a look at my tiny-lib 'taskKS'
).
The timers could run out-of-time (->timeout) and this could be detected by
polling a/o a user-specific callback-function which is called in case of the
timeout-expiration.
It is needed to serve this feature by a periodically called TOTimer task
function (the run-function) and an independent TOTimer tick feature (a ticker
example for linux/POSIX is included, e.g. toticker03, for tests).
For inhere given C-tests the sub-folders inc/, src/ and test/ are valid,
"make maintest" for instance and
run tests with "./maintest <test-number>". (In folder ..TOTimer/code/ of course).
An additional argument [help] behind the test-number may gave information,
currently NYI -or- in german only (may someone want to translate..?).
test-~number~ 't' for temporary tests. NYI
In V 0.1.1 -> maintest just serves test number 1.
{aside that maintest could be enhanced from time to time it is now -v0.1.0-
not very much tested}.
In this version one working (?) simple-test is included via
C-file "simpletest01.c".
> make stestXX -> create a dedicated simple test (XX==01,02,...)
Hence with
> make stest01
you now could build stest01 which could be started as usual with
> ./stest01
. See what happens.
Other simple test NY-fulfilled (V0.1.0).
See release notes for further tests in newer versions.
For using in a virtual-machine, timing is more inaccurate.
Hence make test with VIRBO enviromentvariable to use a tick-time of 40ms:
--one-time--
> VIRBO=1 make maintest
--multiple-times--
> export VIRBO=1 {this set is just needed one-time}
> make maintest
///
Folder test/ do not contain files which are necessary to use TOTimer
feature in your own code.
You have to write a specific totickerYY.c, to support your hardware and enable
this file in totimer-config.mi (or use your own makefile).
For first versions toticker01.c or toticker03.c may be sufficient, ticker04 is
for Mac ok, ticker05 for linux. No example ticker yet included for windows.
### release information
* current version - 0.1.2
* version 0.1.0
Add 1st release of TOTimer to test, ALPHA version(!), not fully
qualified tested
!!!
Pls. deliver info of issues with this version if you will use it.
address: chekrad (AT) freenet (DOT) de
* version 0.1.0+x-27may17
Chg readme file (this file) -> interims readme to give more info
about feature and tests
NO tar.gz
* version 0.1.1
Chg totimer
- make timer-entry-structure local (stTOTimerEntry -> totimer.c,stTmrEntry)
- Handling of secondary timers via macros (timers with same timeout as a timer before)
(This and others will fix some issues)
maintest
- support various base-timer-tick values. e.g. depending on use in Virtual-Machine
(use 40ms tick)
- add ticker-check before real tests (yet: only test01)
- add some new tests in test01, e.g. example 3 with using TestRobo feature
Make
- choose the test-ticker e.g. via OS and more (totimer-cfg.mi)
Add Detect OS for test-functions (makeosdefs.mi).
Insert a new timerrobo feature for automatic testing commands in an array.
Add new test-ticker C-files *04(more delay-calls for more precision)
& *05(Linux: SIGUSR1+CLOCK_MONOTONIC).
More documentation (may be only in DE,sry).
Debug function to show current timer-Q.
Support of Virtual-Machine settings prepared (Env.variable: VIRBO=1).
* version 0.1.2
Add test02: a maintest feature (No.2) to start different timers in parallel
with different timeout callback functions in which these timers are
restarted or stoped. For this GCDebRTrc feature is used to trace the
real times.
With this an testprogram is added to show the timeout differences
from should-be to real (name = 'checkT02RTrc'; under new folder
code/anatestsrc/).
-
Fix Allow starting and stopping of timers in a timer timout-callback
function now. (in previous versions not really supported and working)
-
Chg The other features Lnkdlst (for TOTimer itself and tests) and
GCDebRTrc (only for tests) are used as externals in makefile now; basic
folder were TOTimer/ is located has to be the folder were Lnkdlst/ and
GCDebRTrc/ should be located too.
Could be switched to internal by makefile setting (copy Lnkdlst &
GCDebRTrc inc&src files into the test/ sub folder of TOTimer).
HINT: In folder "Ablage/" you'll find some try-versions of both. If
you do not like to load these features too, it should be
possible to take this code.
Todo in this case:
- copy files from the folders code/inc and code/src of the
zip files into the TOTimer/code/test folder
- change in makefile the EXTERN values to NO
(e.g. EXTERN_LNKDLST_WANTED = NO)
--
-
Chg Use only one h-file "totimer.h" to include both for totimer & toticker.
Some definitions are now part of totimer.h. The TOTicker interface API
is still in toticker.h.
-
Impl TOTIMER_CDEF_AUTOINIT: type 1 for newer Lnkdlst. This makes init of
OAList feature of Lnkdlst implicite in init of TOTimer. No more an extra
init-call before the TOTimer init call necessary (previous version
with additional, exclusive precall of OAList in is supported
furthermore by type 0).
-
Chg Rename some function and macro names due to better understanding
(hopefully). Old names furthermore valid, if definition
'TOTIMER_DEPRECATED_' is defined. See totimer.h for the list of the
renamed functions etc..
-
Add Include TOTIMER_VERSION and other version definitions to get an info
of the TOTimer version in the SW.
-
Chg Rename some type and macro names to have always the prefix 'TOTimer_'
(or TOTIMER_. Old availaible via def. TOTIMER_DEPRECATED_).
-
Add Include newer 'SUCCESS' macros for some functions due to the fact that
not only value 0 is for successful execution (some more info in
the other !0 success return-codes which may be of interest; it's the
type of : when does stopping occur and has a timeout already happen
before).
Belonging functions:
- totimer_unsetTimer (prior function with name totimer_unsetTimeout)
- totimer_stopTimer (new function , specialiced unsetTimer function)
- totimer_deleteTimer (prior function with name totimer_deleteTimeout)
-/-
-
Impl New functions:
-
- totimer_getp2UserData(): UserData via totimer_initialize() {arg3
with a value >0) now supported and this function returns the
ptr to the mem of the user-data (TOTimer SW user) of this
timer.
Hint: any TOTimer timer has always included some specific, only-for-
Timer-user accessed variables named Arg1 & Arg2 for this. May be
these variables are sufficient for user-specific needs and additional
user-data mem is not additionally needed. Also new in version 0.1.2
that these variables are settable and getable (see below).
-
- totimer_changeTimeoutCallbackArg(): When using a timeout callback
function, the argument could be changed via this function.
Hint: the callback-function itself could be changed by using
the totimer_setAstartTimer() function with a specific mode bit set.
-
- totimer_getNextBusyTimerHandle(): specific function for insiders
of TOTimer only (could make a walk through over all existing
timer CBs, the busy elements of the OAList01).
-
- totimer_deinitialize(): stop the work of TOTimer and free all
memory; not fully supported yet (~~ under construction although
mostly done).
-
- totimer_setTimerArg1(): setup the specific timer value Arg1,
an free usable unsigned long variable.
-
- totimer_getTimerArg1(): get the specific timer value Arg1.
-
- totimer_setTimerArg2(): setup the specific timer value Arg2,
an free usable void* variable.
-
- totimer_getTimerArg2(): get the specific timer value Arg2.
(have a look in test02.c for example)
-/-
-
Impl A feature to -optionally- reduce Run-function calling
(via define TOTIMER_TICKERGETSFULLTICKTS_, pre-alpha state).
-
Chg uwsutil.h: Use newer file to have a better type naming
(e.g. UINT1 -> UINT_1) which do not have an collision issue with
VS / MS compiler integral typenames.
(VS: UINT8 means unsigned integer variable with a size of 8bit.
uwsutil: UINT_8 means 8byte; of course using standard names and
inclusion of 'inttypes.h' is a better way and in newer compiler
versions always available. e.g. UINT_8|uws === uint64_t|standard C/CPP
)
hint: use official standard fix-type-size integer types like uint64_t;
they are also supported by uwsutil.h. Use uwsutil.h specific only if
in need that official standard fix-type-size integer types not
available.
-
Impl make: add BUILD_TYPE and OS-specific sub-make file.
Also allow external Lnkdlst and GCDebRTrc software source as mentioned
before.
-
Add A new toticker totickerEvU.c: This ticker seems toB primary ok for
linux and depends on a max. jitter / delay testing before,
For this the extra test "test_tickerEvU" is supported.
-
Impl As far as possible, TOTimer uses auto-init of OAList feature
of Lnkdlst as far as possible (Lnkdlst version must be a newer one).
(init with caller-name; with this the OAList feature could be
initialized by various user-SW without double-init and deinit issue
{TOTIMER_CDEF_AUTOINIT = 1; if wanting older way, outside init of
OALIST, use setting 0 - shouldB deprecated}
)
-
Add totimer.c supports, per default, time-get-function(s). (Not for
OS Windows).
totimer_getCurrentTimeInUS(), and - if needed -
totimer_getCurrentTimeInNS().
-
Add support CPP (CINCPP_OPEN,_CLOSE - a conditional extern "C" block)
-.-.-
### simple TOTimer usage info
-- TOTimer system setup --
A. Initialize TOTimer with a callOf
> Lnkdlst_OAInitialize() {autoinit of this feature in
TOTimer version >= 0.1.2},
> totimer_initialize() and
- to start function -
> totimer_initTicker().
B. Instanciate a forever loop with one permanently called task,
the run-function:
> TOTIMER_CONDCALLTASK();
Period of calling should be less-or-equal then a quater of the tick-time
(less makes usually a more precise timeout). This polling mechanismn
could be done better in system like linux to save CPU-time, but for now
not implemented in TOTimer yet (0.1.2).
-
Attention: This task is -> the-thread of the TOTimer; TOTimer is still
a single threaded feature. If other premptive thread are used within
TOTimer you had to take care by yourself, i.e. in using wrapper
functions with mutex or using another control method (...)!
-- TOTimer timer usage --
C. pre-Initiate timer-hdl one-time with
> TOTIMER_INIT_HANDLE(th)
{a uninitialized handle-variable - typeOf TOTimer_tHandle - must
exist before of course; just a pre-init - no timer-CB allocated
}
or
> TOTIMER_CREATE_TIMER(th)
{a uninitialized handle-variable as input-arg. this allocates the
timer-CB already, hence not done in totimer_setAstartTimer() again if
this call is done instead of the TOTIMER_INIT_HANDLE macro call;
see macro definition in h-file.
}
Thes macros should be just used one-time per timer-handle variable!
D. Create&Start timer with
> totimer_setAstartTimer(&th).
If this is called again, there is no new create done (usually).
It automatically stopps the timer if already exist and in
running state, before starting it (auto-re-start-feature).
A set of the callback args is only done when timer is created or
when mode.bit0 is set.
or
using
> totimer_startTimer(th).
BUT: for this use TOTIMER_CREATE_TIMER() or the totimer_setAstartTimer()
function before to set the callback args.
After this 1st set, the callback args are valid and this timer will use
it when timeouts occur either if stops,starts will happen (no specialized
start of course).
E. When using with a callback function (in callOf D function):
if timeout expires the callback function is called one time
{arg in the totimer_setAstartTimer() function to set the user specific
function function
}
F. When using without callback function (in callOf D function):
timeout expiration must be checked via function
> totimer_isTimeout(th)
This could be done in case E either of course.
Hint: Must be done in the same thread like the run-function (B) is
called <-> single threaded.
G. If the timeout is no longer used [before expiration], it shouldB
switched off via function
> totimer_unsetTimer(th)
or
> totimer_stopTimer(th)
or
> totimer_deleteTimer(&th).
While 1st & 2nd function stopps the timeout only, the 3rd function
(delete) does also clear the timer-hdl
(this function uses a p2 the hdl cs. it willB set to No-Timer-Hdl
value <-> this will force the D function to create the timer
automatically afterwards if the same variable is used for
the timer-hdl!
)
Recommendation:
If a specific timer is not often used, it is best to use the
totimer_setAstartTimer() and the totimer_deleteTimer() function;
this frees the block and other software-part could use it. If it is
often used, then only use the totimer_stopTimer() /
totimer_unsetTimer() function (Timer-mem is still reserved for fast
restarting..).
-.-
### overall-basics
* ovaB01
It is completly assumed - for at least the single threaded
totimer function - that a read and a write process of the
timer-tick counter variables are fully
--> ATOMIC <--.
Means: No interrupt or anything else will disturb (devide) the
complete assembler read or write operation - the (usually 32bit)
value of the tick-function counter is always read or write in one
uninterruptable assembler statement.
-
If this could not be guranteed, the totimer DOES NOT WORK
fully properly.
e.g. some interrupt disable/enable has to block the read/write
operations of the counters
(encapsulate .uFreeRunningTickCtr & .uEqualizeCtr access).
Or a mutex has to be used
or anything else, which makes this timer usually
not-the-best-working-timer-because-of-always-per-tick-needed-additional-delays.
(linux: atomic type)
-
Hence be sure that ovaB01 is true.
If not true, it is recommended to use another timeout-timer (lib), not this
feature (toTimer).
-
{hint: on smaller systems, which has a atomic 16bit access true,
it may work to reduce the type of the counters.
although it is assumed that 'unsigned' on such OS/arch
is already 16bit, and hence -> usually nothing has to be done
in toTimer-feature.
}
* ovaB02
The base toTimer system based on the fact that no mutex/semaphore
has to be used. (may be multi threading opt. compilable in future)
Just two counters exist:
- one (freerunningC) will be incremented in the independent
timer-tick context
- the other (equalizeC) will be incremented in the ~~ non RT
context
- the only linkage is a compare-and-
increment-of-equalizeC in a toTimer service function (in a
single threaded environment it has to be called periodically,
but not with much RT binding).
->
with the ovaB01 we had no need to use semaphores or mutexes
within this implementation at all.
-
This is just for the single-threaded config.
May be in future it will be enhanced to use it fully
multi-threaded {alternatively compilation, of course}.
* ovaB03:
The system has no multiinstance feature.
Just one toTimer feature per process/program/app possible! <-> should be smart enough for
all subsystems, may be optimization is todo for high performance / large system..
(till now upto 1000 timers seems possible in non-fast systems, upto 50 in fast systems)
* ovaB04:
The TOTimer system uses implicitly other features of mine:
- Lnkdlst in C (now: V0.3.1)
- traceam (header file only, controlled via global def USE_DCLTRC
and std. debug defines
TODO: make command to filter DC functions and make a traceam clean
TOTimer C-file.
- uwsutil just to have CINCPP_* macros which makes it a little easier to combine TOTimer in
a CPP environemnt.
-/-
They are automatically included in the TOTimer package (just the C file
set of Lnkdlst: lnkdlst.c & lnkdlst.h)
Could be substituted, oc. Then happy work..
### toticker01
the aim of this file is to call the totimer tick function every x microseconds.
01 means a special method (number 1) to do this.
01 stands for source-of-timer-tick-call-is-a-highPrio-pthread.
Other types (02,03,..) may be included in future for other Systems
(HW,SW), e.g by using a periodically called timer-ISR.
type 01 is not really best if a linux is used without the
fully RT-patch(...).
Interfacing of the totickerXX.c files to toTimer is always the same:
"toticker.h".
(Just compile the specific toticker file via using a makefile-set
in totimer-cfg.mi
).
-
Test mistyrios behavior:
using OS ubuntu (Mate 16.04) a phenomen could be
observed.
try using pthread with a high priority as the source of the
tick-caller, the loop-system has a delay
(loop-system: begin-loop - wait - call tick-function - end-loop)
which based on unknown issues but also on known issue that
the wait x microseconds do not include the other parts of
the loop (call tick-function, end-loop jump to begin-loop ..(?)).
-
hence a general minus-delay has been included
(arg2 of function totimer_initTicker()), which should reduce
tick-time failure.
It's got experimental.
-
If the value is fine - nothing else working on the system than
eclipse and compile-console - i found some issue that is not
fully clear for me.
-
if starting another console and starting some work, e.g.
>> while true; do ls -l tmp; done
<<
which makes the system more busy (afai expect),
the tick precision would be better than before.
-
Hence if a choose a tick-value in low busy state which makes
the tick-ctr nearly a little under the expected full-exact value
{ e.g. if choosing a tick-time of 1000
which means 1millisecond tick
i like to had 10000 or less ticks at ten seconds.
Less: because any timeout should not expire before the
real time is over, but a little after is ok (tolerance
time x .. (x+PlusTime), not less than x - the value
where the timer is started with
},
i found that the tick-ctr is higher if the system has more
to do - like with the while loop in the second console.
-
Hence: founding a good minus-delay has to be done under
heavy-load of the system and should not be too
wrong under no-load.
But: afaiu the jitter is a litte high in non RT-linux
(linux without complete RT-patch of OSADL), and
could be just better if choosing another OS
a/o choosing another toticker function (e.g. a
timer interrupt function).
--/--
### testing
gen-info:
> xyz -> this means, enter xyz in a command-line window. short: in a CLI
which stands for Command-Line-Interface (a type of a
Computer user-interface,UI).
e.g. "> ./maintest 1".
CLI will also be used in short for the CLI window/screen.
Could be directly started (ubuntu for instance by holding keys
<Alt> + <Ctrl>, than press <T> {for Terminal}. more ways possible,
e.g. remote via ssh).
This is now only described for linux/POSIX systems. There is no
integration and test done for windows, sry. May be only a ticker
is needed, but the tests based on linux systems.
Test-Execution may take a lot of time; be patient. Although, if
output is not redirected, the time to display a new line or show
some changes in the CLI should not be more than 2 minutes.
-
<-> blabla
-> this means, blabla is the expected result of the test before.
"ok" means, the command returns with 0 exit code (
in linux checkable by entering > echo $? <; in windows
by entering > echo %ERRORLEVEL% <).
-
i: -> this means, behind i: is only some additional info which may
help in understanding.
-
preset -> before testing at all use
> make clean
<. Just before starting the tests do this.
Hint: -> you could insert "BUILD_TYPE=RELEASE" before any make, which
disables all debug-code.
+C+ -> this means, after this a prepare condition has to be done before
using the next command.. (or checked. obviously it may fail if
this is not correct)
--
1.
> make clean
<-> ok
> make maintest
<-> ok (== errorcode 0; linux: >echo $? <-> CLI output is "0")
> ./maintest 1
i: execute > ./maintest 1 help <-> to get an idea about the test
maintest No. 1.
Details in german language (DE) now only.
(for other tests change number)
<-> ok
> ./maintest 2
<-> ok
<-> GCDebRTrc i.e. RAM-trace output appears at the CLI (e.g. >>
...
///// End of Test 02
(RAM-trace follows)
|00020698#00809|##RT##-920101-- V1= 7530
...
<<
--
2.
> ./maintest 2 >t
i: the output of maintest-2 is redirected into file with name "t"; hence
it is not much seen during test-execution in the CLI.
<-> ok
> make checkT02RTrc
<-> ok
> ./checkT02RTrc t
<-> ok
<-> the output should display an accuracy info of the current ticker,
depending on the current "time-tick" - of course.
Per system, the accuracy could not be much better than 1 time-tick, at
least it should be better than 2 time-ticks.
i: The tick-time is displayed in the start output in the CLI for
maintest command execution.
i: The timeout is much depending on the tick-time:
real-timeout-time/Max = (timeout-time / tick-time) * tick-time
+ 2 * tick-time
+ RUN-macro-loop-time + jitter-time (0..)
Belongs to integer devision.
Examples for real-timeout-time/Max (assumed that
RUN-macro-loop-time and jitter-time are both zero):
time-tick = 2ms
case a: timeout = 1ms -> max.tmo-time =
(1/2)*2 + 4 -> 0+4 = 4ms
case b: timeout = 41ms -> max.tmo-time =
(41/2)*2 + 4 -> 40+4 = 44ms
--
3.
> make stest01
<-> ok
> ./stest01
i: this is just a user reaction test, try to press <Enter> or <Return>
as fast as you can after you see a new output ">>> GO .."
in the CLI. The time before the next >>>GO appears is a random time,
and pre-key-press is not sufficient.
My best times are 240ms.
<-> if you like press multiple times <Enter>. 1st press starts reaction
test and second should be done in time after the ">>> GO" appears,
to go to next test. On time out the test ends.
i: one sequence is
1st Enter -> start one reaction test,
2nd Enter -> reaction, after ">>> GO" is displayed.
The max. allowed reaction time is reduced for each new test.
Second Enter should be done in time after the ">>> GO" appears,
to go to next test. On time out the ~test~ ends.
--
4.
> make stest03
<-> ok
+C+ the CLI window width must be set to a size of 130 characters
> ./stest03
<-> ok
i: simple output of 2 moving "blocks", one with static speed, one with
accelerated.
--
5.
> make test_tickerEvU
<-> ok
> ./test_tickerEvU
<-> ok
i: a jitter test for tickerEvU.c
--
-.-