Critical section in Direction program node

According to the script manual one should use critical sections only when the enclosed code does not contain time-demanding commands as for example move-commands:

To protect against race conditions and other thread-related issues, support for critical
sections is provided. A critical section ensures the enclosed code can finish running
before another thread can start running. The previous statement is always true, unless
a time-demanding command is present within the scope of the critical section. In such
a case, another thread will be allowed to run. Time-demanding commands include
sleep, sync, move-commands, and socketRead. Therefore, it is important to keep the
critical section as short as possible. The syntax is as follows:
thread myThread():
enter_critical
# Do some stuff
exit_critical
return False
end

However I was analyzing the URScript generated by a Direction command and it starts in this way:

global move_thread_flag_19=0
thread move_thread_19():
  enter_critical
  move_thread_flag_19 = 1
  local towardsPos=calculate_point_to_move_towards(p[0.0,0.0,0.0,0.0,0.0,0.0], [0.0,0.0,-1.0], 0.5)
  movel(towardsPos, a=1.2, v=0.25)
  move_thread_flag_19 = 2
  exit_critical
end
move_thread_flag_19 = 0
move_thread_han_19 = run move_thread_19()

This seems inconsistent with the manual recommendation. Is there a reason for this?

Hi @a.mora,

The manual states that another thread is able to interrupt the critical section if the critical section uses physical time, with is the case here. The statement

Therefore, it is important to keep the
critical section as short as possible

Is in terms of executions that does not uses time. Since the critical section in this situation is blocking for other threads.

Ebbe

Sorry, I have read your answer a lot of times but Iā€™m not sure to understand. I try to explain my doubts with an example. If I have:

thread myThread():
  # Non critical code...
  enter_critical
  # Critical code...
  exit_critical
  return False
end
thrd1 = run myThread()
thrd2 = run myThread()

is it correct to say that:

  1. thrd1 starts running
  2. thrd2 starts running, executes # Non critical code and then sleeps until thrd1 has finished # Critical code, then thrd2 executes # Critical code

?

If it is true, this is the second question: if in # Critical code there is a command like a movej() then thrd2 executes # Critical code before thrd1 has finished to execute # Critical code? If this is true, what is the point of using a critical section?

Hi @a.mora,

I am not sure the answer to your first question is a simple yes. I would not recommend building you reliability on the assumption on the scheduler will start thrd2 before thrd1 hit its critical section or that thrd2 would hit its critical section before thrd1.
But you are correct that the thread that hits its critical section first will complete it(under the circumstances that it does not consume physical time), before the other thread continue execution.

To your second question we can take the direction as example. It is critical because it essential that the movel gets it portion of execution time for each physical timeslot. On the other hand the direction shall not block all other thread for seconds. If they are used for synchronizing communicating with other equipment.
I hope it makes sense. Let me know if that is not the case!

If you have one or two threads where the order of execution is important I will suggest to make use of join or program some flags for synchronizing them.

Do you have a use case where you need to block all other program execution except for your own thread?

Ebbe

1 Like

Thanks for your answer, maybe I lack some knowledge about processes and threads to understand it fully.

But you are correct that the thread that hits its critical section first will complete it(under the circumstances that it does not consume physical time), before the other thread continue execution.

When a thread myThread() is running its critical section, all other threads (including the main program) are blocked or only the threads of type myThread() while they are running the same critical section?

It is critical because it essential that the movel gets it portion of execution time for each physical timeslot.

This is not clear for me. Can you tell me what can happen if movel was outside a critical section? For example the code would be:

thread move_thread_19():
  enter_critical
  move_thread_flag_19 = 1
  local towardsPos=calculate_point_to_move_towards(p[0.0,0.0,0.0,0.0,0.0,0.0], [0.0,0.0,-1.0], 0.5)
  exit_critical
  movel(towardsPos, a=1.2, v=0.25)
  enter_critical
  move_thread_flag_19 = 2
  exit_critical
end

Do you have a use case where you need to block all other program execution except for your own thread?

Not for now, I was only trying to understand the mechanism of the critical section in URScript.

1 Like