Why Would a Program Need to Set the Clock?
In most systems, the clock is managed automatically by the NTP (Network Time Protocol) daemon. But understanding the underlying system calls — settimeofday() and adjtime() — is important for embedded systems engineers, where NTP may not be available, or when you need to synchronise time from a custom hardware source (GPS, RTC chip, etc.).
Keywords in This Post
settimeofday() sets the system clock to an exact time you specify. It is the write counterpart to gettimeofday(). Requires the CAP_SYS_TIME capability (root or equivalent).
#define _BSD_SOURCE
#include <sys/time.h>
int settimeofday(const struct timeval *tv, const struct timezone *tz);
/* Returns 0 on success, -1 on error */
/* tz should always be NULL (historical, obsolete argument) */
#define _BSD_SOURCE
#include <sys/time.h>
#include <stdio.h>
int main(void)
{
struct timeval tv;
/* Set clock to: 15 May 2025, 10:30:00 UTC */
/* (In a real program, compute this from reliable external source) */
tv.tv_sec = 1747267800; /* seconds since Epoch */
tv.tv_usec = 0;
if (settimeofday(&tv, NULL) == -1) {
perror("settimeofday");
/* Will fail with EPERM unless running as root or with CAP_SYS_TIME */
return 1;
}
printf("System clock updated successfully.\n");
return 0;
}
The hidden danger of jumping the clock:
When you use settimeofday() to jump the clock forward or backward by several seconds, programs that depend on the clock behaving continuously can break:
• make uses file timestamps to decide what to recompile — a clock jump can cause it to skip necessary rebuilds or redo everything.
• Database systems using timestamps for transaction ordering may produce inconsistent results.
• Log files may have entries appearing “out of order” or in the future.
This is why adjtime() is almost always preferred.
Instead of jumping the clock, adjtime() slews it — it speeds up or slows down the clock slightly until the desired correction is achieved. The clock always moves forward; it just moves at a slightly different rate for a while.
Analogy: You set your wall clock 2 minutes fast. Rather than ripping it off the wall and resetting it, you simply make it tick a tiny bit slower for the next hour until it catches up to the correct time. Everything observing the clock sees a smooth, continuous progression.
#define _BSD_SOURCE
#include <sys/time.h>
int adjtime(struct timeval *delta, struct timeval *olddelta);
/* delta = how much to adjust (positive = speed up, negative = slow down) */
/* olddelta = returns remaining unapplied correction from a prior call (or NULL) */
/* Returns 0 on success, -1 on error */
#define _BSD_SOURCE
#include <sys/time.h>
#include <stdio.h>
int main(void)
{
struct timeval delta;
struct timeval pending;
/* Correct clock: add 2 seconds gradually */
delta.tv_sec = 2;
delta.tv_usec = 0;
if (adjtime(&delta, &pending) == -1) {
perror("adjtime");
return 1;
}
printf("Adjustment requested: +%ld.%06ld s\n",
(long)delta.tv_sec, (long)delta.tv_usec);
printf("Pending from last call: %ld.%06ld s\n",
(long)pending.tv_sec, (long)pending.tv_usec);
return 0;
}
| Scenario | What adjtime() does |
|---|---|
| Clock is 2 seconds slow (delta = +2s) | Speeds clock up by 500 µs/s. Takes 4000 s (≈ 1.1 hours) to add 2 seconds. |
| Clock is 1 second fast (delta = -1s) | Slows clock down by 500 µs/s. Takes 2000 s (≈ 33 minutes) to lose 1 second. |
| New adjtime() call while correction is pending | The remaining correction is returned in olddelta; the new delta replaces it. |
| Scenario | Recommended function | Reason |
|---|---|---|
| System just booted, clock is far off (minutes/hours) | settimeofday() | No running apps to break; need immediate correction |
| Running system, clock is a few seconds off | adjtime() | Maintains monotonic clock; avoids breaking apps |
| Continuous NTP-style synchronisation | adjtimex() | More precise kernel-level interface used by ntpd |
Embedded systems context: If your board has an RTC (real-time clock) chip and reads it at boot via I2C, you would call settimeofday() once at startup (before any user processes start) to set the kernel clock. If your system has periodic GPS pulse synchronisation, you would use adjtime() for continuous small corrections to keep the kernel clock accurate without disrupting running processes.
Up Next in This Series
Part 9 covers the Software Clock (Jiffies), Process Time, and the times() / clock() functions — measuring how much CPU your program actually used.
