# Process synchronization

• Post author:

### 1.0 Problem

Suppose there are n concurrent peer processes, where n > 1. All these processes have a checkpoint, which is an important point in the execution trace of the process. These processes need to be synchronized such that no process crosses its checkpoint before the others have reached their individual checkpoints. For example, a software system might have multiple processes and it might be desirable they all finish their initialization routines before transaction processing can begin.

Figure 1: Concurrent Processes P0 – P4. Each process Pn has a checkpoint at time tn. No process should proceed beyond checkpoint until all processes have reached their individual checkpoints.

### 2.0 Solution

The problem is easily solved using counting semaphores. Suppose there are n processes, where n > 1. There is a semaphore for each process with initial value 0. Once a process reaches a checkpoint it does a V operation on its semaphore (n – 1) times. That is, the value of its semaphore becomes (n – 1). Then, it does a P operation on semaphores of other (n – 1) processes. When this completes, all processes have passed their respective checkpoints and have been synchronized.

### 3.0 Example Program

We have an example program that demonstrates the above solution for three processes. The same program is run as three processes, viz., Process 0, Process 1 and Process 2. Each process does some work and reaches its checkpoint. It, then, synchronizes with other processes. After synchronization, the processes do some arbitrary work.

```/*
*
*   process.c: program to demonstrate process synchronization
*
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <semaphore.h>
#include <unistd.h>
#include <time.h>

#define NUM_PROCESSES 3
#define MAX_SLEEP_TIME 5     // seconds
#define PRIME_MOD 937

sem_t *sem [NUM_PROCESSES];
char buf [128];

int main (int argc, char **argv)
{
int i, my_process_id;

if (argc != 2) {
fprintf (stderr, "Usage: process-id\n");
exit (EXIT_FAILURE);
}
sscanf (argv [1], "%d", &my_process_id);

fprintf (stderr, "(%d): Hello, World!\n", my_process_id);
if (my_process_id < 0 || my_process_id >= NUM_PROCESSES) {
fprintf (stderr, "process id = %d. Out of range\n", my_process_id);
exit (EXIT_FAILURE);
}

// create/open semaphores
for (i = 0; i < NUM_PROCESSES; i++) {
sprintf (buf, "/sem-%d", i);
if ((sem [i] = sem_open (buf, O_CREAT, 0660, 0)) == SEM_FAILED) {
perror ("sem_open"); exit (EXIT_FAILURE);
}
}

time_t now = time (NULL);
srand ((unsigned int) (now % PRIME_MOD));

unsigned int sleep_time;
// sleep for random time
sleep_time = rand () % MAX_SLEEP_TIME;
(void) sleep (sleep_time);

// checkpoint; synchronize
fprintf (stderr, "(%d): Checkpoint, synchronizing ...\n", my_process_id);
//V (sem-id); (n - 1) times
for (i = 0; i < (NUM_PROCESSES - 1); i++) {
if (sem_post (sem [my_process_id]) == -1) {
perror ("sem_post"); exit (EXIT_FAILURE);
}
}

for (i = 0; i < NUM_PROCESSES; i++) {
if (i != my_process_id) {
// P (sem-id)
if (sem_wait (sem [i]) == -1) {
perror ("sem_wait"); exit (EXIT_FAILURE);
}
}
}

fprintf (stderr, "(%d): synchronized. Will do rest of the work.\n", my_process_id);

// sleep for random time
sleep_time = rand () % MAX_SLEEP_TIME;
(void) sleep (sleep_time);

// Remove semaphore
sprintf (buf, "/sem-%d", my_process_id);
if (sem_unlink (buf) == -1) {
}

fprintf (stderr, "(%d): Bye.\n", my_process_id);
exit (0);
}
```

We can compile the above program and run it as three processes, as below.

```\$ ./process 0 & ./process 1 & ./process 2 & ps
[1] 19907
[2] 19908
[3] 19909
(1): Hello, World!
(0): Hello, World!
(2): Hello, World!
PID TTY          TIME CMD
19374 pts/2    00:00:00 bash
19907 pts/2    00:00:00 process
19908 pts/2    00:00:00 process
19909 pts/2    00:00:00 process
19910 pts/2    00:00:00 ps
\$ (0): Checkpoint, synchronizing ...
(1): Checkpoint, synchronizing ...
(2): Checkpoint, synchronizing ...
(2): synchronized. Will do rest of the work.
(0): synchronized. Will do rest of the work.
(1): synchronized. Will do rest of the work.
(0): Bye.
(2): Bye.
(1): Bye.

[1]   Done                    ./process 0
[2]-  Done                    ./process 1
[3]+  Done                    ./process 2
\$
```

### Karunesh Johri

Software developer, working with C and Linux.
Article Rating
Subscribe
Notify of