1. Global Variable Safety with Multi-tasking

What technique (if any) do I need to use to ensure safety when using global variables with real-time tasks?

For example two real-time tasks need to access a global sequence. Task A will read from configuration file every few minutes and may update (add or remove) some elements in the global sequence. Task B will loop thru the elements in the global sequence performing some operations.

If task B yields to task A and task A changes the number of elements in the sequence, when execution returns to task B that could cause a problem with the "for" loop count?

Do I need to ensure that task B only yields after the for loop is complete to be safe? something like:

procedure task_B() 
while 1 
for i = 1 to length(seqGlobal) do 
 DoSomeStuff(seqGlobal[i]) 
end for 
task_yield() 
end while 
end procedure 

Or are their other options which will allow yield more often within the for loop?

thanks, Casey

new topic     » topic index » view message » categorize

2. Re: Global Variable Safety with Multi-tasking

cp said...

What technique (if any) do I need to use to ensure safety when using global variables with real-time tasks?

For example two real-time tasks need to access a global sequence. Task A will read from configuration file every few minutes and may update (add or remove) some elements in the global sequence. Task B will loop thru the elements in the global sequence performing some operations.

If task B yields to task A and task A changes the number of elements in the sequence, when execution returns to task B that could cause a problem with the "for" loop count?

Do I need to ensure that task B only yields after the for loop is complete to be safe?

If you're going to use a for loop, then yes. The upper bound is calculated when the loop is started, so it wouldn't notice the change in the sequence. Alternatively, you could use something like a while loop, though that would be more complicated, because you'd have to be able to know if your index variable needs to be incremented or decremented depending on how the sequence changed.

It's hard to give more detailed advice without knowing more about what exactly you're trying to do.

Matt

new topic     » goto parent     » topic index » view message » categorize

3. Re: Global Variable Safety with Multi-tasking

The solution for this kind of problem has already been established in the network model,where a variable or an element of a database is locked. If you want to use a global variable sequence in a task that is likely to be dynamically changed by another task, a good solution would be to look ahead at one or two elements (depending upon the likelihood of them being changed,) and use the appropriate one for your program.

Let us say, your loop is working with the 4th element of the sequence.
Instead of just picking up the fourth element, you picking it up from the stored one when you were doing the 3rd element, compare with the current, do a condition decision which one you will use and at the same time time you also store the value of the 5th and 6th element.

It will all depend upon what the interfering task is likely to do to the elements of a sequence.

Just my two pence worth.

new topic     » goto parent     » topic index » view message » categorize

4. Re: Global Variable Safety with Multi-tasking

It sounds like you need to use a queue. Each task should be adding and removing objects to/from the queue and working on a local variable. This is a much safer way to prevent them from stomping all over each other.

sequence queue = {} 
 
procedure enqueue( object x ) 
 
    -- add an object into the queue 
    queue = append( queue, x ) 
 
end procedure 
 
function dequeue() 
-- (assume we've checked length(queue) elsewhere) 
 
    -- pull the first object from the queue 
    object x = queue[1] 
 
    -- remove this object from the queue 
    queue = queue[2..$] 
 
    -- return the object 
    return x 
end function 
 
procedure task_1() 
 
    while doing_stuff do 
 
        -- do stuff and queue an item 
 
        object x = some_function() 
        enqueue( x ) 
 
        task_yield() 
    end while 
 
end procedure 
 
procedure task_2() 
 
    while 1 do 
        -- loop forever 
 
        while length( queue ) = 0 do 
            -- wait until we have something to work on 
            task_yield() 
        end while 
 
        -- get the next object 
        object x = dequeue() 
 
        -- do something with this object 
 
        task_yield() 
    end while 
 
end procedure 

-Greg

new topic     » goto parent     » topic index » view message » categorize

5. Re: Global Variable Safety with Multi-tasking

ghaberek said...

It sounds like you need to use a queue. Each task should be adding and removing objects to/from the queue and working on a local variable. This is a much safer way to prevent them from stomping all over each other.

For such a task, you might look at std/stack.e. In particular, use a FIFO stack.

Matt

new topic     » goto parent     » topic index » view message » categorize

6. Re: Global Variable Safety with Multi-tasking

mattlewis said...
ghaberek said...

It sounds like you need to use a queue. Each task should be adding and removing objects to/from the queue and working on a local variable. This is a much safer way to prevent them from stomping all over each other.

For such a task, you might look at std/stack.e. In particular, use a FIFO stack.

Matt

Thanks for the replies. Both the while loop instead of for loop and the queue technique should both work for me.

thanks again,

Casey

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu