Commit Graph

2699 Commits

Author SHA1 Message Date
Gerard Marull-Paretas
4863c5f05b sys/util: extend usage of DIV_ROUND_UP
Many areas of Zephyr divide and round up without using the DIV_ROUND_UP
macro. Make use of it, so that we make use of a tested system macro and
at the same time we make code more readable.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2023-04-12 16:42:29 +02:00
Gerard Marull-Paretas
a5fd0d184a init: remove the need for a dummy device pointer in SYS_INIT functions
The init infrastructure, found in `init.h`, is currently used by:

- `SYS_INIT`: to call functions before `main`
- `DEVICE_*`: to initialize devices

They are all sorted according to an initialization level + a priority.
`SYS_INIT` calls are really orthogonal to devices, however, the required
function signature requires a `const struct device *dev` as a first
argument. The only reason for that is because the same init machinery is
used by devices, so we have something like:

```c
struct init_entry {
	int (*init)(const struct device *dev);
	/* only set by DEVICE_*, otherwise NULL */
	const struct device *dev;
}
```

As a result, we end up with such weird/ugly pattern:

```c
static int my_init(const struct device *dev)
{
	/* always NULL! add ARG_UNUSED to avoid compiler warning */
	ARG_UNUSED(dev);
	...
}
```

This is really a result of poor internals isolation. This patch proposes
a to make init entries more flexible so that they can accept sytem
initialization calls like this:

```c
static int my_init(void)
{
	...
}
```

This is achieved using a union:

```c
union init_function {
	/* for SYS_INIT, used when init_entry.dev == NULL */
	int (*sys)(void);
	/* for DEVICE*, used when init_entry.dev != NULL */
	int (*dev)(const struct device *dev);
};

struct init_entry {
	/* stores init function (either for SYS_INIT or DEVICE*)
	union init_function init_fn;
	/* stores device pointer for DEVICE*, NULL for SYS_INIT. Allows
	 * to know which union entry to call.
	 */
	const struct device *dev;
}
```

This solution **does not increase ROM usage**, and allows to offer clean
public APIs for both SYS_INIT and DEVICE*. Note that however, init
machinery keeps a coupling with devices.

**NOTE**: This is a breaking change! All `SYS_INIT` functions will need
to be converted to the new signature. See the script offered in the
following commit.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>

init: convert SYS_INIT functions to the new signature

Conversion scripted using scripts/utils/migrate_sys_init.py.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>

manifest: update projects for SYS_INIT changes

Update modules with updated SYS_INIT calls:

- hal_ti
- lvgl
- sof
- TraceRecorderSource

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>

tests: devicetree: devices: adjust test

Adjust test according to the recently introduced SYS_INIT
infrastructure.

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>

tests: kernel: threads: adjust SYS_INIT call

Adjust to the new signature: int (*init_fn)(void);

Signed-off-by: Gerard Marull-Paretas <gerard.marull@nordicsemi.no>
2023-04-12 14:28:07 +00:00
Kumar Gala
0722b6f74f smp: Add BUILD_ASSERT to make sure Kconfig values are the same
Add check to ensure that CONFIG_MP_NUM_CPUS and CONFIG_MP_MAX_NUM_CPUS
are set the same.  This will at least cause a build issue for out of
tree users.

Signed-off-by: Kumar Gala <kumar.gala@intel.com>
2023-04-07 13:13:23 +02:00
Nicolas Pitre
524ac8a29a sched: don't call k_sched_time_slice_set() during early init
All we really want here is to set default parameters. However
k_sched_time_slice_set() also calls z_reset_time_slice(_current)
which expects `_current` to be fully initialized.

Simply initialize `slice_ticks` and `slice_max_prio` with default values
directly. Unfortunately the compiler isn't smart enough to expand
k_ms_to_ticks_ceil32(CONFIG_TIMESLICE_SIZE) to a constant expression
at build time so we must do the conversion by hand (and it shouldn't
overflow due to the nature of the value).

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2023-04-03 19:16:48 -04:00
Nicolas Pitre
405611dc9e sched: remove restriction on single-tick time slices
Slice expirations are now based on the same timeout mechanism as
regular timers which have been recently fixed and proven to work with
single-tick periods.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2023-04-03 19:16:48 -04:00
Nicolas Pitre
907eea07f2 z_sched_init: don't use arch_num_cpus()
The reason for arch_num_cpus() is to be able to dynamically adapt to
the actual number of available CPUs at run time.

In the z_sched_init() case, it is not the number of active CPUs that
we need but rather the total number of potential CPUs, and that is
represented by CONFIG_MP_MAX_NUM_CPUS not arch_num_cpus().

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2023-04-03 12:36:30 -04:00
Jordan Yates
db3d51bb7d pm: device_runtime: add zephyr,pm-device-runtime-auto
Add the `zephyr,pm-device-runtime-auto` flag to `pm.yaml` and
`struct pm_device`.

This flag is intended to signify to the boot system that device runtime
PM should be automatically enabled on the device after the init function
has run.

Only run `pm_device_runtime_auto_enable` function on a device if
initialisation succeeded. This prevents actions being run on devices
that are not ready.

Signed-off-by: Jordan Yates <jordan.yates@data61.csiro.au>
2023-03-29 12:21:13 -04:00
Nicolas Pitre
5879d2d6c1 sched: minor time slicing cleanup
Make sliceable() the actual condition for a sliceable thread. Avoid
creating a slice timeout for non sliceable threads. Always reset
slice_expired even if the next thread is not sliceable. Fold
slice_expired_locked() into z_time_slice() to avoid the hidden
unlock/lock. Change `curr` to `thread` as this is not necessarily
the current thread (yet) being set. Make variables static.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2023-03-16 09:16:59 +01:00
Aastha Grover
877fc3d508 kernel: events: fix waitq timeout race condition
Updates events to prevent a timeout from corrupting the list of
threads that needs to be waken up.

Signed-off-by: Aastha Grover <aastha.grover@intel.com>
2023-03-09 09:22:21 +01:00
Aastha Grover
5537776898 kernel: Add z_sched_wake_thread API
This API wakes up a given thread and is also called from
z_thread_timeout()

Signed-off-by: Aastha Grover <aastha.grover@intel.com>
2023-03-09 09:22:21 +01:00
Aastha Grover
a2dccf1283 kernel: events: fix walking the waitq race condition
Fixes race condition for k_event_post_internal() in an
SMP environment while walking the waitq. Uses z_sched_waitq_walk()
to safely walk the waitq by using a sched_spinlock.
It should be noted that since walking the wait queue is an
operation of indeterminant length, there exists the possibility
that the sched_spinlock (which is a highly used and contended-for
lock) may be locked for an indeterminant amount of time. However,
it is expected that few threads will be waiting on any given kernel
event object, which should ameliorate this risk.

Fixes #54317

Signed-off-by: Aastha Grover <aastha.grover@intel.com>
2023-03-09 09:22:21 +01:00
Andy Ross
c5c3ad95de kernel/sched: Close hole with cross-core timeslice expirations
Moving timeslice events to timeouts isn't quite enough on SMP, as it's
still possible for systems that don't broadcast their timer interrupts
to end up handling an expiration for a foreign CPU.  There, we need an
IPI, and a symmetric call to z_time_slice() (which is itempotent and
fast) in the IPI ISR.

Signed-off-by: Andy Ross <andyross@google.com>
2023-03-09 09:21:12 +01:00
Andy Ross
f3afd5a4c9 kernel/sched: Use kernel timeouts for timeslice expirations
Rework the fragile and ad-hoc computation of timeslice expirations
into per-CPU struct _timeout objects with regular callbacks.  The
expiration callbacks themselves simply set a per-cpu flag (they might
run on any CPU), which gets checked at the end of the timer ISR on
every CPU.

This simplifies logic and removes a bunch of code.  It also fixes at
least three bugs:

1. As @npitre discovered: On SMP, the number of ticks announced on any
given CPU is going to be a subset of all expired ticks.  This broke
the accounting of timeslice ticks, and effectively meant that
timeslicing only worked on SMP on systems where one CPU could hog all
the announcements, and only on that CPU.

2. The bootstrap path to arm the timer driver after setting the first
timeout in an empty list couldn't take into account
sys_clock_elapsed() ticks, as it didn't know whether it was being
called underneath an existing announce loop.  Now this code is no
longer responsible for knowing anything about time slicing at all.

3. Also on SMP, there was a case where two CPUs timeslicing
simultaneously could stomp on each others' timeouts in
z_set_timeout_expiry(), as neither had a way of knowing what the
other's state was.  CPUs could miss their own expiration and have to
wait for the slice expiration on the other CPU.  Now, timeouts are
global objects with simple expiration times, and there's no need for
that function at all.

Signed-off-by: Andy Ross <andyross@google.com>
2023-03-09 09:21:12 +01:00
Peter Mitsis
a06f9ac418 kernel: Remove unused derived offset symbols
Some of the offset symbols that are derived from the macro
GEN_OFFSET_SYM() are not used anywhere in the Zephyr codebase.
Remove them as part of a cleanup effort.

Instances of an associated GEN_OFFSET_SYM() have also been
removed when the resulting macro is no longer referenced.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-22 16:01:32 +01:00
Peter Mitsis
fa23eb49b3 kernel: Remove unused generated offset symbols
Some of the offset symbols generated via the macro GEN_OFFSET_SYM()
are not used anywhere in the Zephyr codebase. Remove them as part of
a cleanup effort.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-22 16:01:32 +01:00
Nicolas Pitre
6a51a10dec kernel/timer: fix period argument clamp handling
Commit 3e729b2b1c ("kernel/timer: Correctly clamp period argument")
increased the lower limit to 1 so that it wouldn't conflict with a
K_NO_WAIT. But in doing so it enforced a minimum period of 2 ticks.
And the subtraction must obviously be avoided if the period is zero, etc.

Instead of doing this masquerade in k_timer_start(), let's move the
subtraction and clamping in z_timer_expiration_handler() right before
registering a new timeout. It makes the code cleaner, and then it is
possible to have single-tick periods again.

Whith this, timer_jitter_drift in tests/kernel/timer/timer_behavior does
pass with any CONFIG_SYS_CLOCK_TICKS_PER_SEC value, even when the tick
period is equal or larger than the specified timer period for the test
which failed the test before.

Signed-off-by: Nicolas Pitre <npitre@baylibre.com>
2023-02-20 09:52:53 +01:00
Andy Ross
d00f9b594b kernel/work: Fix race under with delayed work item cancellation
The call to unschedule_locked() would return true ("successfully
unscheduled") even in the case where the underlying z_abort_timeout()
failed (because the callback was already unpended and
in-progress/complete/about-to-be-run, remember that timeout callbacks
are unsynchronized), leading to state bugs and races against the
callback behavior.

Correctly detect that case and propagate the error to the caller.

Fixes #51872

Signed-off-by: Andy Ross <andyross@google.com>
2023-02-11 12:14:16 +09:00
Peter Mitsis
1b49cd2551 kernel: pipes: ISRs use a private pipe descriptor
Fixes sporadic data access violations that were occuring when pipes
were being used from an ISR. The ISR was incorrectly using the pipe
descriptor belonging to the interrupted thread. This led to corrupted
pipe meta-data. The solution proposed here is to perform a run-time
check and if use a pipe descriptor on the ISR's stack if called from
an ISR.

For additional information, see:
   https://github.com/zephyrproject-rtos/zephyr/issues/52812

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-11 06:45:13 +09:00
Peter Mitsis
59cb96e802 kernel: pipes: Add spin lock/unlock barrier pair
Adds a spin lock/unlock barrier pair after a pipe thread wakes.
After the list of waiting threads is generated, it is possible for
threads on that list to timeout and be removed from the wait queue.
However, since that list was generated before the timeout occurred,
the timed-out thread must wait until the copying is done (the
pipe's spin-lock has been released).

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-11 06:45:13 +09:00
Peter Mitsis
31dfd84fd5 kernel: pipes: Change method of unpending waiters
By the time the working list of readers/writers is processed, it is
possible that waiting reader/writer being processed had timed out
and is no longer on the wait queue. As such, we can not blindly
wake the next thread as that next thread might not be the thread we
had just been processing.

To address this, the calls to z_sched_wake() have been replaced
with z_unpend_thread() and z_ready_thread() so that a specific
thread can be safely targeted for waking.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-11 06:45:13 +09:00
Peter Mitsis
0037712e68 kernel: pipes: use wait queue walker to build list
Uses the new z_sched_waitq_walk() routine to walk the pipe's wait
queue to build a list of waiting threads that will be used for
the data transfer.

This method is preferred over the previous as it ensures that
wait queue is safely traversed.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-11 06:45:13 +09:00
Peter Mitsis
ca58339e16 kernel: Add routine to walk a wait queue
Adds a routine to safely walk a specified wait queue and invoke a
custom callback function on each waiting thread.

Signed-off-by: Peter Mitsis <peter.mitsis@intel.com>
2023-02-11 06:45:13 +09:00
Andrzej Głąbek
e60af79268 kernel: timer: Eliminate a race condition in expiration handling
When a timer is restarted from a high priority interrupt, it may
happen that the timer is re-added to the timeout list right after
it is removed from that list prior to execution of its expiration
handler but before that execution actually occurs. This leads to
an assertion failure reported for `z_add_timeout()` because then
that function, called from `z_timer_expiration_handler()` for
periodic timers, turns out to be adding a timeout that is already
added to the timeout list.
This commit detects such situation in `z_timer_expiration_handler()`
and makes that function exit immediately when that occurs (as the
timer was restared, its expiration handler should not be executed).

Signed-off-by: Andrzej Głąbek <andrzej.glabek@nordicsemi.no>
2023-02-08 10:17:56 +01:00
romain pelletant
14bcc859ca kernel: k_msgq: add peek at function
Make message queue able to peek data at the specified index.
Related to issue #53360

Signed-off-by: romain pelletant <romainp@kickmaker.net>
2023-01-26 10:00:29 +00:00
Daniel Leung
256db60ebf kernel: mark z_cstart to not have stack protector
Most of the time, z_cstart() is running on an arbitrary region
of memory as stack, where the necessary stack setup has not been
performed. This prevents stack protection to work correctly,
as the stack canary has not been populated. So mark z_cstart()
to have no stack protection at all inside the function to avoid
raising exception during boot.

Signed-off-by: Daniel Leung <daniel.leung@intel.com>
2023-01-24 13:04:45 -05:00