Know your timer’s type

New 27Feb2012, moved from 041 4Sept2015. Updated 24Sept2018

This page is in group Technology and is a note showing how you might implement a timer system better with correct typing. It assumes that you’re a systems programmer and understands that the system timer is the fastest you get at this level, since it’s incremented on every system timer/clock tick (on a naked processor’s HW timer or piggy backed on an operating system’s timer system) – not possible to set or clear by the application. However, individual timeouts ordered by the application program, threads or tasks are intimately related to the system timer, implying that clocks and calendars are on top of this. This note suggests signed values that wrap between «AM» and «PM» (positive to negative and round again). This is not at all my idea.

There also is a section about implementing this. It will show that in C and C++ it’s very hard to make this software platform-independent. It’s still possible to implement it rather nicely.

Sign your timer (let clock hands rotate)

Clocks from different views

Fig.1 If I want to know the hour I need the outside only

If you are to implement timers in a run-time system, keep these points in mind: True time is represented as a signed value, like int. It increments on every system tick, and is allowed to wrap around (like a standard wall clock: it never rotates back to zero on every noon or midnight: it just continues). It wraps from most positive to most negative and up to -1 into where it started: zero. That’s what happens with any number represented by a finite size of bits. It’s as good, practical and accurate as the face of a wall clock. I’m not talking about the mechanism inside, just the face. If you have fallen off now, read the Two’s complement article in the Wiki-refs below.

As mentioned, two’s complement signed time starts at zero and increments by one on each time tick. Wrapping the signed value around from (e.g.) INT16_MAX (32767 = 0x7fff assuming 16 bits time, including the sign bit) to INT16_MIN (-32768 = 0x8000), and then a lot of ticks up to minus 1 (-1 = 0xffff) and then one up to zero again. This will take 2exp16 = 65536 ms if a tick is a millisecond.

With this representation you can do time arithmetics directly. Adding to present time takes you ahead. Subtracting from present time takes you back. And taking the difference gives you passed time since an incident.

Of course there’s more to it than this. Especially if you program in C/C++.

What I am saying is don’t make a timer with an unsigned value that counts from zero to some value and then it restarts from zero again. It’s much more difficult for the basic low-level timer system. That’s what you would do with a clock and calendar: [year].[month].[day] – [hour].[minute]:[second] – [millisecond]. 2015.09.18 – 18:39:23 – 376 is fine this way: They all regularly start at zero, except for the year I assume. That’s the way the wise men designed it.

Disclaimer (an alternative)

Taking the year number range a little further. It’s easy to see that we need only 16 bits signed [-32768..0..32767] to cover all our years; if we are not in astrophysics. But it’s also ok as unsigned (UINT), since [0..65365] would also cover all our years in it – provided you don’t need to set the date on your computer to 100 A.D. (-100). Using a big enough number range (or wide enough data representation) also solves the problem. 64 bit data width (UINT64) gives you [0..((2exp64)-1))] or [-2exp63…((2exp63)-1))]. It’s big enough to do all the arithmetics you need. If one tick is 1ns then full range unsigned 64 bits range covers 584 years, enough for any low level timer I assume.

But for those of us who can’t afford an INT64, but must use INT32 (which counts milliseconds for max 50 days) – or even INT16 or INT8 (for counting 60 seconds to a minute), then this blog note may be worth reading. It’s also about a deep problem in C/C++. After all, I am in embedded computing.

Disclaimer: at some level time may be signed or unsigned

(Update 6Jan2017) After this note was written I have learned that what matters is that the timer is monotonic and wraps around with the full width of the word. It won’t easily count to some value (like once every us to 1 mill per second and then starting at zero again). That would make it difficult. If the correct type of instruction is used and the correct type of arithmetic operator is used, then at the application level one could have timers and time represented equally well as signed or unsigned! The XMOS XC timer is an example. See more below, in chapter XMOS Xcore XE Community discussion group, second paragraph, that points to an XCore discussion thread. This is important to get right. How much have I learned that everything is connected to everything!

Before start of time

When in need of calculating what the value of time was «10 seconds ago» asked 9 seconds into time really, time being signed or not, I assume one really have to wrap the time back like it had been running as long as the round or reset time. With computers, basically any value of time will wrap around (or be reset) sooner or later, and a start of time would be no different from wrapping-around or reset of time. In that matter, «before start of time» does have some kind of meaning.

I have no idea how this would be handled in a system where the number of bits were thought to increase forever. If a product lasts 30 years then we have seen that forever is indeed possible with f.ex. 64 bits time. But also in this case I think signed numbers are easier, argued as in the above paragraph.

In any case: «order a timeout»

At the application level you would «order a timeout» and get an event when it has timed out. It’s always abstracted to that level in the API.

This event may be a timer message arriving in a message queue; or a CSP type of timeout brought to the process on a timer channel, picked up as waiting for time to pass only (in a single input) or together with other channels in an ALT or selective choice. Like our channel based ALTTIMEREGGTIMER or REPTIMER (which we implemented with signed INT32 values with 10 ms ticks in C) [1].

To order a timeout as ticked off in a calendar is not covered here. However, having something that counts seconds is often enough for an embedded application. Again, the actual waited for value might be signed as discussed here. Even calendars may have this inside.

The AFTER macro

This is just an example from the occam2c.c file that came with SPoC (Occam Portable occam Compiler) [3]. SPoC is long dead and gone, but it’s certainly worth understanding:

#define AFTER_F(a,b) ((a-b)>0) // Portability issue later
c_int09 (void) // Timer tick
    TIMER = TIMER + 1;
    if (QTM != NoTask && AFTER(TIMER,QTM->comms.timer.time))
        TimerEvent = true;

As you see the timer tick looks at the front of a timer queue to see if the next timeout has timed out. That’s all it needs to do, in addition to taking that timeout out of the queue. The queue contains signed timeouts, all future timeouts in that queue being within the range. The queue is arranged according to sequential time, which means that when a timeout (=timer) is ordered it will have to be spiced into the right position. So it’s a linked list with the next in front. If some timeouts are equal then this system is satisfied with taking them one at a time. But it could be implemented differently, of course.

Update (21Sep2018): See my present AFTER macros for XC at Some XC timer macros

Discussing platform dependence

I stumbled on a problem when I tried to implement the AFTER macro with an 8 bit signed char timer value (that I will show you below), expected to count to from 0 up to 127 and wrap to -128 then up to -1, then into 0 again. I was surprised even if I had an earlier blog note on a similar matter, «Is (x < (x+1)) really always true?» [8]. It turned out to be a case about C/C++ platform dependence. Here are some traces of the code and some discussion. Much more at the second half of this note.

EDA Playground

A piece of code to play with at

XMOS Xcore XE Community discussion group

See 8 bit signed overflowing problem. Most portable solution found for C, without having to wrap platform independent code into a portable interface. Great answer from Richard Osborne there (shown below).

Update 5Jan2017: See my «timerafter parameter» xcore discussion group entry that shows the precise semantics of the timer on XMOS cores. The counter is 32 bit «unsigned». It shows that it’s the monotonic full word wrap-around that makes it work. Whether, on the language level we use signed or unsigned doesn’t matter as long as the overflow behaviour is correct. The semantics of the AFTER macro is also shown. Thanks, henk!


See A similar thread is mentioned. Integer promotion in C/C++.

ISO C++ Standard group isocpp

See Quite useful description of what goes on. C and C++ doesn’t guarantee neither two’s complement nor defined overflow semantics.

Go Playground

See for a Go version.

The AFTER macro – platform-independent’ish

This might for all I know be the most platform-independent code there is for standard C/C++ code. It’s the result of all the discussions above, but most from an advice by Richard (above) on the Xcore.

#define AFTER_8(a,b)  ((signed char)(a-b)>0)
#define AFTER_16(a,b) ((short)(a-b)>0)
// No type decorations if int or wider(*) 
#define AFTER_32(a,b) ((a-b)>0)
#define AFTER_64(a,b) ((a-b)>0)

if AFTER_NN (TimeNow_Ticks, TimeoutFuture_Ticks) { // NN is 8,16,32 or 64
    // timed out
    // Add time passed since last (might be the invariant TICK value)
} else {
    // still counting

(*) Assuming sizeof int is 4. The type decoration is said ( above) not to be used for int or wider. However, I have tested this on the XMOS startKIT and there it runs fine, but the (int) decoration for AFTER_32 is optional, it works with or without. When I mentioned this on isocpp the next reply was that this only works by coincidence or something along that matter.

Repeated busy-poll with timeout

(Update Mar2018) I show an XC code example in XC code examples, chapter «Repeated busy-poll with timeout».

Timer queue

There may be one timer queue per process priority. A queue may contain the next timeout in front of the queue (signed timed value or unsigned time until next). The following timeouts may be signed values (where all the timeouts of the whole queue must be within the max time range) or relative times (where each step may take the full range, but depending on the timer data width it may be problematic to delete a timer). I’d again say that with a limited data width like 32, 16 or 8 bits making everything signed is the easiest.

Adding a new timeout and deleting one that’s not wanted any more introduce complexity. Observe that if a timeout is deleted it may be almost too late, and it may not be in the timer queue but might have reached the run queue. Either you pick them out there, too, or you prepare for an application event of type «oops, now!» This may be extremely unwanted, especially from a safety angle. To avoid this in a system we made, with CSP on top of an asynchronous run-time, we solved it by tagging each timeout and then we could remove it before it did any harm [9][10]. A CSP type system will never have any deleted timeout appearing anyhow.

All clocks to stop

Fig.2 No clock lasts forever

Coding surprise

This started with Code 1 (below). As mentioned, I needed to do something once per minute, and I had seconds events arriving. Time was signed char since it even takes two minutes before it wraps around (60, 120, then some negative value that I didn’t care about). Here is the test code that did not work:

Code 1: C with 8 bit signed (never works)

Read the code like this: Compile with ‘>’, «>=» and «==» below ##. Then watch Cnt2. In the example it becomes 35, 35 and the expected 10:

unsigned int  Cnt1 = 0; // 16 bits (kind of system clock)
unsigned int  Cnt2 = 0; // 16 bits (observer)
signed   char Timer_Secs = 0;             // 8 bits with sign
signed   char FutureTimeout_1Minute = 60; // 8 bits with sign

while (Cnt1 < 602) { //                      ##
    if ((Timer_Secs - FutureTimeout_1Minute) == 0) {            
        FutureTimeout_1Minute += 60; // Overflow/underflow  
                                     // implementation dependent, may
                                     // wrap and change sign 
    } else {} // No code
//               ## 
// Cnt2 is 35 if >  0 above   #define AFTER_F(a,b)    ((a-b)>0)
// Cnt2 is 35 if >= 0 above   #define AFTER_EQ_F(a,b) ((a-b)>=0)
// Cnt2 is 10 if == 0 above   #define AFTER_ON_F(a,b) ((a-b)==0) 
//         10 is expected by me

GCC 3.2 on AVR ATmega 8-bitter

With this compiler the example above produced the erroneous signed 8 bit values and for the example below the correct signed 16 bits values. This is the compiler I discovered this with.

GCC 4.8.4 on 64 bits Ubuntu

With this compiler the example above produced the same erroneous signed 8 bit values and for the example below the same correct signed 16 bits values. Thanks to Frank at work!

xTIMEcomposer startKIT on 32-bitter multi-core

With this toolset the example above produced the same erroneous signed 8 bit values. The XMOS startKIT has a processor with 8 logical cores. It compiles xC code. xTIMEcomposer is version 14.0.4, but it probably won’t matter. See My XMOS notes about this platform.  Also another chapter in this document: #xmos_xcore_xe_community_discussion_group

Doing it more right

However, Richard (above) in the Xcore group gave a correct solution to how the 8-bit signed (or any such) code should be written to get it right. Decorate with «(signed char)». See the AFTER macro above etc. Correct enough on that platform, or on other platforms. I found no platforms where code 1 works, and not where the signed char decoration didn’t produce the expected results. But this isn’t enough for C/C++.

A guy at the stackoverflow thread pointed to -fwrapv gcc option [6]. «This option instructs the compiler to assume that signed arithmetic overflow of addition, subtraction and multiplication wraps around using twos-complement representation.» It did not help for Code 1.

Miro Knejp in the isocpp C++ group commented there. Here’s part of a private mail with a good advice:

Me: The responses were as I expected: kind of expect the unexpected!

Miro: No, my point is “don’t do it”. Find a solution that is well defined by the language. If you cannot, then wrap the addition in a function, e.g. signed_add_with_cyclic_overflow(a, b) and use platform-dependent code that is clearly documented by your implementation (e.g. intrinsics or inline assembly) in that function only, then it stands out as something special and you have a customization point for other platforms. Make it clearly visible that this operation is not portable.

Miro: As soon as you start relying on undefined behavior you are just asking for problems either now or in the future (like losing portability, and every compiler update could break your code).

Miro: It is well defined in Go because Go restricts itself to 2’s complement integers only, therefore it only supports hardware that runs with 2’s complement integers.

Building platform-independent software by carefully using platform-dependent Lego bricks certainly makes me doubt. I cannot for the best of it understand that it need be this way! Having two roles, as both high level and low level is a demanding double role for any tool. Not to say its user. Is it layered well enough (like the Modula-2 SYSTEM module that covered everything platform-specific [11])? No, not in C/C++. The platform-dependent matters seem to be so thinly spread!

A very interesting note from «CERT 32-C. Ensure that operations on signed integers do not result in overflow» appears in the isocpp, see [5].

Code 2: C with 16 bits signed (may work)

Here’s a 16 bits version. 60002 has been used to make the point where the diff passes from being negative to equal and positive to exactly hit the equal, so that we compare apples and apples. Also, we needed to wrap at least once, which it does between +32767 and -32768. It works as expected on all the platforms I have tested it. However, as Miro (above) points out «I suggest you point out in that article that the 16 bit version is exactly as broken as the 8 bit version. It is mere coincidence that it works for you.»

unsigned int Cnt1 = 0; // 16 bits (kind of system clock)
unsigned int Cnt2 = 0; // 16 bits (observer)
signed int Timer_Secs = 0;             // 16 bits with sign
signed int FutureTimeout_1Minute = 60; // 16 bits with sign

while (Cnt1 < 60002) { //                   ##
   if ((Timer_Secs - FutureTimeout_1Minute) > 0) {
       FutureTimeout_1Minute += 60; // Promise as broken as 8-bitter
                                    // May wrap and change sign
   } else {} // No code
//                 ##
// Cnt2 is 1000 if >  0 above #define AFTER_F(a,b)    ((a-b)>0)
// Cnt2 is 1000 if >= 0 above #define AFTER_EQ_F(a,b) ((a-b)>=0)
// Cnt2 is 1000 if == 0 above #define AFTER_ON_F(a,b) ((a-b)==0)
//         1000 is expected by me

Code 3: Go (golang) with 8 bit signed (always works)

Why do I bring Golang into this? Because I am curious. Looking through muddy C/C++ glasses I was up for a surprise here too. Surprised that in Go it works for all  ‘>’, «>=» and «==» cases  (at the Go Playground, above (ok then, it’s here)):

package main
import "fmt"
func main() {
        var Cnt1, Cnt2 int = 0, 0
        var Timer_Secs int8 = 0
        var FutureTimeout_1Minute int8 = 60

        for Cnt1 < 602 { //                             ##
                if (Timer_Secs - FutureTimeout_1Minute) == 0 {
                        FutureTimeout_1Minute += 60 
                } else {
                        // No code
        //               ##
        // Cnt2 is 10 if >  0 above (correct)
        // Cnt2 is 10 if >= 0 above (correct)
        // Cnt2 is 10 if == 0 above (correct)
        fmt.Println("Cnt2 ", Cnt2)

Miro (above) writes that «It is well defined in Go because Go restricts itself to 2’s complement integers only, therefore it only supports hardware that runs with 2’s complement integers.»

Richard (Xcore, above) writes that «The rules in Go are different, in particular the result type of an arithmetic operator is the same as the type of its first operand so no explicit cast is needed.»

From «occam 2 Reference Manual»

The «occam 2 Reference Manual» [4] since the 1985 INMOS version has been the ultimate reference for this for me. This is the main text:

A value input from a timer provides an integer value of type representing the time. The value is derived from a clock, which changes by an increment at regular intervals. The value of the clock is cyclic (ie. when the value reaches the most positive integer value, an increment results in the most negative integer value). The special operator AFTER can be used to compare times even though the value may have crossed from most positive to most negative, just as one o’clock pm may be considered later than eleven o’clock am. If t1 and t2 and are successive inputs from the same timer, then the expression t1 AFTER t2 is true if t1 is later than t2. This behaviour is only sensible if the second value (t2) is input within half a cycle of the timer.

occam allowed overflow/underflow with the «PLUS», «MINUS» and «AFTER» and «TIMES» operators. These are standard modulo arithmetic operators. The ‘+’ and ‘-‘ operators did cause exception traps. To make something platform independent in C/C++ this line of reasoning would be the most interesting line of pursue, it’s actually suggested in the isocpp thread.

QAC static analysis tool

Thanks to Frank at work I gather that the QAC tool (QA-C, by PRQA Programming Research, see Wiki-refs below) reports the same message with and without the type decoration in Code 1 (above). (I call it type decoration, even if in the C/C++ world it’s probably called typecast. I’m used to differentiating between the two.) Here’s the QAC output for both cases:

Message 2104
An operand of type signed char is being converted to type signed int
under the rules of integral promotion. This type of conversion will occur 
whenever an expression of type signed char is used as an operand of the 
following operators: (...)
Integral promotion
ISO:C90 Language
Security Problems

In other words: the same info when it works and when it does not work. The reason is that even the type decoration is strictly wrong. As for C/C++ I’d say that..

  1. on the cognitive level there is no type decoration. Rotating hands on a steady clock face is absolutely fine. I see the same hands and face in all aspects of it. I don’t relate to the notebook of an observer; I don’t even dream that there is one such;
  2. knowing the inner shuffling I add the type decoration (with a little help from a friend);
  3. thereby getting it to work I must know that it’s only for now. Don’t dare stating that this is the correct solution;
  4. the correct solution is behind a screen of smoke.
Dual gauge rail (146 and 178 mm) at The Railway Museum at Hamar (Jernbanemuseet) with Minitoget Knertitten

Fig.3 Hard, flexible and no derailing

C/C++ twisted reasoning

So, the C/C++ compiler would treat a and b as int internally. Then the transfer back to signed char is not defined if there is an overflow or underflow. As we have seen it’s called integral promotion in the C/C++ world [7]. To get it about right on a lucky day I have to do it in the code, explicitly, as we have seen:

#define AFTER_8(a,b) ((signed char)(a-b)>0)

I would have been happy if the compiler had required a type decoration. However, in the C/C++ community this can’t be done because it would apply all over.

The more places a potential error might appear, the stronger the argument not to require it to be implemented platform independently

I would call this the «C/C++ twisting reasoning». My conclusion (about C/C++ usage, not about signed vs. unsigned timer values) is covered well in the Fig.3 description below.

MITRE report 2011: 24th Most Dangerous Software Error

In CWE/SANS Top 25 Most Dangerous Software Errors, #24 CWE-190 Integer Overflow or Wraparound [12] MITRE writes:

In the real world, 255+1=256. But to a computer program, sometimes 255+1=0, or 0-1=65535, or maybe 40,000+40,000=14464. You don’t have to be a math whiz to smell something fishy. Actually, this kind of behavior has been going on for decades, and there’s a perfectly rational and incredibly boring explanation. Ultimately, it’s buried deep in the DNA of computers, who can’t count to infinity even if it sometimes feels like they take that long to complete an important task. When programmers forget that computers don’t do math like people, bad things ensue – anywhere from crashes, faulty price calculations, infinite loops, and execution of code.

Use a language that does not allow this weakness to occur or provides constructs that make this weakness easier to avoid. If possible, choose a language or compiler that performs automatic bounds checking.

It’s #24 in a list of 25, but if you sort on computer language there are very few in the list. In other words, it’s a substantial problem related to programming language. IsoCpp can repeat how long they want, but I fail to see how their approach helps.

All of a sudden I felt this blog note even more important. Thanks, colleague Ingar!

And that (again!) the occam design was rather sound: modulo arithmetic operators and arithmetic operators were in separate worlds. The first never caused exception, the latter always cause exception on overflow/underflow.

Monotonic timer

(Update May2016) Have a look at the golang-nuts thread «Monotonic timers on OS X» (here). It’s a valuable read, especially if you follow some of the links there, perhaps the most important being the golang-dev thread «Use monotonic clock for timers» (here). Adding another layer makes matters even more complicated!


The pictures

All photography by me.

  • Fig.1 If I want to know the hour I need the outside only
    The left clock is on Chiesa dei Santi Jacopo e Filippo (o del Carmine) in Montecatini Alto (Italy). It seems to have six named tags (Roman I, II, II, IV, V, VI) but dots for 12 hours. The middle clock is from the inside of Hallgrímskirkja (Reykjavík, Iceland). However, it’s the wrong place to be to if you wonder what time it is. C/C++ is the wrong place to be if you want to find out what the time is 13 hours from now, because you need to see the clock from the outside and the inside at the same time. The right clock is the Swiss railroad Clock at Rorschach (Switzerland). The latter «requires only about 58.5 seconds to circle the face, then the hand pauses briefly at the top of the clock. It starts a new rotation as soon as it receives the next minute impulse from the master clock» (Wikpedia). It’s a very elegant solution to a problem. Several solutions, still easy to understand, contrary to C/C++
  • Fig.2 No clock lasts forever
    The former Landteknikk facility in Ladeveien in Trondheim (clock magnified). The clock is gone, but this structure seems to become part of Nye Lilleby city area. I’d say that the C/C++ solution to overflow handling is doomed like this clock. I magnified the clock a little, to make it better visible
  • Fig.3 Hard, flexible and no derailing
    Dual gauge rail (5″=127 mm and 7 1/4″=184 mm + 3 mm max in the curves) at The Railway Museum at Hamar (Norsk Jernbanemuseum, Jernbanemuseet – thanks for the info!) with Minitoget Knertitten. I wish C/C++ were as easy to work with as this gem of engineering. It even supports dual standards without derailing. Most importantly, the engineer does not have to stop the train, dismantle and study the switch to see if works


Two’s complementoccam, QA-C

The references

  1. New ALT for Application Timers and Synchronisation Point Scheduling, Øyvind Teig and Per Johan Vannebo, 2009, at
  2. Southampton Portable occam Compiler (SPoC) by Mark Debbage, Mark Hill ,Sean Wykes and Denis Nicole at Department of Electronics and Computer Science, University of Southampton (1994), see
    It generated C from occam. I learnt a lot from it and its run-time system implementation
  3. Another side of SPoC: occam’s ALTer ego dissected with PC-lint by Øyvind Teig at WoTUG-22. Architectures, Languages and Techniques for concurrent systems, p.19-36, see About SPoC’s generated file, including the occam2c.c file:
  4. occam 2.1 Reference Manual, SGS-THOMSON Microelectronics Limited. First published 1988 by Prentice Hall International (UK) Ltd as the occam 2 Reference Manual (then INMOS).  SGS-THOMSON Microelectronics Limited 1995, see
  5. 32-C. Ensure that operations on signed integers do not result in overflow by Robert C. Seacord, Software Enineering Institute, Carnegie Mellon University, see Plsu an interesting discussion thread
  6. gcc -fwrapv, see
  7. Implicit conversions -> Numeric promotions -> Integral promotion, see
  8. Is (x < (x+1)) really always true? by me, see
  9. No Blocking on Yesterday’s Embedded CSP Implementation by Øyvind Teig, presented at: Communicating Process Architectures 2006 (CPA-2006) Edinburgh, see
  10. From message queue to ready queue by Øyvind Teig, presented at 31st EUROMICRO Conference on Software Engineering and Advanced Applications (SEAA) Porto, see
  11. (ContentCreationWiki ). «Main differences to Pascal: Pseudo module SYSTEM for accessing system dependent resources. Machine dependent types BYTE, WORD, ADDRESS. Built-in coroutine support for concurrency: PROCESS, NEWPROCESS, TRANSFER, IOTRANSFER»
  12. 2011 CWE/SANS Top 25 Most Dangerous Software Errors, #24 CWE-190 Integer Overflow or Wraparound, see

Leave a Reply

Dette nettstedet bruker Akismet for å redusere spam. Lær om hvordan dine kommentar-data prosesseres.