There are three parallel threads running in fork-join_any.
I want to come-out from that when any two threads get completed.
How to do this?
In reply to Sagar Shah:
You can use a semaphore that waits for 2 keys
semaphore s;
s = new(0);
fork
begin : process1
...
s.put(1);
end
begin : process2
...
s.put(1);
end
begin : process3
...
s.put(1);
end
join_none
s.get(2);
disable fork; // kills remaining process
s = null; // removes semaphore (if you plan to reuse s)
In reply to dave_59:
Thanks for quick solution.
Today I came to know actual usage of semaphore.
Is there any solution possible without the use of semaphore?
In reply to amiya957:
There are other solutions like using a simple counter, but they are not considered “thread-safe”. They would work fine in most situations, but the LRM does not guarantee atomic execution when multiple processes are writing to the same variable. i.e. if two process simultaneously execute N=N+1, there is no guarantee that N winds up being incremented by 2.
With today’s tools, I would say this is an impossible situation, but as your code gets more complex, and as tools adopt multi-core technologies, it could happen. So it’s better to code it the safe way.
In reply to dave_59:
Hi Dave ,
Could it possible using Fine-Grain Process Control ? . Particularly " await " and
" process.status != FINISHED "
Also your suggestion regarding counters being " thread unsafe" is Certainly Crucial .
What I am curious to know is what could be the counter be incremented to ( if not by 2 ) .
Since its a blocking statement although there would be no atomic guarantee , wouldn’t the 2nd Incremental Statement always see the Updated Value ( i.e incremented by 1 ) ?
Not arguing , just curious to know
Thanks ,
AGIS
In reply to Etrx91:
Yes, there are a number of ways to accomplish the same, but all require access to a shared memory variable with some sort of process count. Incrementing a location in memory involves three steps: read, modify(increment), write. It’s a blocking assignment statement in the sense that within the same thread, these three steps must occur in order before the next statement executes. But there’s no guarantee that another process could be executing the same steps interweaved with each other.
Hi All,
the above example by using .put will work only if process timings are different, that is
T1 != T2 != T3;
But I have a scenario, where time intervals between all process are same,
that is T1 = T2 = T3;
in this case, as shown the code below, I am interested in only two process. After two process, I should exit the fork, May I know how can I achieve this?
Currently I can see all process are getting executed, but I want any two of them only to be executed.
Kindly suggest
module fork_join_sample;
semaphore sem = new;
task t1;
#5 $display($time,"\t Process_1");
sem.put(1);
endtask
task t2;
#5 $display($time,"\t Process_2");
sem.put(1);
endtask
task t3;
#5 $display($time,"\t Process_3");
sem.put(1);
endtask
initial begin
fork
t1;
t2;
t3;
join_none
$display("OUT OF FORK");
sem.get(2);
disable fork;
end
endmodule
-----------------------
OUTPUT:
xcelium> run
OUT OF FORK
5 Process_1
5 Process_2
5 Process_3
In that case you have a race condition. All three processes terminate at the same time and the disable fork
makes no sense.