View unanswered posts | View active topics It is currently Tue Sep 23, 2014 11:29 pm






Reply to topic  [ 10 posts ] 
How to use tasks safely? 
Author Message
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
Since I can only see a partial program from your picture, I can only guess what had happened. The Coord structure could be accessed by different tasks. What if Coord.X and/or Coord.Y changed right after Cell_IsExist returned true. Since your debug stream is printed inside Cell_IsExist, it could be valid at that moment.

If the Coord structure can be accessed by multiple tasks, it doesn't matter if only one of them writes to it, it is a shared resources and must be protected when accessed. For example, you could do this:
Code:
bool Cell_IsFree(COORD &Coord)
{
    bool result = false;

    hogCPU();
    if (Cell_IsExist(Coord))
    {
        ubyte u = Home.Cell[Coord.X][CoordY].Info;
        result = !(u & (CELL_WALL|CELL_BUMP));
    }
    releaseCPU();
    return result;
}

But of course, what if the caller of Cell_IsFree is also accessing Coord after calling Cell_IsFree? In order to multi-task safely, you need to consolidate the accesses to share resources into a small number of functions (preferably one) and you need to put hogCPU and releaseCPU around the access to make sure nobody else is changing it in the middle.


Wed Feb 15, 2012 5:31 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
Like I said in other threads before, I can hardly find any scenarios that require using tasks. We have written an entire object oriented library simulating multiple tasks using only the main task. This is called cooperative multi-tasking. Since it is really just the main task, there is no resource contention to deal with. Like you said, the way RobotC is architected makes it really difficult to write programs a certain way since we are used to using standard ANSI C and assuming local variables on the stack etc. So avoiding tasks is my way to work around many issues.


Thu Feb 16, 2012 5:38 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
miki wrote:
Till now, for my robot, I had in mind:
  • 1 task (with high priority) managing motors left and right, contact sensor (as bumper), compass sensor and odometry (20% done)
  • 1 task managing turret motor, US and light sensor. (70% done)
  • 1 task managing the robot representation of its environment, mapping, pathfinding, etc (80% done)
  • 1 task managing a kind of brain, (goal assignation, moods) (0% done)
  • 1 task managing display, BT, and debug stuff. (10% done)
And, as main data shared resource, a big array where each cell represents a 33cmx33cm square and its info (wall? door? ...).

Before giving up with tasks, I would like to have deeper information on their implementation and limitation in RobotC, in order to adapt smartly this architecture.
Quote:
We have written an entire object oriented library simulating multiple tasks using only the main task.
Would it be possible to see this code and get some inspiration ?
Best regards.
Miki.

Sure, here is the code for the library as well as some robot code that uses it.
http://proj.titanrobotics.net/hg/Ftc/20 ... 8dbb95c68b
You may want to take a look at GobbMobile. As you can see, the main task is basically a cooperative multi-tasking scheduler. It cycles through four tasks: HighFreqTasks, InputTasks, MainTasks and OutputTasks. HighFreqTasks is called as fast as it could in the main robot loop. This performs tasks that require high precision such as integrating gyro or accelerometer. The other three task categories are called once every LOOP_TIME (equivalent of a time slice). InputTasks is for interacting with the environment such as reading user input (e.g. joystick) and sensors. Then the MainTasks is called to perform main calculation according to the sensor inputs. Lastly, OutputTasks is called to perform real actions such as programming the motors. The trick of using cooperative multi-tasking is that you should never have any wait loop or wait statements in any of the tasks or in the functions that called by these tasks. If the code needs to wait for something to happen, it uses a State Machine (one of the library modules), meaning that it will remember where it left off and return so that other tasks can run (hence "cooperative"). The next time when the task is called again, it will check the wait condition and continue the task from where it was left off. The state machine is maintained similar to task states. If task is waiting for something, the state machine is put into "Not Ready" state. The transition between "Not Ready" and "Ready" is event driven. When the condition that the state machine is waiting for occurs, an event is signaled. This will transition the state machine to "Ready" state as well as advancing it to the next state. Also note that everything in the library are objects. So you could have multiple sensors or subsystems. Let me know if you have any questions.


Thu Feb 16, 2012 2:47 pm
Profile
Creator
Creator

Joined: Fri Feb 09, 2007 9:21 am
Posts: 615
Post Re: How to use tasks safely?
All the "native" robotc intrinsic functions are multi-task thread safe. Specifically they run to completion and cannot be interrupted by another user task. So things like the screen drawing functions or debug stream utilities work "perfectly" in a multi-task environment.

Of course you can still screw up with multi-tasking and some intrinsic functions that are intended to take multiple time slices. Easiest example I can think of is two tasks boths trying to peform I2C operations on the same sensor port. Or one task zeroing a motor encoder while a different task is reading the encoder and doesn't handle this case!

Semaphones were introduced to handle criticical sections in code. You can also use task priorities to prevent some of the conflicts that occur -- a runnable higher priority task will block a lower priority task from running.

The lack of re-entrant functions is being addressed. Hopefully new version of ROBOTC this summer that support re-entrant functions and better pointer support.


Wed Feb 29, 2012 10:31 am
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
Dick Swan wrote:
The lack of re-entrant functions is being addressed. Hopefully new version of ROBOTC this summer that support re-entrant functions and better pointer support.

That's great news but can you elaborate on how re-entrant functions are being addressed? Also, by "better pointer support", would it be full pointer support or just partial support. For example, could it handle function pointers as well as data pointers? How about passing array as a pointer to the first element to a function?
Can't wait for the new version. :)


Wed Feb 29, 2012 3:10 pm
Profile
Moderator
Moderator
User avatar

Joined: Tue Sep 14, 2010 9:19 pm
Posts: 496
Post Re: How to use tasks safely?
Please tell us that function pointers will be supported :D I can't wait to see the frameworks and libraries that people will build if they are.

_________________
sudo rm -rf /


Wed Feb 29, 2012 3:25 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
Yep, if function pointer is supported, I can finally implement full event callbacks without hacks. And our library will be a lot more object oriented.


Wed Feb 29, 2012 3:35 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
From my point of view, to support "unlimited" re-entrance of functions, you need some sort of linkage storage (actually it is not really unlimited, it is limited by the size of the linkage storage). Generally, that is a stack. Since I had an impression that adding stack support in RobotC was way too much work (at least I was told numerous times), I am worrying about the problem being addressed another way. That's why I asked. That could mean there will be some other limitations.


Wed Feb 29, 2012 6:38 pm
Profile
Guru
User avatar

Joined: Sun Nov 15, 2009 5:46 am
Posts: 1347
Post Re: How to use tasks safely?
miki wrote:
MHTS wrote:
... but can you elaborate on how re-entrant functions are being addressed?

@MHTS: you certainly know how works a compiler ;-).

In college, I studied OS, compilers and databases. I wrote the first ACPI compiler. :)
miki wrote:
One of the most common practice is (in few words): to use the stack frame to store function parameters in it, followed by the return address and then by the local variables. I hope this method will be implemented for this future RobotC release.

Another way is: to store function arguments in the processor registers but in this case the compiler has to push (in the stack) those registers before using them and to pop (from the stack) them after the return. It's less flexible.

Yes, both ways are using stack implementation. In fact, it is not uncommon to use a combination of stack and processor registers to pass function parameters. For example, in Intel/AMD 64-bit processor implementation, the first four function parameters are passed in registers. If the function has more than 4 parameters, they are passed on the stack. The stack also has reserved space for the 4 register parameters in case it needs to re-use those registers in the function.


Wed Feb 29, 2012 6:56 pm
Profile
Rookie

Joined: Fri Apr 15, 2011 10:29 am
Posts: 37
Post Re: How to use tasks safely?
Dick Swan wrote:
All the "native" robotc intrinsic functions are multi-task thread safe. Specifically they run to completion and cannot be interrupted by another user task. So things like the screen drawing functions or debug stream utilities work "perfectly" in a multi-task environment.

Of course you can still screw up with multi-tasking and some intrinsic functions that are intended to take multiple time slices. Easiest example I can think of is two tasks boths trying to peform I2C operations on the same sensor port. Or one task zeroing a motor encoder while a different task is reading the encoder and doesn't handle this case!

Semaphones were introduced to handle criticical sections in code. You can also use task priorities to prevent some of the conflicts that occur -- a runnable higher priority task will block a lower priority task from running.

The lack of re-entrant functions is being addressed. Hopefully new version of ROBOTC this summer that support re-entrant functions and better pointer support.


That's fantastic news Dick!


Wed Feb 29, 2012 10:45 pm
Profile
Display posts from previous:  Sort by  
Reply to topic   [ 10 posts ] 

Who is online

Users browsing this forum: No registered users and 2 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  



Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.