RTOS system design--how many tasks?

Hi,

We're designing a new system using an RTOS. Everyone on the team has worked with an RTOS before, but none of us has ever designed a system. One thing I'm concerned with is we may end up with too many tasks. I reviewed my papers/magazines and searched the web for half a day and didn't get much info. So, for those of you who've been through this before, I have a couple of basic questions:

1) What are the disadvantages of a lot of tasks (besides inefficient stack usage)? I'm concerned it may exacerbate deadlock, make it harder to debug, create synchronization issues, etc.

2) How do you decide when to create a task? We decided to create a "task creation criteria" to aid us. Right now it has the following: a) any defined events in the system (button presses, etc.) should be in a task, b) anything that is going to take a while to complete (i.e. background processing) should be in a task and c) could placing stuff in a task aid in synchronization? (this is currently under debate).

Thanks much for your input!!

Jim

Reply to
james.ro123
Loading thread data ...

The main thing that comes with more tasks is an increased amount of overhead due to the OS switching more often. If two pieces of code work towards the same goal then they should be in the same task. If two pieces of code only need to share data, but perform differents tasks with the data, then each should get its own task. Pretty simple. As far as synchronization goes, it is easier to synchronize inside of a task than it is to synchronize using inter-process communication, and the overhead associated with it is far less.

Also, if you are dealing with a hard real-time system scheduled with say a rate monotonic policy, then the utilization bound can be severely impacted by the number and utilizations of the tasks.

---Matthew Hicks

Reply to
Matthew Hicks

This all depends on the scheduling algorithm, the ratio between no. of tasks and priorities and your methods of inter-task communication and synchronisation.

Deadlock can be avoided altogether by proper system design. If your debugging setup can query the current task after hitting a breakpoint, then it is not harder to debug. If your debugging setup can query synchronisation and communication primitives, then that also is not an issue.

If this means that you can have too few tasks, then yes. Otherwise explain "stuff".

--
Gemaakt met Opera's revolutionaire e-mailprogramma:  
http://www.opera.com/mail/
Reply to
Boudewijn Dijkstra

Memory is cheap these days so inefficient stack usage isn't something to be too concerned about. Time is still expensive, though, so spending too much time switching between tasks is a valid concern.

Everything must be in a task or an ISR if tasking is to work properly. The question, then, is not whether portions of processing should be in tasks but how to organize tasks and assign processing to those tasks.

My designs tend to associate tasks with interrupt sourcess, often with one task per interrupt but multiple interrupts may be associated with single tasks, too. Note that timers are interrupt sources and that tasks may be entirely timer driven.

HTH

--
========================================================================
          Michael Kesti            |  "And like, one and one don't make
                                   |   two, one and one make one."
    mrkesti at hotmail dot com     |          - The Who, Bargain
Reply to
Michael R. Kesti

The whole purpose of multitasking is the simplification of the development. Of course, it comes with some overhead. Having too many tasks actually makes the things more complicated.

In my projects, it is usually about 10 separate threads.

The excessive task switching and message passing between the tasks is wasting the CPU cycles, too.

If there is a job which has to be done from time to time asynchronously to the other jobs, it is good to implement this job as a separate task.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

I'd put the whole user interface into one task. The user is sufficiently slow to not press multiple buttons at once.

The alternate solution to a task is a statemachine for a closed process. Statemachines are more complex than the linear code of a task. So basically you trade complexity against efficiency.

Rene

--
Ing.Buero R.Tschaggelar - http://www.ibrtses.com
& commercial newsgroups - http://www.talkto.net
Reply to
Rene Tschaggelar

The user interface consists of the two asynchronous processes at the least: the input and the output. Thus it is natural to have the two threads for that. Other then that, there could be many threads dealing with the graphics engine, etc.

Yes. Avoiding the state machines is the whole point of multitasking.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

Heh - I avoid (or implement) multitasking using state machines ;).

(Main advantage: synchronicity. Secondary advantage: simplicity.)

Steve

formatting link

Reply to
Steve at fivetrees

for(;;) Do_Everything() works only for the small projects.

The amount of money paid is generally proportional to the size of the project.

Thus multitasking is the way to go :)

Windows 3.x was all synchronous single task system. That's one of the reasons why the programming for it was so miserable.

Vladimir Vassilevsky

DSP and Mixed Signal Design Consultant

formatting link

Reply to
Vladimir Vassilevsky

Others have noted the cost of task switching. I would have thought this was the least of your worries unless you have a slow CPU, a poor RTOS or very high frequencies -- VxWorks on a 1 GHz PPC switches in a small number of us.

Having lots of tasks 'because you can' without a clear design strategy of tasking/synchronisation is a good road to disaster.

We use tasks:

  • to block on input (an interrupt, a network packet).

  • to handle long processes in the background (this is rare for us).

  • to support real-time response requirements, where non-real-time event processing is too unconstrained.

  • to support non-real-time event processing.

  • (rarely!) to support large stack requirements.

The last is a bit odd, but easy in Ada --

procedure Foo is

task type T is pragma Storage_Size (1_000_000); entry Start; end T;

task body T is ... end T;

begin

-- setup

T.Start;

-- blocks here until T terminates

end Foo;

Reply to
Simon Wright

I have used this rule of thumb (sic) for decades: Keep the number of tasks below 11 so you can count the tasks with your fingers. In exceptional cases up to 20 tasks could be used, but my colleagues might not like if I take my socks off and use also my toes to count the tasks :-).

As long as you have a clear system, in which task owns a specific data set (i.e. is allowed to modify it) and use as much atomic data types as possible, the need for task synchronisation primitives is reduced and also the risk for priority inversions and other deadlock situations is minimised.

  • Each external device should get an own task, so if you have multiple serial lines, each should get an own task.
  • A command line interpreter/user interface needs an own task.
  • Disk access or even large queue handling could benefit from an own task.
  • Very heavy, low priority calculations could be done in the NULL/Idle task.
  • A clock task might also be useful to offload the workload from the timer interrupt service routine (i.e. handle time of day and calendar and also control timeouts and other time related functions).

In a typical situation, these tasks should be quite sufficient.

However, in situations with a limited direct addressability (say 64 KiB) combined with a MMU and a much larger physical address space, it can be a good idea to split to chunks to less than 64 KiB, even if the functionality would not absolutely require it.

Paul

Reply to
Paul Keinanen

In some of the systems I work on there can easily be 70+ task instances (a tx and rx task for each of 32 serial ports gets you to 64 right away). If you want to count task "functions" in the souce code, there have probably never been more than 6-8 in anything I've ever worked on.

--
Grant Edwards                   grante             Yow! Can you MAIL a BEAN
                                  at               CAKE?
                               visi.com
Reply to
Grant Edwards

In news: snipped-for-privacy@4ax.com timestamped Fri, 08 Jun 2007 23:10:33 +0300, Paul Keinanen posted a rather helpful response which included: "[..] As long as you have a clear system, in which task owns a specific data set (i.e. is allowed to modify it) and use as much atomic data types as possible, the need for task synchronisation primitives is reduced and also the risk for priority inversions and other deadlock situations is minimised. [..]"

Making your system clear will help you to design it such that priority inversions will be less likely, but if your system has a resource shared by tasks of different priorities, then atomic data types can not prevent a priority inversion here.

Regards, Colin Paul Gloster

Reply to
Colin Paul Gloster

You only get priority inversions, if some of the tasks lock that resource and hence some other task may have to wait for that resource. In many cases the program and the data structures can be designed in such a way that the locking is not required, thus eliminating the possibility of priority inversion.

Paul

Reply to
Paul Keinanen

They'd like it even less if you had 21 tasks ;-)

Reply to
Tom Lucas

I hear this often, but I disagree. I've done some very large/complex systems using cooperative multitasking. As always, it's a question of breaking complex things down into a collection of simple things.

Ah, if you're talking about general-purpose programmable systems, then I'd agree. I'm referring to embedded systems.

I *would* concede, however, that using an RTOS makes good sense where large teams are involved. The discipline required to successfully write cooperative tasks is somewhat relaxed - the brute-force context swapping ensures each task gets a fair shake. And it can be easier to partition tasks. However, cooperative multitasking shouldn't be dismissed - properly written, it's (obviously) more efficient, less demanding of the hardware, and the discipline required to understand the requirements and design it properly in the first place (rather than throw code at an RTOS) tends to make for a more solid system.

YMMV ;).

Steve

formatting link

Reply to
Steve at fivetrees

Me too, for the same reasons - synchronicity and simplicity. With judicious use of interrupts, it is my favoured approach.

I have seen an RTOS approach running on a 32-bit system, then ported to a state machine to get it to work as required - I'm sure there are examples of the other way around too.

And the cut off point between the two approaches (for embedded systems) is? .....

I have seen projects 20K+ lines of code that use a state machine method very well, with very good performance/clarity (and therefore maintainability). The point at which the state machine breaks down is of course due to other factors, other than just LOC. And not well defined. Otherwise, projects wouldn't start with one approach, and then switch over to the other.

Regards,

Paul.

Reply to
Paul Taylor

Did you ask my male or female colleagues :-)

Paul

Reply to
Paul Keinanen

I'd like to thank everyone for their responses. Friday, I'll summarize all this and present it to the team.

Thanks again!

Jim

Reply to
james.ro123

There are a lot of good ideas here, so I thought I'd just throw out a few resources:

Software Design Methods of Concurrent and Real-Time Systems by Hassan Gomaa is a great resource (ISBN 0-201-52577-1).

Operating Systems by Gary Nutt (ISBN 0-201-77344-9) has a really great dead-lock and synchronization section.

OK, some advice here:

  1. Make a rough pass over the entire system first and run that system at speed. It will give you a good idea of the bottle-necks and any potential dead-lock scenarios. Instead of computations, just use busy waits that can emulate the time aspect of each task.

  1. Identify the data sources and sinks. If possible make sure the system "runs down hill."

Reply to
b01011010

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.