Zephyr API Documentation 4.4.99
A Scalable Open Source RTOS
Loading...
Searching...
No Matches
sleep.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7#ifndef ZEPHYR_INCLUDE_SLEEP_H_
8#define ZEPHYR_INCLUDE_SLEEP_H_
9
14
15#include <stdint.h>
16
17#include <zephyr/sys/clock.h>
19#include <zephyr/sys/util.h>
20#include <zephyr/toolchain.h>
21
22#ifdef __cplusplus
23extern "C" {
24#endif
25
30
49
51
52/*
53 * k_sleep() and k_usleep() below are inlined on top of k_sleep_ticks()
54 * rather than being separate out of line entry points. That way the compiler
55 * sees both whether the requested duration is constant and whether the caller
56 * actually cares about the returned value, and it can fold or discard the
57 * unit conversions accordingly. Those conversions are the sole reason many
58 * small builds pull in the 64 bit division helper.
59 *
60 * For the callers that do use the returned value, the two converters below
61 * keep the arithmetic 32 bit wide. They first clamp in the tick domain,
62 * against a bound computed at compile time, which is what makes the narrower
63 * arithmetic safe. It pays off because a compiler strength reduces a 32 bit
64 * division by a constant into a multiply, yet calls the 64 bit division
65 * helper for that same constant divisor in 64 bit.
66 *
67 * Where the tick rate makes the conversion a single division or a single
68 * multiplication, that holds on any target. The split forms are different:
69 * they trade one division for two or three, which only wins where the one
70 * they replace would have been a call to a helper. A 64 bit target divides
71 * in hardware, so it keeps the plain converter for those.
72 *
73 * The tick count handed to these converters always lies in the
74 * [0, INT32_MAX] range, since k_sleep_ticks() derives it from a 32 bit
75 * subtraction, so narrowing k_ticks_t to a uint32_t loses nothing.
76 */
77
78#define Z_SLEEP_TICK_HZ ((uint32_t)CONFIG_SYS_CLOCK_TICKS_PER_SEC)
79
80/* True when the conversion reduces to a single division or multiplication,
81 * needing none of the splits.
82 */
83#define Z_SLEEP_IS_SIMPLE(to_hz) \
84 (Z_SLEEP_TICK_HZ % (to_hz) == 0 || (to_hz) % Z_SLEEP_TICK_HZ == 0)
85
86/* Largest tick count whose value in to_hz units still fits in an int32_t. */
87#define Z_SLEEP_MAX_TICKS(to_hz) ((uint64_t)INT32_MAX * Z_SLEEP_TICK_HZ / (to_hz))
88
89/* True when (rem * to_hz + Z_SLEEP_TICK_HZ - 1) cannot overflow 32 bits,
90 * knowing that rem is a remainder modulo Z_SLEEP_TICK_HZ.
91 */
92#define Z_SLEEP_NO_OVERFLOW(to_hz) \
93 ((uint64_t)Z_SLEEP_TICK_HZ * ((to_hz) + 1U) <= UINT32_MAX)
94
95/* Past the clamp, ceil(t * to_hz / hz) without exceeding 32 bits: split the
96 * division so the whole seconds are scaled separately from the remainder.
97 */
98#define Z_SLEEP_SPLIT(t, to_hz) \
99 (((t) / Z_SLEEP_TICK_HZ) * (to_hz) + \
100 DIV_ROUND_UP(((t) % Z_SLEEP_TICK_HZ) * (to_hz), Z_SLEEP_TICK_HZ))
101
102static inline int32_t z_sleep_ticks_to_int32_ms(k_ticks_t ticks)
103{
104 uint32_t t = (uint32_t)ticks;
105
106 /* a split is not worth narrowing for where 64 bit division is cheap */
107 if (IS_ENABLED(CONFIG_64BIT) && !Z_SLEEP_IS_SIMPLE(MSEC_PER_SEC)) {
109 }
110
111 if (Z_SLEEP_MAX_TICKS(MSEC_PER_SEC) < (uint64_t)INT32_MAX &&
112 t > (uint32_t)Z_SLEEP_MAX_TICKS(MSEC_PER_SEC)) {
113 return INT32_MAX;
114 }
115
116 /* a whole number of ticks per millisecond, 1:1 included */
117 if (Z_SLEEP_TICK_HZ % MSEC_PER_SEC == 0) {
118 return (int32_t)DIV_ROUND_UP(t, z_tmcvt_divisor(Z_SLEEP_TICK_HZ, MSEC_PER_SEC));
119 }
120
121 /* a whole number of milliseconds per tick */
122 if (MSEC_PER_SEC % Z_SLEEP_TICK_HZ == 0) {
123 return (int32_t)(t * z_tmcvt_divisor(MSEC_PER_SEC, Z_SLEEP_TICK_HZ));
124 }
125
126 if (Z_SLEEP_NO_OVERFLOW(MSEC_PER_SEC)) {
127 return (int32_t)Z_SLEEP_SPLIT(t, MSEC_PER_SEC);
128 }
129
130 /* tick rate too high to be scaled in 32 bits at all */
132}
133
134/* Microseconds need one step more than milliseconds: a remainder times
135 * USEC_PER_SEC overflows 32 bits for any tick rate above 4294 Hz, so scale
136 * the remainder by USEC_PER_MSEC twice, carrying the first quotient over.
137 * With A = rem * 1000 = q * hz + r, ceil(A * 1000 / hz) is exactly
138 * q * 1000 + ceil(r * 1000 / hz), and r < hz keeps the second step in range.
139 */
140static inline int32_t z_sleep_ticks_to_int32_us_split(uint32_t t)
141{
142 uint32_t sec = t / Z_SLEEP_TICK_HZ;
143 uint32_t rem = (t % Z_SLEEP_TICK_HZ) * USEC_PER_MSEC;
144 uint32_t q = rem / Z_SLEEP_TICK_HZ;
145 uint32_t r = rem % Z_SLEEP_TICK_HZ;
146
147 return (int32_t)(sec * USEC_PER_SEC + q * USEC_PER_MSEC +
148 DIV_ROUND_UP(r * USEC_PER_MSEC, Z_SLEEP_TICK_HZ));
149}
150
151static inline int32_t z_sleep_ticks_to_int32_us(k_ticks_t ticks)
152{
153 uint32_t t = (uint32_t)ticks;
154
155 /* a split is not worth narrowing for where 64 bit division is cheap */
156 if (IS_ENABLED(CONFIG_64BIT) && !Z_SLEEP_IS_SIMPLE(USEC_PER_SEC)) {
158 }
159
160 if (Z_SLEEP_MAX_TICKS(USEC_PER_SEC) < (uint64_t)INT32_MAX &&
161 t > (uint32_t)Z_SLEEP_MAX_TICKS(USEC_PER_SEC)) {
162 return INT32_MAX;
163 }
164
165 /* a whole number of ticks per microsecond, 1:1 included */
166 if (Z_SLEEP_TICK_HZ % USEC_PER_SEC == 0) {
167 return (int32_t)DIV_ROUND_UP(t, z_tmcvt_divisor(Z_SLEEP_TICK_HZ, USEC_PER_SEC));
168 }
169
170 /* a whole number of microseconds per tick */
171 if (USEC_PER_SEC % Z_SLEEP_TICK_HZ == 0) {
172 return (int32_t)(t * z_tmcvt_divisor(USEC_PER_SEC, Z_SLEEP_TICK_HZ));
173 }
174
175 if (Z_SLEEP_NO_OVERFLOW(USEC_PER_SEC)) {
176 return (int32_t)Z_SLEEP_SPLIT(t, USEC_PER_SEC);
177 }
178
179 if (Z_SLEEP_NO_OVERFLOW(USEC_PER_MSEC)) {
180 return z_sleep_ticks_to_int32_us_split(t);
181 }
182
183 /* tick rate too high to be scaled in 32 bits at all */
185}
186
188
204static inline int32_t k_sleep(k_timeout_t timeout)
205{
206 k_ticks_t ticks = k_sleep_ticks(timeout);
207
208 /* k_sleep() still returns 32 bit milliseconds for compatibility */
209 if (K_TIMEOUT_EQ(timeout, Z_FOREVER)) {
210 return (int32_t)K_TICKS_FOREVER;
211 }
212
213 return z_sleep_ticks_to_int32_ms(ticks);
214}
215
227static inline int32_t k_msleep(int32_t ms)
228{
229 return k_sleep(Z_TIMEOUT_MS(ms));
230}
231
248static inline int32_t k_usleep(int32_t us)
249{
250 k_ticks_t ticks = k_sleep_ticks(Z_TIMEOUT_US(us));
251
252 return z_sleep_ticks_to_int32_us(ticks);
253}
254
256
257#ifdef __cplusplus
258}
259#endif
260
261#include <zephyr/syscalls/sleep.h>
262
263#endif /* ZEPHYR_INCLUDE_SLEEP_H_ */
System clock APIs.
#define MSEC_PER_SEC
number of milliseconds per second
Definition clock.h:92
#define USEC_PER_MSEC
number of microseconds per millisecond
Definition clock.h:89
#define K_TICKS_FOREVER
Definition clock.h:51
#define USEC_PER_SEC
number of microseconds per second
Definition clock.h:110
uint32_t k_ticks_t
Tick precision used in timeout APIs.
Definition clock.h:48
#define K_TIMEOUT_EQ(a, b)
Compare timeouts for equality.
Definition clock.h:80
#define IS_ENABLED(config_macro)
Check for macro definition in compiler-visible expressions.
Definition util_macro.h:154
#define MIN(a, b)
Obtain the minimum of two values.
Definition util.h:406
#define DIV_ROUND_UP(n, d)
Divide and round up.
Definition util.h:348
static int32_t k_sleep(k_timeout_t timeout)
Put the current thread to sleep.
Definition sleep.h:204
static int32_t k_usleep(int32_t us)
Put the current thread to sleep with microsecond resolution.
Definition sleep.h:248
static int32_t k_msleep(int32_t ms)
Put the current thread to sleep.
Definition sleep.h:227
k_ticks_t k_sleep_ticks(k_timeout_t timeout)
Put the current thread to sleep, with tick resolution.
#define k_ticks_to_ms_ceil64(t)
Convert ticks to milliseconds.
Definition time_units.h:1798
#define k_ticks_to_us_ceil64(t)
Convert ticks to microseconds.
Definition time_units.h:1894
__UINT32_TYPE__ uint32_t
Definition stdint.h:90
__INT32_TYPE__ int32_t
Definition stdint.h:74
#define INT32_MAX
Definition stdint.h:18
__UINT64_TYPE__ uint64_t
Definition stdint.h:91
Kernel timeout type.
Definition clock.h:65
Misc utilities.
Macros to abstract toolchain specific capabilities.