/* * \brief Basic locking primitive * \author Norman Feske * \date 2006-07-26 */ /* * Copyright (C) 2006-2017 Genode Labs GmbH * * This file is part of the Genode OS framework, which is distributed * under the terms of the GNU Affero General Public License version 3. */ #ifndef _INCLUDE__BASE__CANCELABLE_LOCK_H_ #define _INCLUDE__BASE__CANCELABLE_LOCK_H_ #include #include namespace Genode { class Thread; class Cancelable_lock; } class Genode::Cancelable_lock { private: class Applicant { private: Thread *_thread_base; Applicant *_to_wake_up; public: explicit Applicant(Thread *thread_base) : _thread_base(thread_base), _to_wake_up(0) { } void applicant_to_wake_up(Applicant *to_wake_up) { _to_wake_up = to_wake_up; } Applicant *applicant_to_wake_up() { return _to_wake_up; } Thread *thread_base() { return _thread_base; } /** * Called from previous lock owner */ void wake_up(); bool operator == (Applicant &a) { return _thread_base == a.thread_base(); } bool operator != (Applicant &a) { return _thread_base != a.thread_base(); } }; /* * Note that modifications of the applicants queue must be performed * atomically. Hence, we use the additional spinlock here. */ volatile int _spinlock_state = 0; volatile int _state = 0; Applicant * volatile _last_applicant = nullptr; Applicant _owner; public: enum State { LOCKED, UNLOCKED }; /** * Constructor */ explicit Cancelable_lock(State initial = UNLOCKED); /** * Try to aquire the lock and block while the lock is not free * * \throw Genode::Blocking_canceled */ void lock(); /** * Release lock */ void unlock(); /** * Lock guard */ typedef Genode::Lock_guard Guard; }; #endif /* _INCLUDE__BASE__CANCELABLE_LOCK_H_ */