×
A semaphore:
  1. is a predefined channel intended to model the behavior of a software semaphore used to provide limited concurrent access to a shared resource.
  2. has an integer value, the semaphore value, which is set to the permitted number of concurrent accesses when the semaphore is constructed.
    a) if the initial value is one, the semaphore is equivelent to a mutex.

Member functions:
  1. int wait():
    a) If the semaphore value is greater than 0, wait() shall decrement the semaphore value and return.
    b) If the semaphore value is equal to 0, wait() shall suspend until the semaphore value is incremented (by another process).
    c) Shall unconditionally return the value 0.
  2. int trywait():
    a) If the semaphore value is greater than 0, trywait() shall decrement the semaphore value and shall return the value 0.
    b) If the semaphore value is equal to 0, trywait() shall immediately return the value –1 without modifying the semaphore value.
  3. int post():
    a) shall increment the semaphore value.
    b) shall use immediate notification to signal the act of incrementing the semaphore value to any waiting processes.
    c) shall unconditionally return the value 0.
  4. int get_value(): shall return the semaphore value.
run
Learn with Examples, 2020, MIT license
#include <systemc>
using namespace sc_core;
SC_MODULE(SEMAPHORE) {
declares semaphore
  sc_semaphore s;
init semaphore with 2 resources
  SC_CTOR(SEMAPHORE) : s(2) {
register 3 threads competing for resources
    SC_THREAD(thread_1);
    SC_THREAD(thread_2);
    SC_THREAD(thread_3);
  }
  void thread_1() {
    while (true) {
try to obtain a resource
      if (s.trywait() == -1) {
if not successful, wait till resource is available
        s.wait();
      }
      std::cout<< sc_time_stamp() << ": locked by thread_1, value is " << s.get_value() << std::endl;
occupy resource for 1 s
      wait(1, SC_SEC);
release resource
      s.post();
      std::cout<< sc_time_stamp() << ": unlocked by thread_1, value is " << s.get_value() << std::endl;
give time for the other process to lock
      wait(SC_ZERO_TIME);
    }
  }
  void thread_2() {
    while (true) {
try to obtain a resource
      if (s.trywait() == -1) {
if not successful, wait till resource is available
        s.wait();
      }
      std::cout<< sc_time_stamp() << ": locked by thread_2, value is " << s.get_value() << std::endl;
occupy resource for 1 s
      wait(1, SC_SEC);
release resource
      s.post();
      std::cout<< sc_time_stamp() << ": unlocked by thread_2, value is " << s.get_value() << std::endl;
give time for the other process to lock
      wait(SC_ZERO_TIME);
    }
  }
  void thread_3() {
    while (true) {
try to obtain a resource
      if (s.trywait() == -1) {
if not successful, wait till resource is available
        s.wait();
      }
      std::cout<< sc_time_stamp() << ": locked by thread_3, value is " << s.get_value() << std::endl;
occupy resource for 1 s
      wait(1, SC_SEC);
release resource
      s.post();
      std::cout<< sc_time_stamp() << ": unlocked by thread_3, value is " << s.get_value() << std::endl;
give time for the other process to lock
      wait(SC_ZERO_TIME);
    }
  }
};
int sc_main(int, char*[]) {
  SEMAPHORE semaphore("semaphore");
  sc_start(4, SC_SEC);
  return 0;
}
Result:
scheduling pattern: 1&2, then 2&3, then 1&2, then 2&3
thread_1 locks @ 0 s
0 s: locked by thread_1, value is 1
thread_2 locks @ 0 s
0 s: locked by thread_2, value is 0
thread_1 unlocks @ 1 s
1 s: unlocked by thread_1, value is 1
thread_2 unlocks @ 1 s
1 s: unlocked by thread_2, value is 2
thread_3 locks @ 1 s
1 s: locked by thread_3, value is 1
thread_2 locks @ 1 s
1 s: locked by thread_2, value is 0
2 s: unlocked by thread_3, value is 1
2 s: unlocked by thread_2, value is 2
thread_1 locks @ 2 s
2 s: locked by thread_1, value is 1
thread_2 locks at 2 s
2 s: locked by thread_2, value is 0
3 s: unlocked by thread_1, value is 1
3 s: unlocked by thread_2, value is 2
thread_3 locks @ 3 s
3 s: locked by thread_3, value is 1
thread_2 locks @ 3 s
3 s: locked by thread_2, value is 0