NXC Multitasking Tutorial

Discussion specific to NXT-G, NXC, NBC, RobotC, Lejos, and more.
m-goldberg
Posts: 73
Joined: 29 Sep 2010, 12:05

NXC Multitasking Tutorial

Post by m-goldberg »

I am attaching a zip file to this post containing an NXC tutorial that I previously posted on the now defunct nxtay forums. It is intended for NXC programers who are ready to move up from programs where everything is coded into a main task, perhaps with a helper function or two, to NXC programs that use the multitasking capabilities of John Hansen's enhanced NXT firmware.

The counter program demonstrates many features of NXC, but it's main purpose is twofold:
  • To show how to write code where several tasks share a common resource through the use of a mutex.
  • To show how what looks like complex output can be built up from a set of simple functions.
Working through the tutorial only requires a NXT brick. No other LEGO parts are needed.

Should you have any questions or comments about the tutorial, please add them to this message thread (rather than sending me a private message) so others can benefit from what you have to say.
Attachments
NXT Counter.zip
(700.78 KiB) Downloaded 410 times
Regards, Morton
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC Multitasking Tutorial

Post by mattallen37 »

Based on what I have read so far, it looks great. Thanks for sharing.

What is the advantage (or difference) between a "mutex" vs. a global variable? I also need to better understand "for" statements, but I am learning. The program is really interesting, and I'm sure I will use a variation of it.

I think the most interesting thing I learned through what you posted though, is that you live in Ann Arbor MI. I went through there on US23 on Friday ;) .
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
spillerrec
Posts: 358
Joined: 01 Oct 2010, 06:37
Location: Denmark
Contact:

Re: NXC Multitasking Tutorial

Post by spillerrec »

Mutex are acquired and released in an atomic operation where global variables (theoretically) are not. (Or at least should...) That means that it cannot be acquired or released by two threads at the same time, the other thread must wait for the first tread to finish acquiring/releasing the mutex. Otherwise the two threads could at the same time read the variable, confirm that it is released and then both acquire it without noticing the other thread is doing exactly the same. So now the two threads would be running at the same time with the danger of unpredictable bugs.
My blog: http://spillerrec.dk/category/lego/
RICcreator, an alternative to nxtRICeditV2: http://riccreator.sourceforge.net/
m-goldberg
Posts: 73
Joined: 29 Sep 2010, 12:05

Re: NXC Multitasking Tutorial

Post by m-goldberg »

Spillerrec has given a good description of how a mutex works, but I will add some additional explanation.

Consider a public meeting where in order to speak you must acquire a microphone that is being passed around. Of course, one reason for doing this is to get the speakers voice amplified so that all can hear. But another reason might be to keep everyone for speaking at once, so that nobody can be heard. In this secondary capacity the microphone is acting as a mutex.
Regards, Morton
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC Multitasking Tutorial

Post by mattallen37 »

Ok, so if I understand right, it is as the following program shows, where "x" is constantly changing, but "y" is like the mutex.

Code: Select all

/*
  In this example, both variables are global, and can be read constantly.
  Only "y" is like a mutex, where you do not see the effect of the "++" until
  "y" is "released".
*/
int x,y;        //both x and y are global

task working()
{
  while(true)
  {
    x=y;        //aquiring the mutex
    repeat(100) //repeat 100 times before pausing
    {
      x++;      //x is changeing constantly
      Wait(10); //slow down so we can see it
    }
    y=x;        //releasing the mutex
    x=0;        //just to prove that it needs to aquire the mutex
    Wait(500);  //pause to see the effect
  }
}

task display()
{
  while(true)
  {
    ClearScreen();
    NumOut(0,LCD_LINE1,x); //display current x
    NumOut(0,LCD_LINE2,y); //display current y
    Wait(50);              //so it doesn't hog the processor
  }
}

task main()
{
  start working;  //start doing stuff
  start display;  //start displaying
}
So it is sort of like this, and another task might to math to "z", and then write "y" to that value. I think I understand now the difference, but I am not sure exactly how to explain it. Basically, this example still lacks the ability to stop another task from using "y", where a mutex would stop it temporarily.

Is this the general idea of what you mean?

Edited code slightly (and again).
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
m-goldberg
Posts: 73
Joined: 29 Sep 2010, 12:05

Re: NXC Multitasking Tutorial

Post by m-goldberg »

As you point out, your variable y doesn't do any blocking, but blocking is what a mutex is all about. I don't think it's a good idea to think of mutexes as in terms of variables. It doesn't hold a value. It is more like an solid token that is passed around, not a bag you can put something into.

Also, in your example, the following would be better:

Code: Select all

task main()
{
   Precedes(one, two);
}
Regards, Morton
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC Multitasking Tutorial

Post by mattallen37 »

m-goldberg wrote:As you point out, your variable y doesn't do any blocking, but blocking is what a mutex is all about. I don't think it's a good idea to think of mutexes as in terms of variables. It doesn't hold a value. It is more like an solid token that is passed around, not a bag you can put something into.

Also, in your example, the following would be better:

Code: Select all

task main()
{
   precedes(one, two);
}
Could you please provide an example program that shows what you mean? I would like to see the it in action, as well as the proper usage of the commands.

Actually, that thought had crossed my mind (though with a capital "P"), but I am just used to doing it this way. I think it is because I use NQC, and I don't think that "Precedes" is a command. What is the difference between the two commands (that accomplish the same thing) anyhow?

Edit: actually, with the updated task names.
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXC Multitasking Tutorial

Post by afanofosc »

Generally a mutex would be used to provide two (or more) things that work simultaneously mutually exclusive access to some shared resource. For example, you don't want two tasks trying to turn motor A on with different motor commands at exactly the same time and you probably don't want two tasks attempting to draw to the LCD at exactly the same time or write to a file at exactly the same time.

Any kind of resource, including a data structure/variable/array or file or motor or LCD, that is shared by two or more tasks that run concurrently (aka simultaneously, in parallel, etc...) should be protected by a mutex. A mutex is a special token or type of variable that you can't do anything with except by the Acquire or the Release commands. If you try to acquire a mutex and some other task already has it acquired then the firmware puts you on hold, as it were, until the mutex is released by its current owner. This synchronizes access to a shared resource across multiple simultaneously executing task.

Wait commands can be used to rank a tasks access to a shared resource as a factor of how long it leaves the mutex unacquired. The longer you refrain from trying to acquire the mutex the lower your "priority" or ranking when it comes to that shared resource.

When a resource is shared by multiple tasks it is crucial that each task keep its access to the resource as short as possible. For example, you would not want to acquire a mutex that is designed for synchronizing access to a particular motor and then wait 60 seconds while the motor turns before finally releasing the mutex. If you write code like that then you really aren't sharing the resource in a good way, though in some specific cases that may be exactly what you really need to do. A multi-task program that controls a robot that avoids falling off the top of a table would not work well if the basic movement task acquired the motors for long periods of time since the task that checks for the table edge and tries to back away from the edge may be blocked at precisely the time it needs to change the robot's direction. But that "avoid the edge" task needs to keep exclusive access to the motors for however long it takes to back up a bit and turn a bit (or whatever you decide the right "avoid" operation should be).

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
HaWe
Posts: 2500
Joined: 04 Nov 2014, 19:00

Re: NXC Multitasking Tutorial

Post by HaWe »

A multi-task program that controls a robot that avoids falling off the top of a table would not work well if the basic movement task acquired the motors for long periods of time since the task that checks for the table edge and tries to back away from the edge may be blocked at precisely the time it needs to change the robot's direction. But that "avoid the edge" task needs to keep exclusive access to the motors for however long it takes to back up a bit and turn a bit (or whatever you decide the right "avoid" operation should be).
Good example .
In those cases a subsumption architecture would be the better approach.
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXC Multitasking Tutorial

Post by mattallen37 »

Thanks, that makes a lot of sense.

Can you please post an NXC example program (or more than one) that uses a mutex? I want to know how to use them, and not just the benefits of using them.
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
Post Reply

Who is online

Users browsing this forum: No registered users and 22 guests