You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

62 lines
2.0 KiB
C++

/*! \file
* \brief Contains the class Spinlock
*/
#pragma once
#include "../types.h"
/*! \brief Using Spinlocks, it is possible to serialize blocks of code
* that might otherwise run in parallel on multiple CPU cores,
* or be interleaved due to interrupts or scheduling.
*
* \ingroup sync
*
* Synchronization is implemented using a lock variable. Once a thread enters
* the critical area, it sets the lock variable (to a non-zero value); when
* this thread leaves the critical area, it resets the lock variable to zero.
* Threads trying to enter an already locked critical area, actively wait,
* continuously checking until the critical area is free again.
*
* Use the following two GCC intrinsics
* - `bool __atomic_test_and_set(void *ptr, int memorder)`
* - `void __atomic_clear (bool *ptr, int memorder)`
*
* These intrinsics are translated into atomic, architecture-specific
* CPU instructions.
*
* If you want that things just work, choose __ATOMIC_SEQ_CST as memorder.
* This is not the most efficient memory order but works reasonably well.
*
* <a
* href="https://gcc.gnu.org/onlinedocs/gcc/_005f_005fatomic-Builtins.html">Atomic
* Builtins in GCC manual</a>
*/
class Spinlock {
// Prevent copies and assignments
Spinlock(const Spinlock& copy) = delete;
Spinlock& operator=(const Spinlock&) = delete;
private:
volatile uint64_t locked;
public:
/*! \brief Constructor; Initializes as unlocked.
*
* \todo(12) Complete Constructor (for \MPStuBS, or use \ref Ticketlock)
*
*/
consteval Spinlock() : locked(0) {}
/*! \brief Enters the critical area. In case the area is already locked,
* \ref lock() will actively wait until the area can be entered.
*
* \see \ref Core::pause()
* \todo(12) Implement Method (for \MPStuBS, or use \ref Ticketlock)
*/
void lock();
/*! \brief Unblocks the critical area.
*
* \todo(12) Implement Method (for \MPStuBS, or use \ref Ticketlock)
*/
void unlock();
};