//----------------------------------------------------------------------------// // GNU GPL OS/K // // // // Desc: Locks and synchronization // // // // // // Copyright © 2018-2019 The OS/K Team // // // // This file is part of OS/K. // // // // OS/K is free software: you can redistribute it and/or modify // // it under the terms of the GNU General Public License as published by // // the Free Software Foundation, either version 3 of the License, or // // any later version. // // // // OS/K is distributed in the hope that it will be useful, // // but WITHOUT ANY WARRANTY//without even the implied warranty of // // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // // GNU General Public License for more details. // // // // You should have received a copy of the GNU General Public License // // along with OS/K. If not, see . // //----------------------------------------------------------------------------// #ifndef _KALBASE_H #include #endif #ifdef _KALEID_KERNEL #ifndef _KALKERN_SCHED_H #include #endif #endif #ifndef _KALEXTRAS_LOCKS_H #define _KALEXTRAS_LOCKS_H #ifdef __cplusplus extern "C" { #endif typedef enum LockType_t LockType_t; typedef struct Lock_t Lock_t; //------------------------------------------// enum LockType_t { // Mutex-type lock // // WARNING // AcquireLock() panics when used on a mutex while not running a process KLOCK_MUTEX, // Spinlock-type lock KLOCK_SPINLOCK, }; struct Lock_t { unsigned int initDone; volatile int locked; LockType_t type; /* #ifdef _KALEID_KERNEL Thread_t *ownerThread; // unused Thread_t *waitingThread; // unused #endif */ }; //------------------------------------------// #ifndef _KALEID_KERNEL int KalYieldCPU(void), #endif // // Initialize a lock // static inline void ExInitLock(Lock_t *lock, LockType_t type) { lock->locked = 0; lock->type = type; lock->initDone = INITOK; /* #ifdef _KALEID_KERNEL lock->ownerThread = NULL; lock->waitingThread = NULL; #endif */ } // // Alternative way to initalize a lock // #ifdef _KALEID_KERNEL # define ExINITLOCK(type) { INITOK, 0, (type), /* NULL, NULL */ } #else # define ExINITLOCK(type) { INITOK, 0, (type) } #endif // // Destroy a lock // static inline void ExDestroyLock(Lock_t *lock) { KalAssert(lock->initDone); __sync_synchronize(); lock->initDone = 0; } // // Acquire the lock // Panic on double acquisition since that should never happen // until we have at least a basic scheduler // static inline #if defined(_KALEID_KERNEL) && !defined(_NO_DEBUG) #define ExAcquireLock(lock) \ _ExAcquireLock(lock,__FILE__, __LINE__, __func__,#lock) void _ExAcquireLock(Lock_t *lock, const char *file, int line, const char *func, const char *obj) #else void ExAcquireLock(Lock_t *lock) #endif { KalAssert(lock->initDone == INITOK); while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) { #if defined(_KALEID_KERNEL) && !defined(_NO_DEBUG) KeStartPanic( "In function '%s', from '%s' line %d\n" "Double ExAcquireLock on object: '%s'", func, file, line, obj); #endif /*if likely (lock->type == KLOCK_SPINLOCK)*/ continue; //else (void)KalYieldCPU(); } PsDisablePreemption(); __sync_synchronize(); } // // Release an already acquired lock // Panic if the lock was never acquired // static inline void ExReleaseLock(Lock_t *lock) { /*#ifdef _KALEID_KERNEL KalAssert(lock->ownerThread == GetCurThread()); #endif*/ __sync_synchronize(); lock->locked = 0; PsEnablePreemption(); } // // Tries to acquire lock // static inline bool ExAttemptLock(Lock_t *lock) { KalAssert(lock->initDone == INITOK); bool retval = __sync_bool_compare_and_swap(&lock->locked, 0, 1); __sync_synchronize(); return retval; } //------------------------------------------// #ifdef __cplusplus } #endif #endif