Process not terminated causing a "too many processes" error - spin

It is my first time using spin and I am encountering an error that I do not understand. I am aware that the processes terminates in the same order they are created thus I don't understand why the process of the function I call in a loop does not terminate.
Here is a very simplified version of my code :
int limit;
proctype f() {
limit--;
printm(limit)
run g();
}
proctype g() {
limit++;
}
init {
limit = 5;
do
:: (limit > 0) -> run f();
od
}
The limit variable is created so there is not more than 5 processes f running at the same time. The processes g does terminate but f don't. So I get the error : too many processes
I would like to know why f does not terminate and if there is another way to do that?

Your question is based on a false premise: it isn't true that there are never more than 5 processes in your system.
In fact, there can be any number of processes of type f(), because there is absolutely no guarantee that the instruction:
limit--;
is executed right after the process is created with
run f();
It is possible that the process scheduler lets init() execute for several (tens, hundreds, more..) loop iterations before it preempts it and gives a chance to some f() to execute anything.
If a process g() is created, then this can clearly terminate.
If a process f() is created, this can terminate only if there aren't already 255 processes in the system and it is the process f() with the highest pid, so that it does not have to wait for other processes.
The init() process can never terminate.
As a possible fix, you might want to try to look into _nr_pr:
int limit = 5;
proctype f() {
printm(limit)
}
init {
do
:: (_nr_pr <= (limit + 1)) ->
run f();
od
}

Related

why while loop is not needed in sem_wait?

I am trying to compare produer consumer problem implementation using cond variable and semaphores.
Implementation using cond variable:
acquire(m); // Acquire this monitor's lock.
while (!p) { // While the condition/predicate/assertion that we are waiting for is not true...
wait(m, cv); // Wait on this monitor's lock and condition variable.
}
// ... Critical section of code goes here ...
signal(cv2); -- OR -- notifyAll(cv2); // cv2 might be the same as cv or different.
release(m);
Implementation using semaphore:
produce:
P(emptyCount)
P(useQueue)
putItemIntoQueue(item)
V(useQueue)
V(fullCount)
why semaphore implementation is not using while loop to check the condition like in cond variable implementation.?
while (!p) { // While the condition/predicate/assertion that we are waiting for is not true...
wait(m, cv); // Wait on this monitor's lock and condition variable.
}
Why do you need a while loop while waiting for a condition variable
Grabbing a semaphore does use a tight loop internally, just like the cond version, but it yields execution back to the scheduler in each iteration to not waste resources like a busy loop would.
When the scheduler has executed some other process for a while, it yields execution back to your thread. If the semaphore is available now, it is grabbed; otherwise it yields back to the scheduler to let some other process run some more before retrying.

How many processes are created in the program when using fork() in a condition?

I'm having trouble to understand how fork() works when it is used as a condition. I know that fork() creates a child process as an exact copy of the parent process. My question is, how many processes are created in the following program? Here is the code:
int global = 0;
int main() {
while(global < 5 && !fork()) {
sleep(1);
global += 1;
}
printf("%d\n", global);
return 0;
}
I was a assuming that for each fork() call, every process that is already running will create a child process and continue like that as long as the variable global reaches the value of 5.
The fork() call returns 0 in the child and the pid of the child in the parent.
Therefore, in the parent, the second condition will evaluate to 0, and the loop will exit and then print. In the child, the second condition will evaluate to non-zero, and the loop will fork again with a higher value of global (which is inherited).
Thus, we will see a total of 5 new processes in addition to the parent.

Go - How to know when an output channel is done

I tried to follow Rob Pike's example from the talk 'Concurrency is not parallelism' and did something like this:
I'm starting many go routines as workers that read from an input channel, perform some processing and then send the result through the output channel.
Then I start another go routine that reads data from some source and send it to the workers through their input channel.
Lastly I want to iterate over all of the results in the output channel and do something with them.
The problem is that because the work is split between the workers I don't know when all of the workers have finished so I can stop asking the output channel for more results, and my program could end properly.
What is the best practice to know when workers have finished sending results to an output channel?
I personally like to use a sync.WaitGroup for that. A waitgroup is a synchronized counter that has three methods - Wait(), Done() and Add(). What you do is increment the the waitgroup's counter, pass it to the workers, and have them call Done() when they're done. Then you just block on the waitgroup on the other end and close the output channel when they're all done, causing the output processor to exit.
Basically:
// create the wait group
wg := sync.WaitGroup{}
// this is the output channel
outchan := make(chan whatever)
// start the workers
for i := 0; i < N; i++ {
wg.Add(1) //we increment by one the waitgroup's count
//the worker pushes data onto the output channel and calls wg.Done() when done
go work(&wg, outchan)
}
// this is our "waiter" - it blocks until all workers are done and closes the channel
go func() {
wg.Wait()
close(outchan)
}()
//this loop will exit automatically when outchan is closed
for item := range outchan {
workWithIt(item)
}
// TADA!
Please can I firstly clarify your terminology: a misunderstanding on the ends of channels could cause problems later. You ask about "output channels" and "input channels". There is no such thing; there are only channels.
Every channel has two ends: the output (writing) end, and the input (reading) end. I will assume that that is what you meant.
Now to answer your question.
Take the simplest case: you have only one sender goroutine writing to a channel, and you only have one worker goroutine reading from the other end, and the channel has zero buffering. The sender goroutine will block as it writes each item it until that item has been consumed. Typically this happens quickly the first time. Once the first item has passed to the worker, the worker will then be busy and the sender will have to wait before the second item can be passed over. So a ping-pong effect follows: either the writer or the reader will be busy but not both. The goroutines will be concurrent in the sense described by Rob Pike, but not always actually executing in parallel.
In the case where you have many worker goroutines reading from the channel (and its input end is shared by all of them), the sender can initially distribute one item to each worker, but then it has to wait whilst they work (similar to the ping-pong case described above). Finally, when all items have been sent by the sender, it has finished its work. However, the readers may not, yet, have finished their work. Sometimes we care that the sender finishes early, and sometimes we don't. Knowing when this happens is most easily done with a WaitGroup (see Not_a_Golfer's answer and my answer to a related question).
There is a slightly more complex alternative: you can use a return channel for signalling completion instead of a WaitGroup. This isn't hard to do, but WaitGroup is preferred in this case, being simpler.
If instead the channel were to contain a buffer, the point at which the sender had sent its last item would happen sooner. In the limit case when the channel has one buffer space per worker; this would allow the sender to complete very quickly and then, potentially, get on with something else. (Any more buffering than this would be wasteful).
This decoupling of the sender allows a fully asynchronous pattern of behaviour, beloved of people using other technology stacks (Node-JS and the JVM spring to mind). Unlike them, Go doesn't need you to do this, but you have the choice.
Back in the early '90s, as a side-effect of work on the Bulk Synchronous Parallelism (BSP) strategy, Leslie Valiant proved that sometimes very simple synchronisation strategies can be cheap. The crucial factor is that there is a need for enough parallel slackness (a.k.a. excess parallelism) to keep the processor cores busy. That means there must be plenty enough other work to be done so that it really doesn't matter if any particular goroutine is blocked for a period of time.
Curiously, this can mean that working with smaller numbers of goroutines might require more care than working with larger numbers.
Understanding the impact of excess parallelism is useful: it is often not necessary to put extra effort into making everything asynchronous if the network as a whole has excess parallelism, because the CPU cores would be busy either way.
Therefore, although it is useful to know how to wait until your sender has completed, a larger application may not need you to be concerned in the same way.
As a final footnote, WaitGroup is a barrier in the sense used in BSP. By combining barriers and channels, you are making use of both BSP and CSP.
var Z = "Z"
func Loop() {
sc := make(chan *string)
ss := make([]string, 0)
done := make(chan struct{}, 1)
go func() {
//1 QUERY
slice1 := []string{"a", "b", "c"}
//2 WG INIT
var wg1 sync.WaitGroup
wg1.Add(len(slice1))
//3 LOOP->
loopSlice1(slice1, sc, &wg1)
//7 WG WAIT<-
wg1.Wait()
sc <- &Z
done <- struct{}{}
}()
go func() {
var cc *string
for {
cc = <-sc
log.Infof("<-sc %s", *cc)
if *cc == Z {
break
}
ss = append(ss, *cc)
}
}()
<-done
log.Infof("FUN: %#v", ss)
}
func loopSlice1(slice1 []string, sc chan *string, wg1 *sync.WaitGroup) {
for i, x := range slice1 {
//4 GO
go func(n int, v string) {
//5 WG DONE
defer wg1.Done()
//6 DOING
//[1 QUERY
slice2 := []string{"X", "Y", "Z"}
//[2 WG INIT
var wg2 sync.WaitGroup
wg2.Add(len(slice2))
//[3 LOOP ->
loopSlice2(n, v, slice2, sc, &wg2)
//[7 WG WAIT <-
wg2.Wait()
}(i, x)
}
}
func loopSlice2(n1 int, v1 string, slice2 []string, sc chan *string, wg2 *sync.WaitGroup) {
for j, y := range slice2 {
//[4 GO
go func(n2 int, v2 string) {
//[5 WG DONE
defer wg2.Done()
//[6 DOING
r := fmt.Sprintf("%v%v %v,%v", n1, n2, v1, v2)
sc <- &r
}(j, y)
}
}

In SPIN/Promela, how to receive a MSG from a channel in the correct way?

I read the spin guide yet there is no answer for the following question:
I have a line in my code as following:
Ch?x
where Ch is a channel and x is channel type (to receive MSG)
What happens if Ch is empty? will it wait for MSG to arrive or not?
Do i need to check first if Ch is not empty?
basically all I want is that if Ch is empty then wait till MSG arrives and when it's arrive continue...
Bottom line: the semantics of Promela guarantee your desired behaviour, namely, that the receive-operation blocks until a message can be received.
From the receive man page
EXECUTABILITY
The first and the third form of the statement, written with a single
question mark, are executable if the first message in the channel
matches the pattern from the receive statement.
This tells you when a receive-operation is executable.
The semantics of Promela then tells you why executability matters:
As long as there are executable transitions (corresponding to the
basic statements of Promela), the semantics engine will select one of
them at random and execute it.
Granted, the quote doesn't make it very explicit, but it means that a statement that is currently not executable will block the executing process until it becomes executable.
Here is a small program that demonstrates the behaviour of the receive-operation.
chan ch = [1] of {byte};
/* Must be a buffered channel. A non-buffered, i.e., rendezvous channel,
* won't work, because it won't be possible to execute the atomic block
* around ch ! 0 atomically since sending over a rendezvous channel blocks
* as well.
*/
short n = -1;
proctype sender() {
atomic {
ch ! 0;
n = n + 1;
}
}
proctype receiver() {
atomic {
ch ? 0;
n = -n;
}
}
init {
atomic {
run sender();
run receiver();
}
_nr_pr == 1;
assert n == 0;
/* Only true if both processes are executed and if sending happened
* before receiving.
*/
}
Yes, the current proctype will block until a message arrives on Ch. This behavior is described in the Promela Manual under the receive statement. [Because you are providing a variable x (as in Ch?x) any message in Ch will cause the statement to be executable. That is, the pattern matching aspect of receive does not apply.]

Process Synchronisation using semaphores

Here is the problem.
I want two processes to occur alternatively, the complete problem is here.
Q. In a system ther are two processes named A and B.When the system starts,the process A executes twice then process B executes once.The Process B cannot execute until process A has executed twice. Once Process A haas executed it can not execute again until process B has executed. The restriction mentioned above allows the process A and B to execute in the following manner.
AABAABAAB...
Write the pseudocode for Process A and B using counting semaphore to achieve the desired synchronisation.
Here is my attemp for this.
Solution:
Process A
var a=1,b=0,i;
begin
repeat
wait(a);
for(i=0;i<2;i++)
printf("A"); // conidering this is what process a does.
signal(b);
forever
end
Process B
begin
repeat
wait(b);
printf("B"); //considering this is what process B does.
signal(a);
forever
end
Is this correct?
An alternative solution would be:
Semaphore as = 1;
Semaphore bs = 0;
A() {
int counter = 0;
while(TRUE) {
if(counter % 2 == 0)
P(as);
print("A"); // and whatever A does
counter++;
if(counter % 2 == 0)
V(bs);
}
}
B() {
P(bs);
print("B"); // and whatever B does
V(as);
}
The idea is that A waits for B on every 2nd turn (execept the 0th).
I think that the general idea is correct, but the terminology is rather strange. Wait-signal pair is usually used for condition variables (although e.g. POSIX semaphorese use post/wait).
I suggest you substitue the wait with semaphore_down and signal with semaphore_up.