//----------------------------------------------------------------------------// // 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_PANIC_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; LockType_t type; volatile int locked; /* #ifdef _KALEID_KERNEL Thread_t *ownerThread; // unused Thread_t *waitingThread; // unused #endif */ }; //------------------------------------------// // // Linux syscall vs unimplemented syscall... // #ifndef _KALEID_KERNEL #ifdef _OSK_SOURCE int KalYieldCPU(void), #else int sched_yield(void); #endif #endif // // Initialize a lock // static inline void InitLock(Lock_t *lock, LockType_t type) { lock->type = type; lock->locked = FALSE; lock->initDone = INITOK; /* #ifdef _KALEID_KERNEL lock->ownerThread = NULL; lock->waitingThread = NULL; #endif */ } // // Alternative way to initalize a lock // #ifdef _KALEID_KERNEL # define INITLOCK(type) { INITOK, FALSE, (type), /* NULL, NULL */ } #else # define INITLOCK(type) { INITOK, FALSE, (type) } #endif // // Destroy a lock // static inline void DestroyLock(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 void AcquireLock(Lock_t *lock) { KalAssert(lock->initDone == INITOK); while (!__sync_bool_compare_and_swap(&lock->locked, 0, 1)) { #ifdef _KALEID_KERNEL StartPanic("AcquireLock on an already locked object"); #else if likely (lock->type == KLOCK_SPINLOCK) continue; #ifdef _OSK_SOURCE else (void)KalYieldCPU(); #else else (void)sched_yield(); #endif #endif } __sync_synchronize(); } // // Release an already acquired lock // Panic if the lock was never acquired // static inline void ReleaseLock(Lock_t *lock) { /*#ifdef _KALEID_KERNEL KalAssert(lock->ownerThread == GetCurThread()); #endif*/ __sync_synchronize(); lock->locked = 0; } // // Tries to acquire lock // static inline bool AttemptLock(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