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++
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();
|
|
};
|