Serenity Operating System
at master 88 lines 1.9 kB view raw
1/* 2 * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org> 3 * Copyright (c) 2021, kleines Filmröllchen <malu.bertsch@gmail.com> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <AK/Assertions.h> 11#include <AK/Noncopyable.h> 12#include <AK/Types.h> 13#include <pthread.h> 14 15namespace Threading { 16 17class Mutex { 18 AK_MAKE_NONCOPYABLE(Mutex); 19 AK_MAKE_NONMOVABLE(Mutex); 20 friend class ConditionVariable; 21 22public: 23 Mutex() 24 : m_lock_count(0) 25 { 26#ifndef AK_OS_SERENITY 27 pthread_mutexattr_t attr; 28 pthread_mutexattr_init(&attr); 29 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); 30 pthread_mutex_init(&m_mutex, &attr); 31#endif 32 } 33 ~Mutex() 34 { 35 VERIFY(m_lock_count == 0); 36 // FIXME: pthread_mutex_destroy() is not implemented. 37 } 38 39 void lock(); 40 void unlock(); 41 42private: 43#ifdef AK_OS_SERENITY 44 pthread_mutex_t m_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP; 45#else 46 pthread_mutex_t m_mutex; 47#endif 48 unsigned m_lock_count { 0 }; 49}; 50 51class MutexLocker { 52 AK_MAKE_NONCOPYABLE(MutexLocker); 53 AK_MAKE_NONMOVABLE(MutexLocker); 54 55public: 56 ALWAYS_INLINE explicit MutexLocker(Mutex& mutex) 57 : m_mutex(mutex) 58 { 59 lock(); 60 } 61 ALWAYS_INLINE ~MutexLocker() 62 { 63 unlock(); 64 } 65 ALWAYS_INLINE void unlock() { m_mutex.unlock(); } 66 ALWAYS_INLINE void lock() { m_mutex.lock(); } 67 68private: 69 Mutex& m_mutex; 70}; 71 72ALWAYS_INLINE void Mutex::lock() 73{ 74 pthread_mutex_lock(&m_mutex); 75 m_lock_count++; 76} 77 78ALWAYS_INLINE void Mutex::unlock() 79{ 80 VERIFY(m_lock_count > 0); 81 // FIXME: We need to protect the lock count with the mutex itself. 82 // This may be bad because we're not *technically* unlocked yet, 83 // but we're not handling any errors from pthread_mutex_unlock anyways. 84 m_lock_count--; 85 pthread_mutex_unlock(&m_mutex); 86} 87 88}