/*! \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. * * Atomic * Builtins in GCC manual */ class Spinlock { // Prevent copies and assignments Spinlock(const Spinlock& copy) = delete; Spinlock& operator=(const Spinlock&) = delete; public: /*! \brief Constructor; Initializes as unlocked. * * \todo(12) Complete Constructor (for \MPStuBS, or use \ref Ticketlock) * */ consteval Spinlock() {} /*! \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() {} };