[ home ] [ math / cs / ai / phy / as / chem / bio / geo ] [ civ / aero / mech / ee / hdl / os / dev / web / app / sys / net / sec ] [ med / fin / psy / soc / his / lit / lin / phi / arch ] [ off / vg / jp / 2hu / tc / ts / adv / hr / meta / tex ] [ chat ] [ wiki ]

Viewing source code

The following is the source code for post >>>/os/2

\textbf{What is a semaphore?}
In programming, a semaphore is a simple integer with two oprations: \`++\` (increment, singal, post, \[V(s)\]) and \`--\` (decrement, wait, \[P(s)\]). Unlike a simple integer, however, it has a special proprety around the value zero: 

\begin{enumerate}
\item (--) If you are a thread (or a task, or a process) and you attempt to decrement a semaphore that's already zero, the semaphore value stays zero, but  you get blocked. The only way you can get unblocked is if somebody unblocks you by attempting to increment the semaphore. Otherwise - if the semaphore value is greater than zero - its value is decremented by one and you continue your execution.
\item (++) If you are a thread (or a task, or a process) and you attempt to increment a semaphore, then its value will be incremented by one ONLY IF the value of the semaphore is greater than zero OR if it's zero and there are no blocked threads on the semaphore.  If the semaphore value is zero and there blocked threads (i.e. they attempted to decrement it bellow zero) then the semaphore value stays zero, but one thread is unblocked. In any case, the execution of those threads that call an increment 
\end{enumerate}
It's not possible for semaphore value to go bellow zero, since any attempt to decrement it bellow zero will get you blocked. Similarly, it's not possible to have threads blocked on a semaphore of value greater than zero, since those threads would have to be unblocked first before incrementing it above zero.

A pseudo-C++ code of how a semaphore works is:
```
class Sem {
    volatile int m_lock;
    int m_value;
    queue<thread> m_queue;
public:
    Sem(int value) : m_value (value), m_lock(0) {}
    
    void wait() {
        lock(&m_lock);
        if (m_value > 0) {
            m_value -= 1;
        } else if (m_value == 0) {
            m_queue.push(thread_running());
            block(thread_running());
        }
        unlock(&m_lock);
    }
    
    void post() {
        lock(&m_lock);
        if (m_value > 0) {
            m_value += 1;
        } else if (m_value == 0) {
            if (m_queue.size() == 0) {
                m_value += 1;
            } else {
                Thread thread = m_queue.pop();
                unblock(thread);
            }
        }
        unlock(&m_lock);
    }
};
```
\`lock()\` could be implemented using a busy wait \`while (test_and_set(&m_lock) == 1);\` while \`unlock()\` could be implemented as a simple \`m_lock = 0;\`.

\`block()\` could be also implemented with a busy wait \`while (__blocked);\`,  while \`unblock()\` could break that loop e.g. with \`__blocked = 0;\`, but every thread would have to have its own \`volatile int __blocked;\` variable.

\textbf{POSIX semaphore}
POSIX semaphores can be included with \`#include <semaphore.h>\` which gives us 4 functions are of importance:
```
sem_init();     // create a semaphore with initial value
sem_post();     // signal (increment)
sem_wait();     // wait   (decrement)
sem_destroy();  // destroy a semaphore
```

We'll now see some classical problems solved using POSIX semaphores: 
\begin{itemize}
\item \href{https://en.wikipedia.org/wiki/Synchronization_(computer_science)}{Thread synchroniztion}
\item \href{https://en.wikipedia.org/wiki/Mutual_exclusion}{Mutual exclusion / Critical Section}
\item \href{https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem}{Producers / Consumers}
\item \href{https://en.wikipedia.org/wiki/Readers%E2%80%93writers_problem}{Readers / Writers}
\item \href{https://en.wikipedia.org/wiki/Dining_philosophers_problem}{Dining Philosophers}
\item \href{https://en.wikipedia.org/wiki/Cigarette_smokers_problem}{Cigarette Smokers}
\item \href{https://en.wikipedia.org/wiki/Sleeping_barber_problem}{Sleeping barber problem}
\end{itemize}