-
Totally reworked the Mutex API to further improve robustness in the face of cancellation.
- The basic locking operation
lock
(and its friendtry_lock
) now return a "permit" that can be used to do one synchronous thing to the guarded data. (This operation was namedperform
/try_perform
in 0.3.) - If you need to access the guarded data on either side of an
await
point, thelock_assuming_cancel_safe
operation becomes available if you opt-in. (This operation was namedlock
in all prior versions, but was renamed to make it harder to grab by accident and easier to spot in code review.)
- The basic locking operation
-
Removed operations that were marked as deprecated during the 0.3.0 series:
spsc::Push::push
. -
The
handoff
module is no longer available by default. If you want it, request it by enabling the thehandoff
Cargo feature. (It's incredibly useful, but has some gotchas, so I wanted to make it a little harder to reach.)
-
Fixed bug that meant
mutex
wouldn't build if you didn't also havehandoff
enabled. Applications relying on default features wouldn't hit this since they're both on by default. -
Added
exec::with_deadline
andexec::with_timeout
, more convenient methods for time-limiting the execution of a future. Compared to the traditional method of usingselect_biased!
, these functions are significantly less verbose, more obvious, and produce smaller code too. This also relieves applications from depending on thefutures
crate for timeouts if they don't want to.
- Fix bug in
handoff
when built withoutdebug_assertions
-- I introduced this in 0.3.4 in my code size "improvements." This has demonstrated the need to build the examples in both release and debug modes for coverage.
-
Changed the lifetimes on the
reserve
operation onspsc::Push
. The original definition allowed for an unlikely but easily reachable deadlock, where code could simultaneously wait for two permits from the same queue -- the second permit will never arrive. I consider this a bug fix, and it won't break code unless that code contains a deadlock, so I'm including this in a minor rev. Currently not planning on yanking 0.3.3. -
Further code size improvements.
- Fixed a bug I introduced into
yield_cpu
in 0.3.1. Please move away from 0.3.1/0.3.2 at your convenience. No other changes in this release.
- Added explicit cancel safety annotations to all async/future operations.
Currently everything except
handoff
is either strict cancel-safe or deprecated! Yay. - Made certain implementation details cheaper on ARMv6-M.
- Took a pass over all the rustdoc and tidied things up. There are now more examples and stuff.
-
Based on watching people learning
async
, I'm adding a new operation tolilos::spsc::Push
:reserve
. This is similar to the oldpush
but resolves to aPermit
that lets you do the push synchronously. This lets you avoid losing data if cancelled, which is critical for building higher-level cancel-safe abstractions. Because I'm increasingly convinced of its danger, I have deprecatedlilos::spsc::Push::push
. Please usereserve
if you need to block:q.reserve().await.push(data);
-
lilos
no longer depends onfutures
, which may reduce your build times, and makes things easier to interpret in a debugger.
lilos
now supports the stable toolchain!
-
Minimum supported Rust version now 1.69 for various fixes.
-
Cortex-M0 CPUs are now fully supported, with a worked example for the RP2040 in
examples/rp2040
, and successful applications (not in this repo) on Nordic nRF52832 and STM32G0. (Note thatlilos
is not multi-CPU aware, so the second core on the RP2040 can run code but notlilos
tasks. Because very fewlilos
types areSend
, it should be hard to screw this up without effort.) -
All SysTick timer support is now behind a feature,
systick
, which is on by default. You can omit this if you're targeting a platform where the SysTick timer is stopped in the normal sleep/wait states, such as the Nordic nRF52832. Your application will need to use interrupts (including potentially interrupts from a replacement low-power timer) to handle all events. I'll post a worked example eventually. -
Upgraded to
cortex-m-rt
0.7.1; earlier 0.6-seriescortex-m-rt
crates don't reliably preserve stack alignment on startup, and must be avoided. (It would be nice if Cargo had something louder than yank in this case.) This is a user-visible change because you're responsible for linking in thecortex-m-rt
setup code into yourmain
routine -- make sure you're not using 0.6.
-
New STM32H7 UART echo example -- similar to the STM32F407 example, but on hardware you can buy! (Edit: ...aaaaand it's out of stock)
-
Changes to ensure that RLS/rust-analyzer work in examples.
-
OS APIs have given up on
never_type
ever stabilizing and switched to the awkwardly-named-but-stablecore::convert::Infallible
type. The main implication for programs: task futures should now have the typeasync fn my_task(arguments) -> Infallible
instead of-> !
. You can probably search-replace this. -
The
Mutex
API has changed to omit thelock
operation by default. I've decided the traditionallock
/MutexGuard
approach in async code makes it too easy to accidentally write cancel-incorrect abstractions. You now have to opt into the guard-based operations on aMutex
-by-Mutex
basis by replacingMutex<T>
withMutex<CancelSafe<T>>
-- but first try using theperform
operation instead. -
APIs relying on
core::time::Duration
have been switched over to a newlilos::time::Millis
type, withDuration
optionally supported where it makes sense. It turns out thatDuration
is internally structured such that essentially all operations require 64-bit (or 128-bit!) multiplication and/or division/remainder. This became really obvious on M0, which lacks any sort of division insruction. Switching away fromDuration
cuts several kiB off the size of the OS (which, depending on which features you're using, can be as much as 50-60%). -
The OS timestamp type has been renamed from
lilos::time::Ticks
tolilos::time::TickTime
because I kept feeling like "ticks" sounds like a measure of time duration, rather than a timestamp. With the introduction ofMillis
it started to seem really ambiguous, so, I changed it. -
Two significant API changes to
PeriodicGate
:-
PeriodicGate
is now created usingfrom
instead ofnew
, which lets it take either a cheapMillis
or an expensiveDuration
. (This is the main change required to port simple applications to 0.3 in my experience.) -
Added
PeriodicGate::new_shift
for setting up periodic timers out of phase with respect to one another. This is useful for e.g. scheduling a display refresh at 60 Hz, and scheduling serial communication to happen at exactly the same frequency but shifted so they don't compete (which was the motivating use case).
-
-
Notify::until
is now more powerful and can wait for abool
condition (its original use case), or for an operation returningOption
to returnSome
. In the latter case, it returns the contained value. As a result, the olduntil_some
has been removed -- change any uses of it to useuntil
. -
All public types in the OS now have
Debug
impls for your debug-printing pleasure. -
TickTime
can now be converted to and from au64
. -
The internal
atomic
module, containing "polyfill" atomic operations for portability between bigger cores and Cortex-M0, is nowpub
so applications can use it if desired.
mutex
macros now importPin
so you don't have to (whoops!).
- A bunch of code size optimizations for small processors.
- Switch to Rust 2021.
- Fix some uses of deprecated
cortex-m
API. - More aggressive warning settings.
- Use
unsafe_op_in_unsafe_fn
, which should really be Rust's default. - The repo is no longer a workspace, because builds in workspaces with
.cargo/config
files change behavior depending on which directory you're in, despite having all build targets available, and this keeps confusing me. - Example programs and OS internals have switched to the newly stabilized
core::pin::pin!
macro instead ofpin_utils
. You don't have to do this in your own programs, but I recommend it!
-
Add
handoff
(rendezvous) type, which can be much cheaper than a fullspsc
queue if you don't mind having the sender and receiver synchronize. -
No longer require the
inline-asm
feature fromcortex-m
. This is a visible change since it may affect your feature unification, but should not be a breaking change.
-
It became apparent that the original
queue
had soundness issues. Replacedqueue
withspsc
, a rewritten version that I'm more confident in. This has a very different API, so this is a breaking change.spsc
(single-producer single-consumer) is intended to distinguish it from other kinds of queues in the future. -
Both
spsc
(formerlyqueue
) andmutex
are now behind features, so you can opt into the parts of the system you need.
Initial public release of the "operating system" factored out of my LED controller project.
0.1.1 and 0.1.2 were only docs changes.