Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 65 additions & 0 deletions include/zephyr/kernel.h
Original file line number Diff line number Diff line change
Expand Up @@ -2707,6 +2707,71 @@ extern struct k_work_q k_sys_work_q;
* INTERNAL_HIDDEN @endcond
*/

/* Wrapper for the zync utilities below. Here in kernel.h because it
* needs to appear in both kernel and non-kernel contexts (i.e. can't
* be a simple function) AND needs to call out to external syscalls.
* Our include structure isn't friendly to this kind of usage.
*/
static inline int32_t z_pzyncmod(struct z_zync_pair *zp, int32_t mod,
k_timeout_t timeout)
{
int32_t ret;
int64_t start;
k_ticks_t t0;
bool retry, forever = K_TIMEOUT_EQ(timeout, Z_FOREVER);
bool ticking = !forever && !K_TIMEOUT_EQ(timeout, Z_TIMEOUT_NO_WAIT);

if (!IS_ENABLED(CONFIG_ZYNC_STRICT_TIMEOUTS)) {
ticking = false;
}

if (ticking) {
t0 = timeout.ticks;
start = k_uptime_ticks();
#ifdef CONFIG_TIMEOUT_64BIT
if (Z_TICK_ABS(t0) < 0) {
timeout = K_TIMEOUT_ABS_TICKS(t0 + start);
}
#endif
}

do {
if (IS_ENABLED(Z_ZYNC_ALWAYS_KERNEL)) {
ret = z_pzync(Z_PAIR_ZYNC(zp), mod, timeout);
} else if (k_zync_try_mod(Z_PAIR_ATOM(zp), mod)) {
return 0;
} else {
ret = k_zync(Z_PAIR_ZYNC(zp), Z_PAIR_ATOM(zp),
false, mod, timeout);
}

retry = mod < 0 && ret == 0;
if (retry) {
if (ticking) {
int64_t dt = k_uptime_ticks() - start;

if (!IS_ENABLED(CONFIG_TIMEOUT_64BIT)) {
timeout = Z_TIMEOUT_TICKS(t0 - dt);
}
if (dt <= 0) {
retry = false;
}
} else {
retry = forever;
}
}
} while (retry);

/* Infuriating historical API requirements in test suite */
if (ret == 0) {
ret = -EAGAIN;
}
if (ret == -EAGAIN && K_TIMEOUT_EQ(timeout, Z_TIMEOUT_NO_WAIT)) {
ret = -EBUSY;
}
return ret < 0 ? ret : 0;
}

/**
* @defgroup mutex_apis Mutex APIs
* @ingroup kernel_apis
Expand Down
26 changes: 0 additions & 26 deletions include/zephyr/sys/zync.h
Original file line number Diff line number Diff line change
Expand Up @@ -343,32 +343,6 @@ struct z_zync_pair {
__syscall int32_t z_pzync(struct k_zync *zync, int32_t mod, k_timeout_t timeout);
__syscall void z_pzync_init(struct z_zync_pair *zp, struct k_zync_cfg *cfg);

static inline int32_t z_pzyncmod(struct z_zync_pair *zp, int32_t mod,
k_timeout_t timeout)
{
int32_t ret;

do {
if (IS_ENABLED(Z_ZYNC_ALWAYS_KERNEL)) {
ret = z_pzync(Z_PAIR_ZYNC(zp), mod, timeout);
} else if (k_zync_try_mod(Z_PAIR_ATOM(zp), mod)) {
return 0;
} else {
ret = k_zync(Z_PAIR_ZYNC(zp), Z_PAIR_ATOM(zp),
false, mod, timeout);
}
} while (mod < 0 && K_TIMEOUT_EQ(timeout, Z_FOREVER) && ret == 0);

/* Infuriating historical API requirements in test suite */
if (ret == 0) {
ret = -EAGAIN;
}
if (ret == -EAGAIN && K_TIMEOUT_EQ(timeout, Z_TIMEOUT_NO_WAIT)) {
ret = -EBUSY;
}
return ret < 0 ? ret : 0;
}

/* Low level "wait on condition variable" utility. Atomically: sets
* the "mut" zync to 1, wakes up a waiting thread if there is one, and
* pends on the "cv" zync. Unlike k_condvar_wait() it does not
Expand Down
13 changes: 13 additions & 0 deletions kernel/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,19 @@ config ZYNC_LEGACY
Very few applications depend on this older behavior and most
should select the various features individually.

config ZYNC_STRICT_TIMEOUTS
bool "Add retries to k_zync-based timeouts"
help
When set, zync-wrapped IPC primitives like k_sem and k_mutex
will have a timeout-sensitive retry loop placed around their
k_zync() invocation. This will force them to wait for the
specified time even in circumstances (like being
suspended/restarted, or having their intended atom count
"stolen" by a higher priority thread) where k_zync would
naturally return early with -EAGAIN. Optional; most code
should be prepared to handle -EAGAIN on its own, where the
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? Are there other RTOSes where the caller must be prepared to handle something like -EAGAIN?

app can make a better choice as to what to do.

menu "Kernel Debugging and Metrics"

config INIT_STACKS
Expand Down