Semaphores in Linux Kernel

 

πŸ’€ Semaphores in Linux Kernel 

✅ What is a semaphore?

A semaphore in Linux is a sleeping lock used to protect shared resources.

  • If the semaphore is free → the task acquires it immediately

  • If unavailable → the task is:

    1. placed in a wait queue

    2. put to sleep

    3. CPU executes other tasks

  • When released → one waiting task is woken up and allowed to acquire it

πŸ‘‰ Unlike spin locks, no busy waiting occurs, so CPU time is not wasted.


✅ Why semaphores are used

Semaphores are suitable when:

✔ Lock may be held for a long time
✔ Task may need to sleep
✔ Synchronization involves user-space interaction
✔ Blocking is acceptable

They are not good for very short locks because:

  • sleeping + wakeup overhead

  • managing wait queues

can cost more than the protected operation.


✅ Important properties

1️⃣ Sleeping behavior

When a task waits:

  • it sleeps instead of spinning

  • improves CPU utilization

  • allows scheduler to run other tasks


2️⃣ Process-context only

Because semaphores may sleep:

❌ Cannot be used in interrupt handlers
✔ Must be used only in process context

(interrupt context cannot be scheduled)


3️⃣ Can sleep while holding a semaphore

Unlike spin locks:

✔ It is allowed to sleep while holding a semaphore

Other tasks requesting it:

  • simply go to sleep

  • no deadlock from spinning


4️⃣ Cannot acquire semaphore while holding spin lock

Because:

  • semaphore acquisition may sleep

  • sleeping while holding spin lock is illegal


5️⃣ Do not disable kernel preemption

Unlike spin locks:

  • code holding semaphore can be preempted

  • does not increase scheduling latency


πŸ”’ Types of Semaphores

🟒 Binary semaphore (mutex)

  • Count = 1

  • Only one holder allowed

  • Used for mutual exclusion

  • Most common in kernel


πŸ”΅ Counting semaphore

  • Count > 1

  • Allows multiple simultaneous holders

  • Used to limit resource usage

  • Rarely used in kernel


⚙️ Semaphore Operations

Semaphores support two atomic operations:

⬇️ down() → acquire semaphore

  • decrements count by 1

  • if result ≥ 0 → lock acquired

  • if result < 0 → task sleeps in wait queue

This is called “downing” the semaphore


⬆️ up() → release semaphore

  • increments count

  • wakes one waiting task (if any)

Called “upping” the semaphore


πŸ— Creating and Initializing Semaphores

Static semaphore

struct semaphore name; sema_init(&name, count);

Static mutex shortcut (binary semaphore)

static DECLARE_MUTEX(name);

Dynamic semaphore

sema_init(sem, count);

Dynamic mutex

init_MUTEX(sem);

πŸ›  Using Semaphores

Acquire (interruptible sleep)

down_interruptible(&sem);
  • sleeps in TASK_INTERRUPTIBLE

  • wakes on signal

  • returns -EINTR if interrupted

πŸ‘‰ Most commonly used


Acquire (uninterruptible sleep)

down(&sem);
  • sleeps in TASK_UNINTERRUPTIBLE

  • ignores signals

  • usually avoided


Try acquire without blocking

down_trylock(&sem);
  • returns immediately if unavailable


Release semaphore

up(&sem);

Example

static DECLARE_MUTEX(mr_sem); if (down_interruptible(&mr_sem)) { /* interrupted */ } /* critical section */ up(&mr_sem);

πŸ“– Reader–Writer Semaphores

Used when:

  • many readers

  • few writers

  • read/write paths clearly separated


Characteristics

✔ Multiple readers allowed simultaneously
✔ Only one writer allowed
✔ Writers require exclusive access

All reader-writer semaphores:

  • behave like mutexes internally (count=1)

  • use uninterruptible sleep


Creating

static DECLARE_RWSEM(name);

Dynamic:

init_rwsem(&sem);

Reader usage

down_read(&sem); /* read-only */ up_read(&sem);

Writer usage

down_write(&sem); /* read/write */ up_write(&sem);

Trylock versions

down_read_trylock() down_write_trylock()

Return nonzero on success (note: opposite of normal semaphore trylock).


Special feature

downgrade_write()

  • atomically converts write lock → read lock

(Not available in reader-writer spin locks)


⚖️ Spin Lock vs Semaphore (Quick comparison)

FeatureSpin Lock    Semaphore
Waiting styleBusy wait (spin)    Sleep
CPU usageHigh while waiting    Efficient
Use in interrupt context✔ Yes    ❌ No
Long lock hold time❌ Bad    ✔ Good
Allows sleeping inside critical section❌ No    ✔ Yes
Preemption disabled✔ Yes    ❌ No

⭐ Key takeaway

πŸ‘‰ Spin lock = fast, short, cannot sleep
πŸ‘‰ Semaphore = slower, can sleep, used for longer operations

Comments

Popular posts from this blog

Operating Systems OS PCCST403 Semester 4 BTech KTU CS 2024 Scheme

Introduction to Operating System -Virtualization, Concurrency, and Persistence

Differences Between Linux and Classic UNIX Kernels