hn-classics/_stories/1990/12036394.md

27 lines
16 KiB
Markdown
Raw Permalink Normal View History

---
created_at: '2016-07-05T13:50:03.000Z'
title: Implementing Software Timers (1990)
url: http://www.kohala.com/start/libes.timers.txt
author: ingve
points: 66
story_text:
comment_text:
num_comments: 10
story_id:
story_title:
story_url:
parent_id:
created_at_i: 1467726603
_tags:
- story
- author_ingve
- story_12036394
objectID: '12036394'
2018-06-08 12:05:27 +00:00
year: 1990
---
2018-02-23 18:19:40 +00:00
[Source](http://www.kohala.com/start/libes.timers.txt "Permalink to ")
Title: Implementing Software Timers By: Don Libes Originally appeared in the Nov. 1990 "C User's Journal" and is also reprinted as Chapter 35 of "Obfuscated C and Other Mysteries", John Wiley & Sons, 1993, ISBN 0-471-57805-3. http://www.wiley.com/compbooks/m3.html. \--------------------------------------------------------------------- This column will describe a set of functions to implement software timers. What are software timers and why do you need them? Software timers make up for inherent limitations in hardware timers. For example, while most computers have clock hardware, you can typically only have the clock trigger an interrupt for one time in the future. When running multiple tasks, you will want to have the clock keep track of multiple timers concurrently so that interrupts can be generated correctly even if the time periods overlap. Operating systems do this all the time. Robert Ward discussed the related problem of building a general purpose scheduler ("Practical Schedulers for Real-Time Applications") in the April 1990 CUJ. In the "Additional Ideas" section, Robert described the usefulness of a timer scheduling queue. "Events can specify the timing of other events by putting a timer programming request in a special queue." That is exactly what the software in this column will do. (Thanks for the lead in, Robert.) You may want to reread at least the beginning of his column right now, although it isn't really necessary. The code in this column has other uses as well. For example, you can use it to simulate multiple timers in environments such as a UNIX process which only allows the user one software timer. Even if you aren't interested in software timers, I think you will find this an intriguing column. Using simple techniques and data structures, this C code produces very powerful results. The code was very tricky to get right, and my commentary should be interesting if only as some more practice in reading and writing C code. Timers By implementing the timers as a separate piece of software, we can reduce the complexity of the scheduler. Some people like this kind of modularization, and some don't. Similarly some operating systems do this, and some don't. I like it. It makes the code easier to write, to read, and to correct (oops). The basic idea of a timer is that they allow tasks to be run at some time in the future. When their time arrives, they are scheduled to be run. The responsibility of actually running them is then turned over to someone else, such as the scheduler. In order to communicate with the scheduler, we'll set up a common data structure called a timer (listing 1). I've also included a few other miscellaneous definitions that will be needed later on. For instance, the TIME typedef is used to declare all relative time variables. You can complete this definition based on what your needs are. #include #define TRUE 1 #define FALSE 0 #define MAX_TIMERS ... /* number of timers */ typedef ... TIME; /* how time is actually stored */ #define VERY_LONG_TIME ... /* longest time possible */ struct timer { int inuse; /* TRUE if in use */ TIME time; /* relative time to wait */ char *event; /* set to TRUE at timeout */ } timers[MAX_TIMERS]; /* set of timers */ listing 1 Each timer will be represented by a timer struct. The set of timers will be maintained in an array, timers. The first element of each timer declares whether the timer is in use. The second element of a timer is the amount of time being waited for. As time passes, this will be periodically updated. event is a pointer to a value that is initially set to 0. When it is time to run the task, *event is set to 1\. We can imagine that the scheduler also keeps an event pointer. Every so often, it reexamines it. When it finds it has been set to 1, it knows that the timer has expired and the associated task can be run. [Notice how simple this is. Other schedulers or other scheduler data structures could enable runnability, without worrying or even knowing about timers.] The code in listing 2 initializes the timers. It runs through the array settin