Discussion:
[rust-dev] Rust and real-time audio
David Henningsson
2014-10-08 05:49:26 UTC
Permalink
Hi,

I'm curious about the possibilities to use Rust for programming
real-time audio stuff. Usually one has one small task that runs in high
priority, and everything else is handled by a main task.

I have a few questions related to this:

1) The real-time audio task should never block when not expected to,
so stuff like malloc() is forbidden. Is there a way I can mark a
section/module/crate/something of the code as "real time safe", and thus
get warnings or errors in case I try to do something that would require
heap allocation or other blocking stuff?
The rest of the code (i e the main task) should still be able to use the
entire libstd.

2) The real-time audio thread might want to receive messages as well.
Are channels suitable for this, or are the complications that cause
things to be problematic here?

3) When using e g ALSA as your audio API, you usually block waiting on
a file descriptor. I was wondering if one would be able to select
between ALSA's fd and the channel, thus the blocking part of the
real-time thread would look something like:

select! (
command = rx.recv() => handle_command_from_main_thread(command),
() = alsa.wait_for_avail() => alsa.write_more_audio_to_buffer()
)

...where alsa.wait_for_avail() would somehow tell rust that it should
block on ALSA's file descriptor in addition to other things (such as
messages on the channel).

If it matters, assume native threads (i e, not green threads).

// David
Allen Welkie
2014-10-08 11:02:50 UTC
Permalink
For your first question, you could enable the "owned-heap-memory" warning
as an error for the crate in which you want to avoid heap memory. If this
doesn't do exactly what you want, you may be able to write your own lint to
do what you want http://doc.rust-lang.org/rustc/lint/
Hi,
I'm curious about the possibilities to use Rust for programming real-time
audio stuff. Usually one has one small task that runs in high priority, and
everything else is handled by a main task.
1) The real-time audio task should never block when not expected to, so
stuff like malloc() is forbidden. Is there a way I can mark a
section/module/crate/something of the code as "real time safe", and thus
get warnings or errors in case I try to do something that would require
heap allocation or other blocking stuff?
The rest of the code (i e the main task) should still be able to use the
entire libstd.
2) The real-time audio thread might want to receive messages as well. Are
channels suitable for this, or are the complications that cause things to
be problematic here?
3) When using e g ALSA as your audio API, you usually block waiting on a
file descriptor. I was wondering if one would be able to select between
ALSA's fd and the channel, thus the blocking part of the real-time thread
select! (
command = rx.recv() => handle_command_from_main_thread(command),
() = alsa.wait_for_avail() => alsa.write_more_audio_to_buffer()
)
...where alsa.wait_for_avail() would somehow tell rust that it should
block on ALSA's file descriptor in addition to other things (such as
messages on the channel).
If it matters, assume native threads (i e, not green threads).
// David
_______________________________________________
Rust-dev mailing list
Rust-dev at mozilla.org
https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20141008/4e725155/attachment.html>
David Henningsson
2014-10-08 12:05:03 UTC
Permalink
This post might be inappropriate. Click to display it.
David Henningsson
2014-10-13 10:47:46 UTC
Permalink
Post by David Henningsson
Hi,
I'm curious about the possibilities to use Rust for programming
real-time audio stuff. Usually one has one small task that runs in
high priority, and everything else is handled by a main task.
1) The real-time audio task should never block when not expected to,
so stuff like malloc() is forbidden. Is there a way I can mark a
section/module/crate/something of the code as "real time safe", and
thus get warnings or errors in case I try to do something that would
require heap allocation or other blocking stuff?
The rest of the code (i e the main task) should still be able to use
the entire libstd.
It seems to me like one option could be to do this runtime, by switching
the allocator (this should be possible, right?) to one that checks the
thread context first and fails (or emits a warning) in case we're
currently in a hard real-time safe thread/mode.
Post by David Henningsson
2) The real-time audio thread might want to receive messages as well.
Are channels suitable for this, or are the complications that cause
things to be problematic here?
So after having looked through the code, I think I can answer the two
remaining one myself (but feel free to correct me if I'm wrong here) :

It looks like this *might* be problematic in the sense that there
*might* be heap memory allocation involved when sending things over the
channel. But it seems to recycle the memory by keeping a list of "unused
list items". So it was not designed for hard real-time usage.
Post by David Henningsson
3) When using e g ALSA as your audio API, you usually block waiting
on a file descriptor. I was wondering if one would be able to select
between ALSA's fd and the channel, thus the blocking part of the
select! (
command = rx.recv() => handle_command_from_main_thread(command),
() = alsa.wait_for_avail() => alsa.write_more_audio_to_buffer()
)
...where alsa.wait_for_avail() would somehow tell rust that it should
block on ALSA's file descriptor in addition to other things (such as
messages on the channel).
If it matters, assume native threads (i e, not green threads).
The answer is "no, not as the runtime is currently designed". When a
task deschedules, it seems to wait on a mutex or semaphore. It is not
waiting for file descriptors (like the other mainloops I've seen on Linux).

If it were, it would provide a more flexible approach, including waiting
for pipes, sockets, etc. And eventfds could replace the mutex/semaphore
currently used for channels. It would be interesting to know if there
was a difference in performance though.

// David
David Henningsson
2014-10-13 10:45:19 UTC
Permalink
Post by David Henningsson
Hi,
I'm curious about the possibilities to use Rust for programming
real-time audio stuff. Usually one has one small task that runs in
high priority, and everything else is handled by a main task.
1) The real-time audio task should never block when not expected to,
so stuff like malloc() is forbidden. Is there a way I can mark a
section/module/crate/something of the code as "real time safe", and
thus get warnings or errors in case I try to do something that would
require heap allocation or other blocking stuff?
The rest of the code (i e the main task) should still be able to use
the entire libstd.
It seems to me like one option could be to do this runtime, by switching
the allocator (this should be possible, right?) to one that checks the
thread context first and fails (or emits a warning) in case we're
currently in a hard real-time safe thread/mode.
Post by David Henningsson
2) The real-time audio thread might want to receive messages as well.
Are channels suitable for this, or are the complications that cause
things to be problematic here?
So after having looked through the code, I think I can answer the two
remaining one myself (but feel free to correct me if I'm wrong here) :

It looks like this *might* be problematic in the sense that there
*might* be heap memory allocation involved when sending things over the
channel. But it seems to recycle the memory by keeping a list of "unused
list items". So it was not designed for hard real-time usage.
Post by David Henningsson
3) When using e g ALSA as your audio API, you usually block waiting
on a file descriptor. I was wondering if one would be able to select
between ALSA's fd and the channel, thus the blocking part of the
select! (
command = rx.recv() => handle_command_from_main_thread(command),
() = alsa.wait_for_avail() => alsa.write_more_audio_to_buffer()
)
...where alsa.wait_for_avail() would somehow tell rust that it should
block on ALSA's file descriptor in addition to other things (such as
messages on the channel).
If it matters, assume native threads (i e, not green threads).
The answer is "no, not as the runtime is currently designed". When a
task deschedules, it seems to wait on a mutex or semaphore. It is not
waiting for file descriptors (like the other mainloops I've seen on Linux).

If it were, it would provide a more flexible approach, including waiting
for pipes, sockets, etc. And eventfds could replace the mutex/semaphore
currently used for channels. It would be interesting to know if there
was a difference in performance though.

// David
Ilya Dmitrichenko
2014-10-14 08:43:33 UTC
Permalink
It would make sense to suggest that a Real-time Runtime would be an
interesting project to consider.

I also think that may be one could attempt implementing an audio engine on
a bare-metal chip, like an MCU. For that purpose there is Zinc project to
look into, which already supports some Cortex-M4 devices, which are great
for DSP. Perhaps a device with audio peripherals would have to be found and
drivers may need to be implemented, but this is probably okay to do
considering that such project would leverage Rust's ability to run on
bare-silicon, as well as study it's suitability for real-time applications
without burden of latency caused by general purpose OS.
On 13 Oct 2014 17:35, "David Henningsson" <david.henningsson at canonical.com>
Post by David Henningsson
Hi,
I'm curious about the possibilities to use Rust for programming real-time
audio stuff. Usually one has one small task that runs in high priority, and
everything else is handled by a main task.
1) The real-time audio task should never block when not expected to, so
stuff like malloc() is forbidden. Is there a way I can mark a
section/module/crate/something of the code as "real time safe", and thus
get warnings or errors in case I try to do something that would require
heap allocation or other blocking stuff?
The rest of the code (i e the main task) should still be able to use the
entire libstd.
It seems to me like one option could be to do this runtime, by switching
the allocator (this should be possible, right?) to one that checks the
thread context first and fails (or emits a warning) in case we're currently
in a hard real-time safe thread/mode.
2) The real-time audio thread might want to receive messages as well.
Are channels suitable for this, or are the complications that cause things
to be problematic here?
So after having looked through the code, I think I can answer the two
It looks like this *might* be problematic in the sense that there *might*
be heap memory allocation involved when sending things over the channel.
But it seems to recycle the memory by keeping a list of "unused list
items". So it was not designed for hard real-time usage.
3) When using e g ALSA as your audio API, you usually block waiting on a
file descriptor. I was wondering if one would be able to select between
ALSA's fd and the channel, thus the blocking part of the real-time thread
select! (
command = rx.recv() => handle_command_from_main_thread(command),
() = alsa.wait_for_avail() => alsa.write_more_audio_to_buffer()
)
...where alsa.wait_for_avail() would somehow tell rust that it should
block on ALSA's file descriptor in addition to other things (such as
messages on the channel).
If it matters, assume native threads (i e, not green threads).
The answer is "no, not as the runtime is currently designed". When a task
deschedules, it seems to wait on a mutex or semaphore. It is not waiting
for file descriptors (like the other mainloops I've seen on Linux).
If it were, it would provide a more flexible approach, including waiting
for pipes, sockets, etc. And eventfds could replace the mutex/semaphore
currently used for channels. It would be interesting to know if there was a
difference in performance though.
// David
_______________________________________________
Rust-dev mailing list
Rust-dev at mozilla.org
https://mail.mozilla.org/listinfo/rust-dev
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/rust-dev/attachments/20141014/3355a778/attachment.html>
Loading...