More Semaphore Examples

Here, we will take few more examples to understand Semaphore thoroughly.

Example 1:

Assume that we have 3 processes, second process starts only after completing the first and 3rd starts only after completing the 2nd process. Let’s see how we can implement the situation using semaphore.

module test;

  // Declare a semaphore
  semaphore sem;

  // Task for the first process
  task process_1();
    $display("[%0t] Process 1 started.", $time);
    #10; // Simulate process execution time
    $display("[%0t] Process 1 completed.", $time);
    sem.put(1); // Release one semaphore token for the next process
  endtask

  // Task for the second process
  task process_2();
    sem.get(1); // Acquire a semaphore token (wait for Process 1 to complete)
    $display("[%0t] Process 2 started.", $time);
    #15; // Simulate process execution time
    $display("[%0t] Process 2 completed.", $time);
    sem.put(1); // Release one semaphore token for the next process
  endtask

  // Task for the third process
  task process_3();
    sem.get(1); // Acquire a semaphore token (wait for Process 2 to complete)
    $display("[%0t] Process 3 started.", $time);
    #20; // Simulate process execution time
    $display("[%0t] Process 3 completed.", $time);
  endtask

  // Initial block to initialize semaphore and start the tasks
  initial begin
    sem = new(0); // Initialize semaphore with 0 tokens
    fork
      process_1(); 
      process_2(); 
      process_3(); 
    join
    $display("[%0t] All processes completed.", $time);
    $finish;
  end

endmodule

Explanation

  1. Semaphore:
    • A semaphore is initialized with 0 tokens. This ensures that the second and third processes cannot proceed until the first process provides a token, and similarly, the third process waits for the second.
  2. Tasks:
    • process_1():
      • Starts execution.
      • Once completed, it calls sem.put(1) to release one token, signaling that the second process can proceed.
    • process_2():
      • Calls sem.get(1) to wait until it gets a token (from process_1()).
      • Once completed, it releases a token for the third process using sem.put(1).
    • process_3():
      • Waits for a token from process_2() and then executes.
  3. Fork-Join:
    • fork allows all tasks to start concurrently, but the semaphore ensures proper synchronization.
  4. Simulation Output:
[0] Process 1 started.
[10] Process 1 completed.
[10] Process 2 started.
[25] Process 2 completed.
[25] Process 3 started.
[45] Process 3 completed.
[45] All processes completed.