Number of semaphore keys. created keys are not matching with get and put

Kindly help me to understand how this is possible to get and put the number of keys which is not initialized in new as per given below:

module tb();
  semaphore sem = new(3);
  
  task process_A();
    sem.get(3);
    $display("process_A is started");
    #5ns;
    $display("process_A is completed");
    sem.put(5);
  endtask

  task process_B();
    sem.get(5);  // Accessing more keys than initialized
    $display("process_B is started");
    #5ns;
    $display("process_B is completed");
    sem.put(5);
  endtask
  
  task process_C();
    sem.get(6);  // Accessing more keys than available in the bucket
    $display("process_C is started");
    #5ns;
    $display("process_C is completed");
    sem.put(5);
  endtask
  
  initial begin
    fork
      process_A();
      process_B();
      process_C();
    join_none
  end
endmodule

It gives the below output:

process_A is started
process_A is completed
process_B is started
process_B is completed

When you write semaphore sem = new(3); it initializes the semaphore with 3 keys.

process_A() :

  • sem.get(3) Acquires all 3 available keys.
  • Executes its logic, then calls sem.put(5) returning 5 keys.
  • A semaphore does not restrict you from putting back more keys than were originally acquired.

process_B() :

  • sem.get(5) When this process starts, all keys have been taken by process_A, so it blocks and waits.
  • After process_A completes and puts back 5 keys, the semaphore has enough keys.
  • process_B then resumes execution, successfully acquires 5 keys, and completes its task.

process_C() :

  • sem.get(6)This process attempts to acquire 6 keys.
  • However, at no point does the semaphore hold 6 or more keys (maximum was 5).
  • As a result, process_C waits indefinitely and never proceeds, unless additional keys (at least 6) are put into the semaphore.

Hi Hardik,
Thanks, I understood your points. One more doubt is there:

We are creating 3 keys in new. Then what is the point in putting back 5 keys, we have not created these 2 extra keys. Considering the process_A() only, how we can putting(or put()) which we are not getting . Is it good practice to code in this way.

This is a weakness in the functionality of the semaphore class. Important is you should be aware of this and double-check how many keys you are putting back.

The semaphore class is a primitive construct serving various purposes, such as process synchronization and resource allocation. The user of the semaphore is responsible for managing the allocation of keys. Typically, a semaphore is encapsulated within another class that manages the keys. In most applications, the key count is always set to 1.