Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.arch.embedded > #28994 > unrolled thread
| Started by | pozz <pozzugno@gmail.com> |
|---|---|
| First post | 2020-01-03 14:41 +0100 |
| Last post | 2020-01-03 21:46 -0500 |
| Articles | 20 on this page of 74 — 15 participants |
Back to article view | Back to comp.arch.embedded
Task priorities in non strictly real-time systems pozz <pozzugno@gmail.com> - 2020-01-03 14:41 +0100
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-03 15:19 +0100
Re: Task priorities in non strictly real-time systems pozz <pozzugno@gmail.com> - 2020-01-05 01:25 +0100
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 13:32 -0600
Re: Task priorities in non strictly real-time systems Richard Damon <Richard@Damon-Family.org> - 2020-01-05 16:49 -0500
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 21:05 -0600
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-05 17:08 -0700
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 21:26 -0600
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-05 22:10 -0700
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-06 07:37 -0600
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-06 17:21 -0700
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-07 19:23 -0600
Re: Task priorities in non strictly real-time systems Richard Damon <Richard@Damon-Family.org> - 2020-01-06 20:36 -0500
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-07 01:38 -0600
Re: Task priorities in non strictly real-time systems Richard Damon <Richard@Damon-Family.org> - 2020-01-07 06:53 -0500
Re: Task priorities in non strictly real-time systems George Neuner <gneuner2@comcast.net> - 2020-01-06 07:13 -0500
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-07 10:11 +0100
Re: Task priorities in non strictly real-time systems Richard Damon <Richard@Damon-Family.org> - 2020-01-07 07:05 -0500
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-07 19:34 -0600
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-06 10:44 +0200
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-06 02:51 -0700
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-06 15:39 +0200
Re: Task priorities in non strictly real-time systems George Neuner <gneuner2@comcast.net> - 2020-01-06 13:29 -0500
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-06 14:38 -0700
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-07 07:05 +0200
Re: Task priorities in non strictly real-time systems George Neuner <gneuner2@comcast.net> - 2020-01-07 13:09 -0500
Re: Task priorities in non strictly real-time systems Dimiter_Popoff <dp@tgi-sci.com> - 2020-01-07 20:53 +0200
Re: Task priorities in non strictly real-time systems Clifford Heath <no.spam@please.net> - 2020-01-08 08:43 +1100
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-08 00:33 +0200
Re: Task priorities in non strictly real-time systems Dimiter_Popoff <dp@tgi-sci.com> - 2020-01-08 15:26 +0200
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-08 00:08 +0200
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-07 10:37 +0100
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-06 16:10 -0700
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-07 07:37 +0200
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-07 01:49 -0600
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-07 06:43 -0700
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-07 10:21 +0200
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-07 06:42 -0700
Re: Task priorities in non strictly real-time systems Richard Damon <Richard@Damon-Family.org> - 2020-01-07 22:23 -0500
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-09 22:07 +0200
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-07 10:54 +0200
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-07 06:43 -0700
Re: Task priorities in non strictly real-time systems Hans-Bernhard Bröker <HBBroeker@t-online.de> - 2020-01-06 18:01 +0100
Re: Task priorities in non strictly real-time systems Niklas Holsti <niklas.holsti@tidorum.invalid> - 2020-01-06 19:47 +0200
Re: Task priorities in non strictly real-time systems pozz <pozzugno@gmail.com> - 2020-01-05 01:58 +0100
Re: Task priorities in non strictly real-time systems Clifford Heath <no.spam@please.net> - 2020-01-05 14:26 +1100
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-05 11:21 +0200
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-05 14:07 +0100
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-05 17:46 +0200
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-05 19:08 +0100
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-05 13:56 +0100
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 13:39 -0600
Re: Task priorities in non strictly real-time systems Clifford Heath <no.spam@please.net> - 2020-01-06 07:44 +1100
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 21:00 -0600
Re: Task priorities in non strictly real-time systems Clifford Heath <no.spam@please.net> - 2020-01-06 14:50 +1100
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-06 07:12 -0600
Re: Task priorities in non strictly real-time systems Paul Rubin <no.email@nospam.invalid> - 2020-01-04 22:34 -0800
Re: Task priorities in non strictly real-time systems David Brown <david.brown@hesbynett.no> - 2020-01-05 14:12 +0100
Re: Task priorities in non strictly real-time systems Niklas Holsti <niklas.holsti@tidorum.invalid> - 2020-01-05 18:00 +0200
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 13:44 -0600
Re: Task priorities in non strictly real-time systems George Neuner <gneuner2@comcast.net> - 2020-01-06 14:52 -0500
Re: Task priorities in non strictly real-time systems George Neuner <gneuner2@comcast.net> - 2020-01-06 15:05 -0500
Re: Task priorities in non strictly real-time systems gtwrek@sonic.net (gtwrek) - 2020-01-06 22:41 +0000
Re: Task priorities in non strictly real-time systems Don Y <blockedofcourse@foo.invalid> - 2020-01-06 19:50 -0700
Re: Task priorities in non strictly real-time systems George Neuner <gneuner2@comcast.net> - 2020-01-07 13:26 -0500
Re: Task priorities in non strictly real-time systems Niklas Holsti <niklas.holsti@tidorum.invalid> - 2020-01-03 16:28 +0200
Re: Task priorities in non strictly real-time systems pozz <pozzugno@gmail.com> - 2020-01-05 01:37 +0100
Re: Task priorities in non strictly real-time systems Les Cargill <lcargill99@comcast.com> - 2020-01-05 13:46 -0600
Re: Task priorities in non strictly real-time systems Niklas Holsti <niklas.holsti@tidorum.invalid> - 2020-01-05 22:44 +0200
Re: Task priorities in non strictly real-time systems Rick C <gnuarm.deletethisbit@gmail.com> - 2020-01-03 11:49 -0800
Re: Task priorities in non strictly real-time systems upsidedown@downunder.com - 2020-01-03 22:51 +0200
Re: Task priorities in non strictly real-time systems pozz <pozzugno@gmail.com> - 2020-01-05 01:48 +0100
Re: Task priorities in non strictly real-time systems Joe Chisolm <jchisolm6@earthlink.net> - 2020-01-03 15:34 -0600
Re: Task priorities in non strictly real-time systems Richard Damon <Richard@Damon-Family.org> - 2020-01-03 21:46 -0500
Page 3 of 4 — ← Prev page 1 2 [3] 4 Next page →
| From | upsidedown@downunder.com |
|---|---|
| Date | 2020-01-07 10:54 +0200 |
| Message-ID | <85g81flnmgprie5meragkpopm61m62qr8n@4ax.com> |
| In reply to | #29043 |
On Mon, 6 Jan 2020 16:10:03 -0700, Don Y <blockedofcourse@foo.invalid>
wrote:
<description of simple RT kernel for 6809 with typically 6 to 12 tasks
skipped>
>>>> The scheduler checked the task state byte of each created task
>>>> (requiring just 3 instructions/task). If no new higher priority task
>>>> had become runnable, the scheduler performed a simple return from
>>>> interrupt restoring the registers from the local stack and the
>>>> suspended task was resumed.
>>>
>>> Deciding and picking can often be far more complicated actions.
>>> And, the criteria used to make that selection are often not simple
>>> (static?) priorities.
Assuming a task can be in a WAITING state (not READY), runnable
(READY) and actually RUNNING. The scheduler simply scans the priority
list in priority order and when it detects the first task in READY
state (or already RUNNING) execute that task. The scan omits all tasks
in WAITING state.
Only if a very large number (dozens) of tasks are expected to be in
WAITING state before detecting the first task in READY state it might
make sense to have a separate queue for READY or RUNNING tasks only
>> Why complicate things with dynamically changing priorities ? For
>> avoiding priority inversion or improve user responsiveness ? But as I
>
>I find the whole notion of "priorities" to be abhorrent. It suggests
>that you KNOW what the priorities SHOULD be -- as part of the DESIGN
>of the system.
Of course I know :-).
>In practice, they tend to be twiddled after-the-fact
>when things don't quite work as you'd HOPED (i.e., you screwed up
>the design and are now using a rejiggering of priorities to try to
>coax it into behaving the way you'd HOPED)
I may sometimes have to split a task that consumes more than expected
CPU time for its priority level into two task, moving the high time
requirement to a separate task and run it at a lower priority.
>When you assign arbitrary numeric values to impose an ordering on
>tasks ("relative importance"), do you prepare a formal justification
>for those choices? A *rationale* that defends your choices?
Of course I check the deadline requirement of each task before
assigning priorities. Those tasks without formal deadline requirement
can often be execute in the null task with lowest priority. This of
course requires that the average CPU load is well below 100 % so that
the null task is sometimes executed.
[toc] | [prev] | [next] | [standalone]
| From | Don Y <blockedofcourse@foo.invalid> |
|---|---|
| Date | 2020-01-07 06:43 -0700 |
| Message-ID | <qv21tl$14e$2@dont-email.me> |
| In reply to | #29056 |
On 1/7/2020 1:54 AM, upsidedown@downunder.com wrote:
> On Mon, 6 Jan 2020 16:10:03 -0700, Don Y <blockedofcourse@foo.invalid>
> wrote:
>
> <description of simple RT kernel for 6809 with typically 6 to 12 tasks
> skipped>
>
>>>>> The scheduler checked the task state byte of each created task
>>>>> (requiring just 3 instructions/task). If no new higher priority task
>>>>> had become runnable, the scheduler performed a simple return from
>>>>> interrupt restoring the registers from the local stack and the
>>>>> suspended task was resumed.
>>>>
>>>> Deciding and picking can often be far more complicated actions.
>>>> And, the criteria used to make that selection are often not simple
>>>> (static?) priorities.
>
> Assuming a task can be in a WAITING state (not READY), runnable
> (READY) and actually RUNNING. The scheduler simply scans the priority
> list in priority order and when it detects the first task in READY
> state (or already RUNNING) execute that task. The scan omits all tasks
> in WAITING state.
Something PUT those tasks into those states. Sort them into the
correct queues, by "priority", when *that* happens. In that way,
the decision time is made constant when you need to do a context switch.
> Only if a very large number (dozens) of tasks are expected to be in
> WAITING state before detecting the first task in READY state it might
> make sense to have a separate queue for READY or RUNNING tasks only
Do you *force* the developer NOT to have more than a certain number of
tasks? It's the use of these "simple" algorithms that don't scale well
that I consider as differentiating an RTOS from an MTOS.
>> In practice, they tend to be twiddled after-the-fact
>> when things don't quite work as you'd HOPED (i.e., you screwed up
>> the design and are now using a rejiggering of priorities to try to
>> coax it into behaving the way you'd HOPED)
>
> I may sometimes have to split a task that consumes more than expected
> CPU time for its priority level into two task, moving the high time
> requirement to a separate task and run it at a lower priority.
>
>> When you assign arbitrary numeric values to impose an ordering on
>> tasks ("relative importance"), do you prepare a formal justification
>> for those choices? A *rationale* that defends your choices?
>
> Of course I check the deadline requirement of each task before
> assigning priorities. Those tasks without formal deadline requirement
> can often be execute in the null task with lowest priority. This of
> course requires that the average CPU load is well below 100 % so that
> the null task is sometimes executed.
But deadlines vary, over time. This is why priorities are a bad fit
as a scheduling criteria. As a deadline approaches, do you tweek the
priority to ensure the task gets a chance to run?
"Lets make EVERYTHING louder than EVERYTHING else"
-- Deep Purple (?)
ACTUAL deadlines are relatively easy to grok. And, express numerically.
So, folks/developers can relate to the scheduler opting to run X instead
of Y at a particular time.
But, explaining why X should run at "3" while Y runs at "7" gets into a
lot of hand-waving ("What's running at 2? And 5? What about 8?")
I'm out. I only "dropped in" to verify that I had set up Thunderbird
correctly on this rebuilt machine. I have a fixed budget of time for
"correspondence" (my plate is *WAY* too full) and USENET burns up too
much for the benefit that it provides (me! :> )
As of this moment, it appears that I've not left any conversations in
which I was a participant "dangling".
Happy New Year!
[toc] | [prev] | [next] | [standalone]
| From | Hans-Bernhard Bröker <HBBroeker@t-online.de> |
|---|---|
| Date | 2020-01-06 18:01 +0100 |
| Message-ID | <h7h7fdFr0f8U1@mid.dfncis.de> |
| In reply to | #29021 |
Am 06.01.2020 um 01:08 schrieb Don Y: > Preemptive frameworks can be implemented in a variety of ways. > It need NOT mean that the processor can be pulled out from under > your feet at any "random" time. I think I have to disagree with that. Let's start with linguistics. To "preempt" means: to get in ahead of someone (or something) else. In the RT world, that something is a running task, and preemption happens when some other task gets to use the CPU before that task is done with it. I.e. a preemptive framework, pretty much by definition of the words, does pull the CPU out from under you, and that _will_ happen at, essentially, random times. If the running task can routinely (as opposed to exceptionally) avoid that happening to itself, that means it's essentially the other type of framework: a cooperative one. In other words: for the distinction of preemptive vs. cooperative multitasking to make any sense at all, it has to be about who routinely gets to decide whether task switching is allowed at any given time. If the decision normally is with individual tasks, that's cooperative. If it's centralized in the OS, that's preemptive. Now we in c.a.embedded don't usually get to make that distinction quite so cleanly of course, because for us, ISRs are a fact of life, and those are always preemptive. So purely cooperative multitasking is out. We only get to decide between largely cooperative systems with some preemptive task disturbing the "clean" picture, and almose purely preemptive system setups, with all the extra cost in terms of data exchange synchronization between tasks that entails. > So, barring "events" signalled by an ISR, you can conceivably > execute code inside a single task for DAYS and never lose control of > the processor. And still, when eventually you do lose it, the time when that happens is, for all practical intents and purposes, random. Because otherwise you wouldn't "lose" control, you'ld be "giving it up". In other words, in such a case the used RTOS framework may be preemptive, but you're not using it that way.
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2020-01-06 19:47 +0200 |
| Message-ID | <h7ha4pFrjcnU1@mid.individual.net> |
| In reply to | #29036 |
On 2020-01-06 19:01, Hans-Bernhard Bröker wrote:
> Am 06.01.2020 um 01:08 schrieb Don Y:
>
>> Preemptive frameworks can be implemented in a variety of ways.
>> It need NOT mean that the processor can be pulled out from under
>> your feet at any "random" time.
>
> I think I have to disagree with that.
>
> Let's start with linguistics. To "preempt" means: to get in ahead of
> someone (or something) else.
>
> In the RT world, that something is a running task, and preemption
> happens when some other task gets to use the CPU before that task is
> done with it. I.e. a preemptive framework, pretty much by definition of
> the words, does pull the CPU out from under you, and that _will_ happen
> at, essentially, random times.
>
> If the running task can routinely (as opposed to exceptionally) avoid
> that happening to itself, that means it's essentially the other type of
> framework: a cooperative one.
There are lots of intermediate ideas, "limited preemption" systems. See
"Limited Preemptive Scheduling for Real-Time Systems: a Survey", at
https://algo.ing.unimo.it/people/marko/papers/TII13.pdf
> Now we in c.a.embedded don't usually get to make that distinction quite
> so cleanly of course, because for us, ISRs are a fact of life, and those
> are always preemptive.
Except, of course, when the task that would be interrupted disables or
masks the interrupt(s) for a while, thus delaying the
interruption/preemption until later.
Some embedded programs run with all interrupts always disabled, and
instead poll for inputs and events.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | pozz <pozzugno@gmail.com> |
|---|---|
| Date | 2020-01-05 01:58 +0100 |
| Message-ID | <qurcak$puc$1@dont-email.me> |
| In reply to | #28995 |
Il 03/01/2020 15:19, David Brown ha scritto:
> With pre-emptive scheduling, you will have to go
> through your existing code and make very sure that you have locks or
> synchronisation in place for any shared resources or data.
As I already wrote many times, I don't have experience with RTOS and
task sync mechanism such as semaphores, locks, mutexes, message queues
and so on.
So I'm not able to understand when a sync is really needed.
Could you point on a good simple material to study (online or book)?
For example, many times I have a serial channel where soma data are
received. A frame parser decodes the "wire data" in variables, accessed
by other tasks.
while(1) {
serial_task(); // frame receiver/parser
main_task(); // uses variables touched by frame parser
}
Supposing all the variables are of type int (i.e., they are changed
atomically in serial_task()), should I need to protect them with locks,
because they are used by main_task() too?
I think lock isn't needed, except main_task() needs to have a coerent
data values for all the variables (all variables with new values or old
values).
[toc] | [prev] | [next] | [standalone]
| From | Clifford Heath <no.spam@please.net> |
|---|---|
| Date | 2020-01-05 14:26 +1100 |
| Message-ID | <qHcQF.22112$MS2.17419@fx19.iad> |
| In reply to | #29004 |
On 5/1/20 11:58 am, pozz wrote: > Il 03/01/2020 15:19, David Brown ha scritto: >> With pre-emptive scheduling, you will have to go >> through your existing code and make very sure that you have locks or >> synchronisation in place for any shared resources or data. > > As I already wrote many times, I don't have experience with RTOS and > task sync mechanism such as semaphores, locks, mutexes, message queues > and so on. > So I'm not able to understand when a sync is really needed. > Could you point on a good simple material to study (online or book)? I wish I could, but it is actually a frightfully difficult subject. Basically it's the same as thread-safe programming. Only about 1% of programmers think they can do it. Of those, only about 1% actually can. It's the 0.99% that you have to worry about. At least some of them for Toyota. Don't be one of them! However, this difficulty is precisely why Rust was created. Although I haven't yet done a project in Rust, I've done enough multi-threaded work in C++ to know that the ideas in Rust are a massive leap forwards, and anyone doing this kind of work (especially professionally) owes it to their users to learn it. > Supposing all the variables are of type int (i.e., they are changed > atomically in serial_task()), should I need to protect them with locks, > because they are used by main_task() too? If "int" is your CPUs word size, you are using word alignment, and you don't have multiple CPUs with separate caches accessing the same RAM, you're probably ok for individual variables. However you will come unstuck if you expect assignments and reads to be performed in the same order you wrote them. A modern compiler will freely re-order things in extremely ambitious and unexpected ways, in order to keep the pipeline flowing. I cannot emphasise this enough. The compiler will do what it can to make your program do what it thinks you have asked for - which will NOT be the same as what you think you have asked for. You need to understand about basic mutex operations, preferably also semaphores, and beyond that to read and write barriers (if you want to write lock-free code). It's a big subject. Clifford Heath.
[toc] | [prev] | [next] | [standalone]
| From | upsidedown@downunder.com |
|---|---|
| Date | 2020-01-05 11:21 +0200 |
| Message-ID | <7t531fpde9jlae0u0tos4o933mqpu3uluq@4ax.com> |
| In reply to | #29005 |
On Sun, 5 Jan 2020 14:26:12 +1100, Clifford Heath <no.spam@please.net> wrote: >On 5/1/20 11:58 am, pozz wrote: >> Il 03/01/2020 15:19, David Brown ha scritto: >>> With pre-emptive scheduling, you will have to go >>> through your existing code and make very sure that you have locks or >>> synchronisation in place for any shared resources or data. >> >> As I already wrote many times, I don't have experience with RTOS and >> task sync mechanism such as semaphores, locks, mutexes, message queues >> and so on. >> So I'm not able to understand when a sync is really needed. >> Could you point on a good simple material to study (online or book)? > >I wish I could, but it is actually a frightfully difficult subject. >Basically it's the same as thread-safe programming. >Only about 1% of programmers think they can do it. >Of those, only about 1% actually can. > >It's the 0.99% that you have to worry about. At least some of them for >Toyota. Don't be one of them! > >However, this difficulty is precisely why Rust was created. Although I >haven't yet done a project in Rust, I've done enough multi-threaded work >in C++ to know that the ideas in Rust are a massive leap forwards, and >anyone doing this kind of work (especially professionally) owes it to >their users to learn it. > >> Supposing all the variables are of type int (i.e., they are changed >> atomically in serial_task()), should I need to protect them with locks, >> because they are used by main_task() too? You may need some double buffering in one form or another. Assuming you have a receiver byte buffer that can take a full serial message and a structure of integers that will receive the values decoded from the message. When the serial task notices the end of a message. it immediately decodes the values into the integers in the struct. After this, the serial byte buffer is ready to start receiving the next message.The serial task can then inform the main task that new data is in the integer structure and main task can copy it to local variables. Alternatively, if a serial byte buffer is not used but the received bytes are decoded into the integer fields in the fly, then a copy of the struct may be provided, e.g. after the last integer has been decoded, put the complete struct into a mailbox, if the RTOS provides mailbox support. In both cases the main task has a full message transfer time to process a message, before it has to process the next serial message. If the main task is incapable of processing the messages in time, then the program is faulty at least in the hard real time sense. > >If "int" is your CPUs word size, you are using word alignment, and you >don't have multiple CPUs with separate caches accessing the same RAM, >you're probably ok for individual variables. However you will come >unstuck if you expect assignments and reads to be performed in the same >order you wrote them. A modern compiler will freely re-order things in >extremely ambitious and unexpected ways, in order to keep the pipeline >flowing. Using volatile declaration and turn of optimization will help. Better yet, use small assembler routines to have full control of actual memory access. > >I cannot emphasise this enough. The compiler will do what it can to make >your program do what it thinks you have asked for - which will NOT be >the same as what you think you have asked for. > >You need to understand about basic mutex operations, preferably also >semaphores, and beyond that to read and write barriers (if you want to >write lock-free code). It's a big subject. t least with a small micro controller, simply disable interrupts for a critical section. Of course the critical section must behave like a real interrupt, limit the number of instructions and do not call any library routines.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-01-05 14:07 +0100 |
| Message-ID | <qusn2q$m5i$1@dont-email.me> |
| In reply to | #29007 |
On 05/01/2020 10:21, upsidedown@downunder.com wrote: > On Sun, 5 Jan 2020 14:26:12 +1100, Clifford Heath <no.spam@please.net> >> >> If "int" is your CPUs word size, you are using word alignment, and you >> don't have multiple CPUs with separate caches accessing the same RAM, >> you're probably ok for individual variables. However you will come >> unstuck if you expect assignments and reads to be performed in the same >> order you wrote them. A modern compiler will freely re-order things in >> extremely ambitious and unexpected ways, in order to keep the pipeline >> flowing. > > Using volatile declaration and turn of optimization will help. Better > yet, use small assembler routines to have full control of actual > memory access. Turning off optimisation is /never/ the answer! (Baring bugging compilers, of course.) If your code "works with optimisation disabled", your code is /wrong/. In over 25 years in this business, I have never seen an exception. Remember, there is no such thing as "disabling optimisations" - compilers can re-arrange code and apply whatever transformations they like, according to the C standards, with a total disregard for your choice of optimisation settings. These settings are guidelines, not part of the semantics of the language - the language and the freedoms the compiler has do not change (unless your compiler specifically documents the changes). And even if you think it is a "workaround" that is good enough for now, you are creating a maintainability nightmare. Or worse - you are creating something that works fine during your testing and fails when deployed. "Volatile", when used correctly, can be helpful. Assembly routines for memory accesses are usually a bad idea - inefficient, inflexible and error-prone. If you want a simple and relatively fool-proof system, all you really need are two functions (preferably inline) : interrupt_status_t disableGlobalInterrupts(void); void restoreGlobalInterrupts(interrupt_status_t old_status); These must both act as full memory fences. Then you can put whatever code needs atomic behaviour within a critical section bracketed by these functions. You need more work if you have other memory masters (DMA, second processor, etc.). > >> >> I cannot emphasise this enough. The compiler will do what it can to make >> your program do what it thinks you have asked for - which will NOT be >> the same as what you think you have asked for. >> >> You need to understand about basic mutex operations, preferably also >> semaphores, and beyond that to read and write barriers (if you want to >> write lock-free code). It's a big subject. > > t least with a small micro controller, simply disable interrupts for a > critical section. Of course the critical section must behave like a > real interrupt, limit the number of instructions and do not call any > library routines. >
[toc] | [prev] | [next] | [standalone]
| From | upsidedown@downunder.com |
|---|---|
| Date | 2020-01-05 17:46 +0200 |
| Message-ID | <74041f9c9p82eeac586mn9bo8c73jeqfcj@4ax.com> |
| In reply to | #29009 |
On Sun, 5 Jan 2020 14:07:37 +0100, David Brown <david.brown@hesbynett.no> wrote: >On 05/01/2020 10:21, upsidedown@downunder.com wrote: >> On Sun, 5 Jan 2020 14:26:12 +1100, Clifford Heath <no.spam@please.net> > >>> >>> If "int" is your CPUs word size, you are using word alignment, and you >>> don't have multiple CPUs with separate caches accessing the same RAM, >>> you're probably ok for individual variables. However you will come >>> unstuck if you expect assignments and reads to be performed in the same >>> order you wrote them. A modern compiler will freely re-order things in >>> extremely ambitious and unexpected ways, in order to keep the pipeline >>> flowing. >> >> Using volatile declaration and turn of optimization will help. Better >> yet, use small assembler routines to have full control of actual >> memory access. > >Turning off optimisation is /never/ the answer! (Baring bugging >compilers, of course.) > >If your code "works with optimisation disabled", your code is /wrong/. >In over 25 years in this business, I have never seen an exception. > >Remember, there is no such thing as "disabling optimisations" - >compilers can re-arrange code and apply whatever transformations they >like, according to the C standards, with a total disregard for your >choice of optimisation settings. These settings are guidelines, not >part of the semantics of the language - the language and the freedoms >the compiler has do not change (unless your compiler specifically >documents the changes). The problem is the C standard or actually the language lawyers (in most languages) who do not have understanding for multithreading or multiprocessors. >And even if you think it is a "workaround" that is good enough for now, >you are creating a maintainability nightmare. Or worse - you are >creating something that works fine during your testing and fails when >deployed. > >"Volatile", when used correctly, can be helpful. > >Assembly routines for memory accesses are usually a bad idea - >inefficient, inflexible and error-prone. In any hardware platforms with at least memory location increment or decrement operation as on a single instruction performing read/modify/write memory access cycle is often quite hardly. Even if you can't get an atomic R/M/W cycle, there are often similar tricks e.g. such as using the lock prefix in x86 >If you want a simple and relatively fool-proof system, all you really >need are two functions (preferably inline) : > >interrupt_status_t disableGlobalInterrupts(void); >void restoreGlobalInterrupts(interrupt_status_t old_status); > >These must both act as full memory fences. > >Then you can put whatever code needs atomic behaviour within a critical >section bracketed by these functions. Is this standard C in some recent standard variant ? >You need more work if you have other memory masters (DMA, second >processor, etc.). This has a lot to do with cache coherence.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-01-05 19:08 +0100 |
| Message-ID | <qut8m6$uq3$1@dont-email.me> |
| In reply to | #29011 |
On 05/01/2020 16:46, upsidedown@downunder.com wrote:
> On Sun, 5 Jan 2020 14:07:37 +0100, David Brown
> <david.brown@hesbynett.no> wrote:
>
>> On 05/01/2020 10:21, upsidedown@downunder.com wrote:
>>> On Sun, 5 Jan 2020 14:26:12 +1100, Clifford Heath <no.spam@please.net>
>>
>>>>
>>>> If "int" is your CPUs word size, you are using word alignment, and you
>>>> don't have multiple CPUs with separate caches accessing the same RAM,
>>>> you're probably ok for individual variables. However you will come
>>>> unstuck if you expect assignments and reads to be performed in the same
>>>> order you wrote them. A modern compiler will freely re-order things in
>>>> extremely ambitious and unexpected ways, in order to keep the pipeline
>>>> flowing.
>>>
>>> Using volatile declaration and turn of optimization will help. Better
>>> yet, use small assembler routines to have full control of actual
>>> memory access.
>>
>> Turning off optimisation is /never/ the answer! (Baring bugging
>> compilers, of course.)
>>
>> If your code "works with optimisation disabled", your code is /wrong/.
>> In over 25 years in this business, I have never seen an exception.
>>
>> Remember, there is no such thing as "disabling optimisations" -
>> compilers can re-arrange code and apply whatever transformations they
>> like, according to the C standards, with a total disregard for your
>> choice of optimisation settings. These settings are guidelines, not
>> part of the semantics of the language - the language and the freedoms
>> the compiler has do not change (unless your compiler specifically
>> documents the changes).
>
> The problem is the C standard or actually the language lawyers (in
> most languages) who do not have understanding for multithreading or
> multiprocessors.
The main point of C11 is support for multi-threading and multi-processor
systems. The standards, and the language lawyers, /do/ understand it.
The more advanced and progressive compilers support C11. Many embedded
ones do not, but that is the fault of the compiler vendors, and perhaps
of developers who don't realise that they should be insisting on it.
The big missing feature, however, is that you need an implementation of
some of the functions in the C11 threading libraries, and the
implementation must fit the OS in use. That's not too hard for Linux or
Windows, but a different world in embedded systems. Still, it should be
possible to make C11 library support for FreeRTOS, mbed, and any other
RTOS you like.
Key points like atomics, fences, and language semantics for
multi-threading are in place.
(And C++ is more helpful in providing higher level multi-threading
features.)
So we are far from having nice multi-threading integration in C
toolchains, but nearly as far as you suggest.
>
>> And even if you think it is a "workaround" that is good enough for now,
>> you are creating a maintainability nightmare. Or worse - you are
>> creating something that works fine during your testing and fails when
>> deployed.
>>
>> "Volatile", when used correctly, can be helpful.
>>
>> Assembly routines for memory accesses are usually a bad idea -
>> inefficient, inflexible and error-prone.
>
> In any hardware platforms with at least memory location increment or
> decrement operation as on a single instruction performing
> read/modify/write memory access cycle is often quite hardly.
>
/Some/ hardware platforms that let you do "x++" as a single instruction
on memory, do so atomically. Many others do not. Typically, they are
atomic on small 8-bit CISC microcontrollers. On larger processors, you
rarely get such instructions at all (they don't exist on any kind of
RISC cpu). And even when you /do/ get them, they may be implemented by
multiple separate actions. Perhaps they are atomic with respect to
other code on the same core (such as interrupts), but not with respect
to DMA or other cores.
So this kind of thing can sometimes be acceptable on target-specific
code for small microcontrollers, but not otherwise.
> Even if you can't get an atomic R/M/W cycle, there are often similar
> tricks e.g. such as using the lock prefix in x86
>
You do that using intrinsics or C11/C++11 atomics. You certainly don't
do it with "volatile".
>
>> If you want a simple and relatively fool-proof system, all you really
>> need are two functions (preferably inline) :
>>
>> interrupt_status_t disableGlobalInterrupts(void);
>> void restoreGlobalInterrupts(interrupt_status_t old_status);
>>
>> These must both act as full memory fences.
>>
>> Then you can put whatever code needs atomic behaviour within a critical
>> section bracketed by these functions.
>
> Is this standard C in some recent standard variant ?
No C standard covers interrupts, or ways to disable and enable them -
that is highly target-specific.
For example, on the ARM Cortex-M, you might use:
#include "core_cmFunc.h"
typedef interrupt_status_t uint32_t;
static inline interrupt_status_t disableGlobalInterrupts(void) {
interrupt_status_t old = __get_PRIMASK();
__disable_irq();
return old;
}
static inline void restoreGlobalInterrupts(interrupt_status_t old) {
__set_PRIMASK(old);
}
If you don't want to use the ARM core functions, you can use inline
assembly - but that is compiler specific. For gcc, that would be:
typedef interrupt_status_t uint32_t;
static inline interrupt_status_t disableGlobalInterrupts(void) {
interrupt_status_t old;
asm volatile ("mrs %0, primask" : "=r" (old));
asm volatile ("cpsid i" : : : "memory");
return old;
}
static inline void restoreGlobalInterrupts(interrupt_status_t old) {
asm volatile ("msr primask, %0" : : "r" (old) : "memory");
}
C11 provides standard support for a memory barrier, but since you need
compiler-specific code for the implementation anyway, you might as well
use the compiler-specific memory barrier.
>
>
>> You need more work if you have other memory masters (DMA, second
>> processor, etc.).
>
> This has a lot to do with cache coherence.
>
That is one aspect, yes. But it is not the only one. For example,
bigger processors can have write buffers with re-ordering.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-01-05 13:56 +0100 |
| Message-ID | <qusmdc$idf$1@dont-email.me> |
| In reply to | #29005 |
On 05/01/2020 04:26, Clifford Heath wrote: > On 5/1/20 11:58 am, pozz wrote: >> Il 03/01/2020 15:19, David Brown ha scritto: >>> With pre-emptive scheduling, you will have to go >>> through your existing code and make very sure that you have locks or >>> synchronisation in place for any shared resources or data. >> >> As I already wrote many times, I don't have experience with RTOS and >> task sync mechanism such as semaphores, locks, mutexes, message queues >> and so on. >> So I'm not able to understand when a sync is really needed. >> Could you point on a good simple material to study (online or book)? > > I wish I could, but it is actually a frightfully difficult subject. > Basically it's the same as thread-safe programming. > Only about 1% of programmers think they can do it. > Of those, only about 1% actually can. > > It's the 0.99% that you have to worry about. At least some of them for > Toyota. Don't be one of them! All good points. > > However, this difficulty is precisely why Rust was created. Although I > haven't yet done a project in Rust, I've done enough multi-threaded work > in C++ to know that the ideas in Rust are a massive leap forwards, and > anyone doing this kind of work (especially professionally) owes it to > their users to learn it. "Safe" languages like Rust can help for simple issues, but won't give any benefits of the more challenging cases. If you understand the basics of multi-threading, and have a good, careful development methodology, you won't have the kind of problems that Rust would help you with. Maybe Rust will help for some cases, but don't believe that it is a game-changer. > >> Supposing all the variables are of type int (i.e., they are changed >> atomically in serial_task()), should I need to protect them with >> locks, because they are used by main_task() too? > > If "int" is your CPUs word size, you are using word alignment, and you > don't have multiple CPUs with separate caches accessing the same RAM, > you're probably ok for individual variables. However you will come > unstuck if you expect assignments and reads to be performed in the same > order you wrote them. A modern compiler will freely re-order things in > extremely ambitious and unexpected ways, in order to keep the pipeline > flowing. Yes. Simple reads and writes of aligned data that is no bigger than the cpu's word size will be atomic without any more effort. But complex accesses (like "x++;") are not atomic on most processors. And you don't have any ordering unless you use "volatile", or memory fences of some kind. A key mistake many people make is to think that non-volatile accesses are also ordered by volatile accesses - this is, of course, untrue. > > I cannot emphasise this enough. The compiler will do what it can to make > your program do what it thinks you have asked for - which will NOT be > the same as what you think you have asked for. Well, it /will/ be the same as you think you asked for when you know what you are doing! > > You need to understand about basic mutex operations, preferably also > semaphores, and beyond that to read and write barriers (if you want to > write lock-free code). It's a big subject. > Yes. Or he can use cooperative multitasking, and avoid many of these issues! > Clifford Heath.
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2020-01-05 13:39 -0600 |
| Message-ID | <qutdje$tko$1@dont-email.me> |
| In reply to | #29005 |
Clifford Heath wrote: > On 5/1/20 11:58 am, pozz wrote: <snip> > > I wish I could, but it is actually a frightfully difficult subject. > Basically it's the same as thread-safe programming. > Only about 1% of programmers think they can do it. > Of those, only about 1% actually can. > I could show anyone how in an afternoon. So I take your statement as being "only 1% of 1% have been forced to take that afternoon to learn it." I should qualify that - I could show anyone working on a classic architecture how. With multilevel caches and certain sorts of MMUs, there may be more to it. I'm thinking the WindRiver drivers course was about one week, which should about cover everything conceptually. > It's the 0.99% that you have to worry about. At least some of them for > Toyota. Don't be one of them! > > However, this difficulty is precisely why Rust was created. Although I > haven't yet done a project in Rust, I've done enough multi-threaded work > in C++ to know that the ideas in Rust are a massive leap forwards, and > anyone doing this kind of work (especially professionally) owes it to > their users to learn it. > I seriously doubt Rust represents some quantum leap here. <snip> > > You need to understand about basic mutex operations, preferably also > semaphores, and beyond that to read and write barriers (if you want to > write lock-free code). It's a big subject. > And that's about an afternoon, really. Not so much the barriers and bothering with lock-free. That may take a little more. > Clifford Heath. -- Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Clifford Heath <no.spam@please.net> |
|---|---|
| Date | 2020-01-06 07:44 +1100 |
| Message-ID | <uUrQF.242435$%d1.180908@fx45.iad> |
| In reply to | #29015 |
On 6/1/20 6:39 am, Les Cargill wrote: > Clifford Heath wrote: >> On 5/1/20 11:58 am, pozz wrote: > <snip> >> >> I wish I could, but it is actually a frightfully difficult subject. >> Basically it's the same as thread-safe programming. >> Only about 1% of programmers think they can do it. >> Of those, only about 1% actually can. >> > > I could show anyone how in an afternoon. So I take your statement as > being "only 1% of 1% have been forced to take that afternoon to learn it." > > I should qualify that - I could show anyone working on a classic > architecture how. With multilevel caches and certain sorts of MMUs, > there may be more to it. > > I'm thinking the WindRiver drivers course was about one week, which > should about cover everything conceptually. > >> It's the 0.99% that you have to worry about. At least some of them for >> Toyota. Don't be one of them! >> >> However, this difficulty is precisely why Rust was created. Although I >> haven't yet done a project in Rust, I've done enough multi-threaded >> work in C++ to know that the ideas in Rust are a massive leap >> forwards, and anyone doing this kind of work (especially >> professionally) owes it to their users to learn it. >> > > I seriously doubt Rust represents some quantum leap here. > > <snip> >> >> You need to understand about basic mutex operations, preferably also >> semaphores, and beyond that to read and write barriers (if you want to >> write lock-free code). It's a big subject. >> > > And that's about an afternoon, really. Not so much the barriers and > bothering with lock-free. That may take a little more. Behold a 0.99%-er! :)
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2020-01-05 21:00 -0600 |
| Message-ID | <quu7ei$btv$1@dont-email.me> |
| In reply to | #29018 |
Clifford Heath wrote: > On 6/1/20 6:39 am, Les Cargill wrote: >> Clifford Heath wrote: >>> On 5/1/20 11:58 am, pozz wrote: >> <snip> >>> >>> I wish I could, but it is actually a frightfully difficult subject. >>> Basically it's the same as thread-safe programming. >>> Only about 1% of programmers think they can do it. >>> Of those, only about 1% actually can. >>> >> >> I could show anyone how in an afternoon. So I take your statement as >> being "only 1% of 1% have been forced to take that afternoon to learn >> it." >> >> I should qualify that - I could show anyone working on a classic >> architecture how. With multilevel caches and certain sorts of MMUs, >> there may be more to it. >> >> I'm thinking the WindRiver drivers course was about one week, which >> should about cover everything conceptually. >> >>> It's the 0.99% that you have to worry about. At least some of them >>> for Toyota. Don't be one of them! >>> >>> However, this difficulty is precisely why Rust was created. Although >>> I haven't yet done a project in Rust, I've done enough multi-threaded >>> work in C++ to know that the ideas in Rust are a massive leap >>> forwards, and anyone doing this kind of work (especially >>> professionally) owes it to their users to learn it. >>> >> >> I seriously doubt Rust represents some quantum leap here. >> >> <snip> >>> >>> You need to understand about basic mutex operations, preferably also >>> semaphores, and beyond that to read and write barriers (if you want >>> to write lock-free code). It's a big subject. >>> >> >> And that's about an afternoon, really. Not so much the barriers and >> bothering with lock-free. That may take a little more. > > Behold a 0.99%-er! > > :) We can larf, but I think there's less to serialization than is made of it. -- Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Clifford Heath <no.spam@please.net> |
|---|---|
| Date | 2020-01-06 14:50 +1100 |
| Message-ID | <m8yQF.61419$sS2.24799@fx15.iad> |
| In reply to | #29022 |
On 6/1/20 2:00 pm, Les Cargill wrote: > Clifford Heath wrote: >> On 6/1/20 6:39 am, Les Cargill wrote: >>> Clifford Heath wrote: >>>> You need to understand about basic mutex operations, preferably also >>>> semaphores, and beyond that to read and write barriers (if you want >>>> to write lock-free code). It's a big subject. >>> And that's about an afternoon, really. Not so much the barriers and >>> bothering with lock-free. That may take a little more. > We can larf, but I think there's less to serialization than is made of it. Serialization using one giant lock isn't too hard - that's how people write code using interrupts. But it's a very simplified case, and the problem is to use such simple locking to construct correct algorithms at a higher level. Many apparently straightforward algorithms have dire pathologies when the atomic operations can get interspersed at will. In many cases the bugs will not ever show up during testing. And *that* is the real problem. Such code must be *correct by construction*, but people generally don't work that way. Clifford Heath.
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2020-01-06 07:12 -0600 |
| Message-ID | <quvb9p$rms$1@dont-email.me> |
| In reply to | #29025 |
Clifford Heath wrote: > On 6/1/20 2:00 pm, Les Cargill wrote: >> Clifford Heath wrote: >>> On 6/1/20 6:39 am, Les Cargill wrote: >>>> Clifford Heath wrote: >>>>> You need to understand about basic mutex operations, preferably >>>>> also semaphores, and beyond that to read and write barriers (if you >>>>> want to write lock-free code). It's a big subject. >>>> And that's about an afternoon, really. Not so much the barriers and >>>> bothering with lock-free. That may take a little more. >> We can larf, but I think there's less to serialization than is made of >> it. > Well said, Clifford, by the way. > Serialization using one giant lock isn't too hard - that's how people > write code using interrupts. But it's a very simplified case, and the > problem is to use such simple locking to construct correct algorithms at > a higher level. > I really feel it's just a matter of people stretching metaphors beyond the breaking point. Most of the example cases I have seen to illustrate these pathologies are rather contrived. Most of these are due to ... reversing dependencies within a logic structure, not abuse of constructs. And yes, I have trouble reading that sentence too. I also don't want to appear to be too blase about things like cache lines, memory fences and all that. I just mean basic semaphores. > Many apparently straightforward algorithms have dire pathologies when > the atomic operations can get interspersed at will. Because it can't very well be "at will". Aren't semaphores like the escapement mechanism in a regulator clock more than anything else? They say "Not now." > In many cases the > bugs will not ever show up during testing. And *that* is the real > problem. Such code must be *correct by construction*, but people > generally don't work that way. > I will not disagree; it doesn't mean I have to like that state of affairs. To an extent the very word "correct" seems to inspire helplessness. > Clifford Heath. -- Les Cargill
[toc] | [prev] | [next] | [standalone]
| From | Paul Rubin <no.email@nospam.invalid> |
|---|---|
| Date | 2020-01-04 22:34 -0800 |
| Message-ID | <87blrio1hk.fsf@nightsong.com> |
| In reply to | #29004 |
pozz <pozzugno@gmail.com> writes: > As I already wrote many times, I don't have experience with RTOS and > task sync mechanism such as semaphores, locks, mutexes, message queues > and so on. > So I'm not able to understand when a sync is really needed. > > Could you point on a good simple material to study (online or book)? I have found it simplest to have tasks communicate by message passing, the so-called "CSP model" (communicating sequential processes), rather than fooling around with explicit locks. With locks you have to worry about lock inversion and all kinds of other madness, and your main hope of getting it right is formal methods, like Lamport used for the Paxos algorithm. Message passing incurs some cpu overhead because of the interprocess communication and context switches, but it gets rid of a lot of ways things go wrong. If your RTOS supports message passing (look for "mailboxes" in the RTOS docs) then I'd say use them. The language most associated with CSP style is Erlang, which doesn't really fit on small embedded devices, but Erlang materials might still be a good place to learn about the style. Erlang inventor Joe Armstrong's book might be a good place to start: http://erlang.org/download/erlang-book-part1.pdf At the much lower end, you could check out Brad Rodriguez's articles about Forth multitaskers: https://www.bradrodriguez.com/papers/mtasking.html and related ones at https://www.bradrodriguez.com/papers/ .
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2020-01-05 14:12 +0100 |
| Message-ID | <qusnb2$nod$1@dont-email.me> |
| In reply to | #29006 |
On 05/01/2020 07:34, Paul Rubin wrote: > pozz <pozzugno@gmail.com> writes: >> As I already wrote many times, I don't have experience with RTOS and >> task sync mechanism such as semaphores, locks, mutexes, message queues >> and so on. >> So I'm not able to understand when a sync is really needed. >> >> Could you point on a good simple material to study (online or book)? > > I have found it simplest to have tasks communicate by message passing, > the so-called "CSP model" (communicating sequential processes), rather > than fooling around with explicit locks. With locks you have to worry > about lock inversion and all kinds of other madness, and your main hope > of getting it right is formal methods, like Lamport used for the Paxos > algorithm. Message passing incurs some cpu overhead because of the > interprocess communication and context switches, but it gets rid of a > lot of ways things go wrong. > > If your RTOS supports message passing (look for "mailboxes" in the RTOS > docs) then I'd say use them. > Yes - message passing (whether asynchronous with queues, or synchronous with CSP style) is often a lot easier to get right than complicated locking mechanisms. > The language most associated with CSP style is Erlang, which doesn't > really fit on small embedded devices, but Erlang materials might still > be a good place to learn about the style. Erlang inventor Joe > Armstrong's book might be a good place to start: > > http://erlang.org/download/erlang-book-part1.pdf > I've worked indirectly with Erlang (I made the microcontroller half of the system, in C, while someone else wrote the Linux half in Erlang). I was not impressed - he spend a lot of time figuring out things that should have been very simple. It is just one sample point, of course, and not enough to condemn a whole language - but it does mean Erlang is not high on my "languages to learn when I have time" list. Far and away the most popular "CSP language" is Go, as I understand it. Another option is XC for XMOS devices, but that is hardware-specific. > At the much lower end, you could check out Brad Rodriguez's articles > about Forth multitaskers: > > https://www.bradrodriguez.com/papers/mtasking.html > > and related ones at https://www.bradrodriguez.com/papers/ . >
[toc] | [prev] | [next] | [standalone]
| From | Niklas Holsti <niklas.holsti@tidorum.invalid> |
|---|---|
| Date | 2020-01-05 18:00 +0200 |
| Message-ID | <h7efgbF9e1nU1@mid.individual.net> |
| In reply to | #29010 |
On 2020-01-05 15:12, David Brown wrote:
> On 05/01/2020 07:34, Paul Rubin wrote:
>> pozz <pozzugno@gmail.com> writes:
>>> As I already wrote many times, I don't have experience with RTOS and
>>> task sync mechanism such as semaphores, locks, mutexes, message queues
>>> and so on.
>>> So I'm not able to understand when a sync is really needed.
>>>
>>> Could you point on a good simple material to study (online or book)?
>>
>> I have found it simplest to have tasks communicate by message passing,
>> the so-called "CSP model" (communicating sequential processes), rather
>> than fooling around with explicit locks.
[snip]
> Yes - message passing (whether asynchronous with queues, or synchronous
> with CSP style) is often a lot easier to get right than complicated
> locking mechanisms.
>
>> The language most associated with CSP style is Erlang, which doesn't
>> really fit on small embedded devices, but Erlang materials might still
>> be a good place to learn about the style. Erlang inventor Joe
>> Armstrong's book might be a good place to start:
>>
>> http://erlang.org/download/erlang-book-part1.pdf
[snip]
> Far and away the most popular "CSP language" is Go, as I understand it.
> Another option is XC for XMOS devices, but that is hardware-specific.
Another language with CSP-style primitives is Ada (the "rendez-vous"
feature), although AIUI most embedded Ada programs currently being
implemented use the alternative "monitor"-like primitives (the
"protected object" feature), which can be used to implement critical
regions, or CSP-like message passing, or buffered (queued) message
passing, or for many other styles.
--
Niklas Holsti
Tidorum Ltd
niklas holsti tidorum fi
. @ .
[toc] | [prev] | [next] | [standalone]
| From | Les Cargill <lcargill99@comcast.com> |
|---|---|
| Date | 2020-01-05 13:44 -0600 |
| Message-ID | <qutdta$vk4$1@dont-email.me> |
| In reply to | #29006 |
Paul Rubin wrote: > pozz <pozzugno@gmail.com> writes: >> As I already wrote many times, I don't have experience with RTOS and >> task sync mechanism such as semaphores, locks, mutexes, message queues >> and so on. >> So I'm not able to understand when a sync is really needed. >> >> Could you point on a good simple material to study (online or book)? > > I have found it simplest to have tasks communicate by message passing, > the so-called "CSP model" (communicating sequential processes), rather > than fooling around with explicit locks. With locks you have to worry > about lock inversion and all kinds of other madness, and your main hope > of getting it right is formal methods, like Lamport used for the Paxos > algorithm. Message passing incurs some cpu overhead because of the > interprocess communication and context switches, but it gets rid of a > lot of ways things go wrong. > > If your RTOS supports message passing (look for "mailboxes" in the RTOS > docs) then I'd say use them. > Mailboxes are just semaphores with extra steps :) When I've written mailboxes for use in user space, they usually use a semaphore. In kernel space, you're already under a "semaphore" ( but still subject to asynchronous interrupts ). This of course varies by O/S.... > The language most associated with CSP style is Erlang, which doesn't > really fit on small embedded devices, but Erlang materials might still > be a good place to learn about the style. Erlang inventor Joe > Armstrong's book might be a good place to start: > Erlang is a fine system,. The ( arguably ) best thing it provides is the "actor pattern", which applies independent of language choice. <snip> -- Les Cargill
[toc] | [prev] | [next] | [standalone]
Page 3 of 4 — ← Prev page 1 2 [3] 4 Next page →
Back to top | Article view | comp.arch.embedded
csiph-web