thor-os/kernel/include/conc/deferred_unique_semaphore.hpp
Baptiste Wicht 24b6eb4b1a
Fix the lock
It was possible to loose some notifications
2016-09-26 19:05:06 +02:00

93 lines
2.0 KiB
C++

//=======================================================================
// Copyright Baptiste Wicht 2013-2016.
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
// http://www.opensource.org/licenses/MIT)
//=======================================================================
#ifndef DEFERRED_UNIQUE_SEMAPHORE_H
#define DEFERRED_UNIQUE_SEMAPHORE_H
#include "conc/int_lock.hpp"
#include "scheduler.hpp"
/*!
* \brief A deferred unique semaphore lock implementation.
*
* This must be used when the notifier is an IRQ handler.
*
* Once the lock is acquired, the critical section is only accessible by the
* thread who acquired the mutex.
*/
struct deferred_unique_semaphore {
/*!
* \brief Claim the mutex
*/
void claim() {
this->pid = scheduler::get_pid();
}
void init(size_t value){
this->value = value;
}
/*!
* \brief Wait for the lock
*/
void wait() {
int_lock lock;
lock.lock();
if (value > 0) {
--value;
lock.unlock();
} else {
waiting = true;
scheduler::block_process_light(pid);
lock.unlock();
scheduler::reschedule();
}
}
/*!
* \brief Release the lock, from an IRQ handler.
*/
void notify() {
if(waiting){
scheduler::unblock_process_hint(pid);
waiting = false;
} else {
++value;
}
}
/*!
* \brief Release the lock several times, from an IRQ
*/
void notify(size_t n) {
if (waiting) {
scheduler::unblock_process_hint(pid);
waiting = false;
--n;
if (n) {
value += n;
}
} else {
value += n;
}
}
private:
size_t pid = 0; ///< The claimed pid
volatile size_t value = 0; ///< The value of the mutex
volatile bool waiting = false; ///< Indicates if the process is waiting
};
#endif