Tasks, synchronization, messaging
Page 1 of 1

Author:  sessyargc [ Fri Mar 09, 2007 12:28 am ]
Post subject:  Tasks, synchronization, messaging

I'm a new RobotC user.

After reading the sample applications included in RobotC, I had the impression that multiple tasks/threads are possible.

Upon further reading and playing, I checked the available intrinsics defined in RobotC but I was unable to find information regarding synchronization (semaphores) and messaging (message queues) primitives.

Are these primitives support or will be supported in future releases?

Author:  sessyargc [ Thu Mar 15, 2007 10:11 am ]
Post subject: 

hope a developer or an experienced user can provide the needed information

Author:  Dick Swan [ Fri Mar 23, 2007 2:27 pm ]
Post subject: 

There is a sample program included in standard RobotC that includes multiple tasks. It's called "NXT Task Test.c" and shows starting up five extra tasks.

It's very simple simple. You simply write a task using the "task" keyword in the declaration. You can then start and stop tasks with the "StartTask" and "StopTask" functions.

Make sure you've enable "Advanced" menus. Then double click on the "Task Control" item in the code templates window -- it's the left vertical pane in the main RobotC window. This will popup a HTML page containing the above and more.

Author:  sessyargc [ Fri Mar 23, 2007 7:11 pm ]
Post subject: 

Yup I think I've seen that sample application.

(I'm at work now so I don't have RobotC handy)

If indeed were talking about the same application, I noticed in the sample that a variable was being incremented but without locks (ie semaphores). Are these operations atomic on the NXT/RobotC firmware thus not requiring a lock?

Sorry if this is too technical. I just realized that most RobotC users might be hobbyists and don't write embedded code for a living.

Author:  SuntzuMaster [ Sun Apr 15, 2007 8:57 am ]
Post subject: 


As soon as you deal with thread(s) and / or task(s) the O/S must provide a way to serialize access to a variable(s). As you know when the same variable is updated in different task(s) then it is more than critical to ensure that the variable is updated only by one task at a time other task(s) must wait until the the current task release the "Lock". Does someone at ROBOTC.NET knows if the ROBOTC OS/FIRMWARE support this feature?


Author:  HoTWiReZ [ Tue Apr 17, 2007 10:28 am ]
Post subject: 

Well, while my understanding of RobotC is still somewhat limited, it would seem that since there is only one copy of any variable contained in a function, the best thing you could use for a lock would be an int or bool global variable that can be read/written from every task. The task that needs to lock the variable just changes its value, and the task that wants to wait for the lock to be available again just checks it in a while loop or something. I've tried to implement it, but abandoned the attempt. Just make sure that you endtimeslice in the while loop to help keep the task that you want working working.

I hope this isn't too abstract or simplified to be of any help, because I no longer have my source for that..

Author:  sessyargc [ Tue Apr 17, 2007 8:54 pm ]
Post subject: 

It is actually hard to properly implement these synchronization primitives. Most of the time OS support is required to properly implement these primitives.

You can not just have a global variable that can be read/written by every task. For example, you have 3 tasks, t1, t2 and t3, which accesses a resource that you are locking. If t1 has the lock, and both t2 and t3 are already waiting for the resource, who gets to lock the resource once t1 releases/updates the global variable? It is possible that both t2 and t3 will read the global variable as available and so they both access the resource!

I originally asked this question because NXC/NBC has support for mutexes and actually the Lego Executable File Specification describes support for mutexes.

Author:  HoTWiReZ [ Tue Apr 17, 2007 10:40 pm ]
Post subject: 

My case only had one task operating on the lock, and the main was just checking to see when it was released so that it would know it could continue. If you want to use more tasks then I guess it would be a good idea to do something like:


//Start of section needing lock
nSchedulePriority = kHighPriority;
//To disallow other tasks from being scheduled.
  //enable interrupts and release control since lock is not available
   nSchedulePriority = kDefaultTaskPriority;

  //disable interrupts for the next check
   nSchedulePriority = kHighPriority;
//High priority will still be in effect here no matter what
lock = true;

//allow interrupts again since other tasks know that lock is taken
nSchedulePriority = kDefaultTaskPriority;

//Do Work..

//disable interrupts for lock release
nSchedulePriority = kHighPriority;
lock = false;
//enable interrupts again to return to normal operation
nSchedulePriority = kDefaultTaskPriority;

This may be too much or too simplistic, but I think it should work.. Maybe the parts with kDefaultTaskPriority will need an endtimeslice too, but I haven't tested this code yet, so I don't know.

I forgot to mention that I know that the kHighPriority part works as far as keeping any other tasks from grabbing the cpu.. I had a task use that when checking the light sensor (for table edge/stair detection) and set the priority to high at the start to try to have the task run more often, but the task was the only one to run at all once it was started by main(). So, it seems that there aren't any sort of round robin or fair play algorithms being used with the task scheduler. There's probably documentation saying that but I can't be sure.

Added comments to the code and added the endtimeslice() to the while loop to avoid wasted checks.

Author:  sessyargc [ Wed Apr 18, 2007 12:52 am ]
Post subject: 

In its simplest form HoTWiRez code might work, but there might be starvation issues i.e. a low priority task might not be able to get the lock because the task with the higher priority would be the one always getting it.

Am not sure how the Lego firmware implements its priorities so I could only guess here.

Hope RobotC will support mutexes soon.

Author:  SuntzuMaster [ Wed Apr 18, 2007 12:17 pm ]
Post subject: 

using a global variable to track what task is currently holding the lock
is not very efficient and won't work. The OS/FIRMWARE API used to serialize access to a resource that cannot be shared not only provide lock but also a queueing mechanims that will ensure that the waiting tasks will get access in the right order.

Author:  HoTWiReZ [ Wed Apr 18, 2007 9:14 pm ]
Post subject: 

Suntzu, this implementation doesn't include a way to check to see what task is holding the lock. Really, it relies on each task to make sure it checks the lock just as in the code above and to release the lock as soon as it is finished with a critical section. This implementation is probably the simplest one that I will be able to find from my operating systems class, but I think it has everything that someone using robotc would need. Also, as robotc is currently, most variables are semi-global anyhow, in that they're always sitting in a static memory position anyhow (at least as I understand it). The only thing this is meant to do is to make sure that only one task can use a locked variable at a time.

Author:  SuntzuMaster [ Thu Apr 19, 2007 8:17 am ]
Post subject: 

Hi HotWiReZ,

I understand your code and your point of view I have been O/S system engineer for the past 25 years and I just decided to look at robotics, in fact I always was interested by this topic. I am building a navigation system for my small bot that is based on a surrounding environment analysis and on a very precize bot positionning (I had to find the best way to achieve a motor control that is able to stop at the exact computed angle). My next challenge is to design an algorythm that could be used with the US sensor for objects mapping ( I am currently testing that piece of code). Obviously, I am using multitasking/threading and the question about lock was linked with the fact that I have implemented a circular buffer queue to store motion control command then because of the producer / consumer model it is very important to insure that when the producer update the queue that the consumer won't try to read the queue and to update the queue indexes...

I have another question, do you know
I got some information on their products and it seems that company provide the best in class robotics building stuff...(I guess that they are the main LEGO competitor?).

have a good day.

Author:  Dick Swan [ Sun May 06, 2007 10:38 pm ]
Post subject: 

Do a search on the forum for "synchronization". I posted a reply a few days ago on this topic.

RobotC does not currently have native "synchronization" primitive. But this is very easy to add because the function "++X" is a single indivisible opcode. SO you can implement a lock by incrementing a counter and checking if the value after incremented is "1". If not, then decrement the value, wait and try again. There is no chance that the "++" or "--" will get interrupted in mid-stride!

Page 1 of 1 All times are UTC - 5 hours [ DST ]
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group