Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/mutex_irql.c
- This file was added.
#include <sys/mutex_irql.h> | |||||
#include <sys/types.h> | |||||
#include <machine/cpufunc.h> | |||||
#include <machine/atomic.h> | |||||
#define X86_EFLAGS_IF 0x200 | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_init_irql(struct mtx_irql* mtx, const char* name, uint32_t irql) | |||||
{ | |||||
mtx->irql = irql; | |||||
mtx->iflag_n_irql = 0; | |||||
mtx->lock = 0; | |||||
mtx->name = name; | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_destroy_irql(struct mtx_irql* mtx) | |||||
{ | |||||
mtx->name = 0; | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_lock_irql(struct mtx_irql* mtx) | |||||
{ | |||||
// reset flags | |||||
uint32_t iflag_n_irql = 0; | |||||
// interrupts already disabled? | |||||
register_t eFlags = read_rflags(); | |||||
if (eFlags & X86_EFLAGS_IF) | |||||
{ | |||||
// no, then raise irql | |||||
u_int irql = rcr8(); | |||||
if (irql < mtx->irql) | |||||
{ | |||||
load_cr8(mtx->irql); | |||||
iflag_n_irql = X86_EFLAGS_IF | (irql & 0xF); | |||||
} | |||||
} | |||||
// spin on lock variable | |||||
while (atomic_swap_long(&(mtx->lock), 1)) | |||||
{ | |||||
ia32_pause(); | |||||
} | |||||
// save flags | |||||
mtx->iflag_n_irql = iflag_n_irql; | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_unlock_irql(struct mtx_irql* mtx) | |||||
{ | |||||
// get flags and delete | |||||
uint32_t iflag_n_irql = mtx->iflag_n_irql; | |||||
mtx->iflag_n_irql = 0; | |||||
// release lock variable | |||||
atomic_store_long(&(mtx->lock), 0); | |||||
// restore irql if "IF" flags is set | |||||
if (iflag_n_irql & X86_EFLAGS_IF) | |||||
{ | |||||
load_cr8(iflag_n_irql & 0xF); | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_init_un(struct mtx_un* mtx, const char* name, uint32_t irql) | |||||
{ | |||||
if (irql == 0) | |||||
{ | |||||
mtx->isbsd = 1; | |||||
mtx_init(&(mtx->mtx_bsd), name, 0, MTX_SPIN); | |||||
} | |||||
else | |||||
{ | |||||
mtx->isbsd = 0; | |||||
mtx_init_irql(&(mtx->mtx_irql), name, irql); | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_destroy_un(struct mtx_un* mtx) | |||||
{ | |||||
if (mtx->isbsd != 0) | |||||
mtx_destroy(&(mtx->mtx_bsd)); | |||||
else | |||||
mtx_destroy_irql(&(mtx->mtx_irql)); | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_lock_un(struct mtx_un* mtx) | |||||
{ | |||||
if (mtx->isbsd != 0) | |||||
mtx_lock_spin(&(mtx->mtx_bsd)); | |||||
else | |||||
mtx_lock_irql(&(mtx->mtx_irql)); | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_unlock_un(struct mtx_un* mtx) | |||||
{ | |||||
if (mtx->isbsd != 0) | |||||
mtx_unlock_spin(&(mtx->mtx_bsd)); | |||||
else | |||||
mtx_unlock_irql(&(mtx->mtx_irql)); | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_sysinit_un(const void* udata) | |||||
{ | |||||
const struct mtx_un_args* pArgs = (const struct mtx_un_args*) udata; | |||||
mtx_init_un(pArgs->ma_mtx, pArgs->ma_name, pArgs->ma_irql); | |||||
} | |||||
// ----------------------------------------------------------------------------- | |||||
void mtx_sysuninit_un(const void* udata) | |||||
{ | |||||
const struct mtx_un_args* pArgs = (const struct mtx_un_args*) udata; | |||||
mtx_destroy_un(pArgs->ma_mtx); | |||||
} |