# Hardware solutions

## Disabling interrupts

**Uniprocessor computational system**

* The switching of processes, in a multiprogrammed environment, is always caused by an external device:
  * **real time clock (RTC)** – cause the time-out transition in preemptive systems.
  * **device controller** – can cause the preempt transitions in case of waking up of a higher priority process.
  * In any case, interruptions of the processor.
* Thus, access in mutual exclusion can be implemented disabling interrupts.
* Only valid in kernel.
  * Malicious or buggy code can completely block the system.

**Multiprocessor computational system**

* Disabling interrupts in one processor has no effect.

## Special instructions

### TAS

<figure><img src="https://933056030-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmDWmJ4LyRblScRPGY3di%2Fuploads%2Fqc0BB4BJaP2E4PCNFay7%2Fa.png?alt=media&#x26;token=16158c1a-a22f-4761-933e-03128569beeb" alt=""><figcaption></figcaption></figure>

The *test\_and\_set* function, if implemented **atomically** (without interruptions), can be used to construct the **lock** (**enter critical section**) primitive.

In the instruction set of some of the current processors, there is an atomic instruction implementing this behavior.

Surprisingly, it is often called **TAS** (**test and set**).

### CAS

<figure><img src="https://933056030-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmDWmJ4LyRblScRPGY3di%2Fuploads%2FTFJh9nPPXVoRkZOfJA3g%2Fa.png?alt=media&#x26;token=64bbfea9-73ac-4ef0-b9e0-ffed6a157a29" alt=""><figcaption></figcaption></figure>

The *compare\_and\_swap* function, if implemented **atomically** (without interruptions), can be used to construct the **lock** (**enter critical section**) primitive.

In the instruction set of some of the current processors, there is an atomic instruction implementing that behavior.

In some instruction sets, there is a *compare\_and\_set* variant this returns a bool.

## Busy waiting

The previous solutions suffer from *busy waiting*.

* The **lock** primitive is in the active state (using the CPU) while waiting.
* It is often referred to as a **spinlock**, as the process spins around the variable while waiting for access.

In **uniprocessor systems**, busy waiting is unwanted, as there is:

* **loss of efficiency** – the time quantum of a process is used for nothing.
* **risk of deadlock** – if a higher priority process calls lock while a lower priority process is inside its critical section, none of them can proceed.

In **multiprocessor systems** with shared memory, busy waiting can be less critical.

* switching processes cost time, that can be higher than the time spent by the other process inside its critical section.

## Block and wake up

In general, at least in uniprocessor systems, there is the requirement of blocking a process while it is waiting for entering its critical section.

<figure><img src="https://933056030-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FmDWmJ4LyRblScRPGY3di%2Fuploads%2Fsy7VzI231cL56zaySULr%2Fa.png?alt=media&#x26;token=9f537994-fc53-4447-9e0c-00fb56032bb2" alt=""><figcaption></figcaption></figure>

Atomic operations are still required.
