The spinlock validation isn't super lightweight -- it adds only a few
tens of bytess per call, but there are a LOT of locking calls. On
smaller platforms with 32kb of flash, we're bumping into code size
limits on the bigger tests (tests/kernel/poll is a particular
offender).
Check the declared flash size before enabling it.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Spinlocks are written above the arch-provided _arch_irq_un/lock()
calls. But those aren't stubbed by the mocking layer, and as it's not
an "arch" I don't see an obvious place to put them. Handle them in
spinlock.h.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
The validation checking recently added to spinlocks is useful, but
requires kernel-internals like _current and _current_cpu in a header
context that tends to be needed before those are declared (or where we
don't want them declared), and is causing big header dependency
headaches.
Move it to C code, it's just a validation tool, not a performance
thing.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
We want a _Swap() variant that can atomically release/restore a
spinlock state in addition to the legacy irqlock. The function as it
was is now named "_Swap_irqlock()", while _Swap() now refers to a
spinlock and takes two arguments. The former will be going away once
existing users (not that many! Swap() is an internal API, and the
long port away from legacy irqlocking is going to be happening mostly
in drivers) are ported to spinlocks.
Obviously on uniprocessor setups, these produce identical code. But
SMP requires that the correct API be used to maintain the global lock.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Something is going wrong with code generation here, potentially the
inline assembly generated by _arch_irq_un/lock(), and these calls are
not being inlined by gcc. So what should be a ~3 instruction sequence
on most uniprocessor architectures is turning into 8-20 cycles worth
of work to implement the API as written.
Use an ALWAYS_INLINE, which is sort of ugly semantically but produces
much better code.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
There was an existing validation layer in the spinlock implementation,
but it was only enabled when both SMP and CONFIG_DEBUG were enabled,
which meant that nothing was using it. Replace it with a more
elaborate framework that ensures that every lock taken is not already
taken by the current CPU and is released on the same CPU by the same
thread.
This catches the much more common goof of locking a spinlock
recursively, which would "work" on uniprocessor setups but have the
side effect of releasing the lock prematurely at the end of the inner
lock. We've done that in two spots already.
Note that this patch causes k_spinlock_t to have non-zero size on
builds with CONFIG_ASSERT, so expect a little data and code size
increase. Worth it IMHO.
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
Any word started with underscore followed by and uppercase letter or a
second underscore is a reserved word according with C99.
Signed-off-by: Flavio Ceolin <flavio.ceolin@intel.com>
Minimal spinlock API based on the existing atomic.h layer. Usage
works just like irq_lock(), but takes an argument to a specific struct
k_spinlock_t to un/lock. No attempt at implementing fairness or
backoff semantics. No attempt made at architecture-specific assembly.
When CONFIG_SMP is not enabled, this code falls back to a zero-size
struct and becomes functionally identical to irq_lock/unlock().
Signed-off-by: Andy Ross <andrew.j.ross@intel.com>