2020-05-24 15:30:55 -05:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
#ifndef SPINLOCK_H
|
|
|
|
#define SPINLOCK_H
|
2022-02-19 10:17:40 -06:00
|
|
|
/**
|
|
|
|
* \file
|
|
|
|
*
|
2020-05-24 15:30:55 -05:00
|
|
|
* Provides a lightweight mutex synchronisation primitive.
|
|
|
|
*
|
2022-02-19 13:56:55 -06:00
|
|
|
*//*
|
2022-02-19 10:17:40 -06:00
|
|
|
* Copyright (C) 2020-2022 Martin Whitaker.
|
2020-05-24 15:30:55 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
2022-02-19 10:17:40 -06:00
|
|
|
/**
|
2020-05-24 15:30:55 -05:00
|
|
|
* A mutex object. Use spin_unlock() to initialise prior to first use.
|
|
|
|
*/
|
|
|
|
typedef volatile bool spinlock_t;
|
|
|
|
|
2022-02-19 10:17:40 -06:00
|
|
|
/**
|
2020-05-24 15:30:55 -05:00
|
|
|
* Spins until the mutex is unlocked.
|
|
|
|
*/
|
|
|
|
static inline void spin_wait(spinlock_t *lock)
|
|
|
|
{
|
|
|
|
if (lock) {
|
|
|
|
while (*lock) {
|
|
|
|
__builtin_ia32_pause();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-19 10:17:40 -06:00
|
|
|
/**
|
2020-05-24 15:30:55 -05:00
|
|
|
* Spins until the mutex is unlocked, then locks the mutex.
|
|
|
|
*/
|
|
|
|
static inline void spin_lock(spinlock_t *lock)
|
|
|
|
{
|
|
|
|
if (lock) {
|
|
|
|
while (!__sync_bool_compare_and_swap(lock, false, true)) {
|
|
|
|
do {
|
|
|
|
__builtin_ia32_pause();
|
|
|
|
} while (*lock);
|
|
|
|
}
|
|
|
|
__sync_synchronize();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-19 10:17:40 -06:00
|
|
|
/**
|
2020-05-24 15:30:55 -05:00
|
|
|
* Unlocks the mutex.
|
|
|
|
*/
|
|
|
|
static inline void spin_unlock(spinlock_t *lock)
|
|
|
|
{
|
|
|
|
if (lock) {
|
|
|
|
__sync_synchronize();
|
|
|
|
*lock = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif // SPINLOCK_H
|