Skip to content

Commit 0a64787

Browse files
committed
samples: timerfd: add sample and readme
Add the timerfd sample and README file. The timerfd follows a similar behavior as specified in other POSIX OS. Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
1 parent a993358 commit 0a64787

File tree

6 files changed

+146
-0
lines changed

6 files changed

+146
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
5+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
6+
project(timerfd)
7+
8+
target_sources(app PRIVATE src/main.c)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# This makefile builds the sample for a POSIX system, like Linux
2+
3+
timerfd: src/main.c
4+
mkdir -p build
5+
$(CC) $^ -o build/$@

samples/posix/timerfd/README.rst

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.. zephyr:code-sample:: posix-timerfd
2+
:name: timerfd_create()
3+
4+
Use ``timerfd_create()`` to create a file descriptor for timer notification.
5+
6+
Overview
7+
********
8+
9+
This sample application demonstrates using the POSIX timerfd_create() functions to create a file
10+
descriptor, which can be used as a timer. The returned file descriptor is used with read calls
11+
and the timeout count are printed to the console.
12+
13+
Building and Running
14+
********************
15+
16+
This project outputs to the console. It can be built and executed on QEMU as follows:
17+
18+
.. zephyr-app-commands::
19+
:zephyr-app: samples/posix/timerfd
20+
:host-os: unix
21+
:board: qemu_x86
22+
:goals: run
23+
:compact:
24+
25+
For comparison, to build directly for your host OS if it is POSIX compliant (for ex. Linux):
26+
27+
.. code-block:: console
28+
29+
cd samples/posix/timerfd
30+
make -f Makefile.host
31+
32+
The make output file will be located in samples/posix/timerfd/build.
33+
34+
Sample Output
35+
=============
36+
37+
.. code-block:: console
38+
39+
Timer expired 1 times
40+
Timer expired 3 times
41+
Timer closed

samples/posix/timerfd/prj.conf

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# General config
2+
CONFIG_REQUIRES_FULL_LIBC=y
3+
CONFIG_POSIX_API=y
4+
CONFIG_TIMERFD=y
5+
CONFIG_ZVFS_OPEN_MAX=4

samples/posix/timerfd/sample.yaml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
sample:
2+
description: Extended POSIX (Linux) API timerfd() example
3+
name: timerfd
4+
common:
5+
filter: CONFIG_FULL_LIBC_SUPPORTED and not CONFIG_NATIVE_LIBC
6+
tags: posix
7+
platform_exclude: m2gl025_miv
8+
integration_platforms:
9+
- mps2/an385
10+
tests:
11+
sample.posix.timerfd:
12+
min_ram: 32
13+
tags: posix
14+
harness: console
15+
harness_config:
16+
type: multi_line
17+
ordered: true
18+
regex:
19+
- "Timer expired 1 times"
20+
- "Timer expired 3 times"
21+
- "Timer closed"

samples/posix/timerfd/src/main.c

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/*
2+
* Copyright (c) 2025 Atym, Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*
6+
* This sample application is roughly based on the sample code in Linux
7+
* manpage for timerfd().
8+
*/
9+
#include <sys/timerfd.h>
10+
#include <unistd.h>
11+
#include <stdlib.h>
12+
#include <stdio.h>
13+
#include <stdint.h>
14+
#include <inttypes.h>
15+
16+
#define fatal(msg) \
17+
do { perror(msg); exit(EXIT_FAILURE); } while (0)
18+
19+
void read_now(int fd)
20+
{
21+
uint64_t count;
22+
23+
/* read the number of times the timer has expired */
24+
int bytes_read = read(fd, &count, sizeof(count));
25+
if (bytes_read == -1) {
26+
fatal("read");
27+
}
28+
printf("Timer expired %" PRIu64 " times\n", count);
29+
}
30+
31+
int main(void)
32+
{
33+
/* create the timer file descriptor */
34+
int tfd = timerfd_create(0, 0);
35+
if (tfd == -1) {
36+
fatal("timerfd_create");
37+
}
38+
39+
/* arm a recurring timer for 1 second */
40+
struct itimerspec timer_spec = {
41+
.it_interval = { .tv_sec = 1, .tv_nsec = 0 },
42+
.it_value = { .tv_sec = 1, .tv_nsec = 0 }
43+
};
44+
45+
int rc = timerfd_settime(tfd, 0, &timer_spec, NULL);
46+
47+
if (rc == -1) {
48+
fatal("timerfd_settime");
49+
}
50+
51+
/* read the number of times the timer has expired */
52+
/* will block until the timer expires */
53+
read_now(tfd);
54+
55+
/* if we wait long enough, the timer will expire more than once */
56+
sleep(3);
57+
58+
/* the function will not block as the timer already expired */
59+
read_now(tfd);
60+
61+
close(tfd);
62+
63+
printf("Timer closed\n");
64+
65+
return 0;
66+
}

0 commit comments

Comments
 (0)