1 /* Copyright (c) 2007-2017. The SimGrid Team. All rights reserved. */
3 /* This program is free software; you can redistribute it and/or modify it
4 * under the terms of the license (GNU LGPL) which comes with this package. */
6 #include "smx_private.hpp"
7 #include "src/surf/cpu_interface.hpp"
8 #include "src/surf/surf_interface.hpp"
11 #include <xbt/utility.hpp>
13 #include "src/kernel/activity/SynchroRaw.hpp"
14 #include "src/simix/MutexImpl.hpp"
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mutex, simix_synchro, "Mutex kernel-space implementation");
21 MutexImpl::MutexImpl() : mutex_(this)
27 MutexImpl::~MutexImpl()
33 void MutexImpl::lock(smx_actor_t issuer)
35 XBT_IN("(%p; %p)", this, issuer);
36 /* FIXME: check where to validate the arguments */
37 smx_activity_t synchro = nullptr;
40 /* FIXME: check if the host is active ? */
41 /* Somebody using the mutex, use a synchronization to get host failures */
42 synchro = SIMIX_synchro_wait(issuer->host, -1);
43 synchro->simcalls.push_back(&issuer->simcall);
44 issuer->waiting_synchro = synchro;
45 this->sleeping.push_back(*issuer);
50 SIMIX_simcall_answer(&issuer->simcall);
55 /** Tries to lock the mutex for a process
57 * \param issuer the process that tries to acquire the mutex
58 * \return whether we managed to lock the mutex
60 bool MutexImpl::try_lock(smx_actor_t issuer)
62 XBT_IN("(%p, %p)", this, issuer);
74 /** Unlock a mutex for a process
76 * Unlocks the mutex and gives it to a process waiting for it.
77 * If the unlocker is not the owner of the mutex nothing happens.
78 * If there are no process waiting, it sets the mutex as free.
80 void MutexImpl::unlock(smx_actor_t issuer)
82 XBT_IN("(%p, %p)", this, issuer);
84 THROWF(mismatch_error, 0, "Cannot release that mutex: it was not locked.");
86 /* If the mutex is not owned by the issuer, that's not good */
87 if (issuer != this->owner)
88 THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%lu), not by you.",
89 this->owner->getCname(), this->owner->pid);
91 if (not this->sleeping.empty()) {
92 /*process to wake up */
93 smx_actor_t p = &this->sleeping.front();
94 this->sleeping.pop_front();
95 p->waiting_synchro = nullptr;
97 SIMIX_simcall_answer(&p->simcall);
99 /* nobody to wake up */
100 this->locked = false;
101 this->owner = nullptr;
108 /** Increase the refcount for this mutex */
109 smx_mutex_t SIMIX_mutex_ref(smx_mutex_t mutex)
111 if (mutex != nullptr)
112 intrusive_ptr_add_ref(mutex);
116 /** Decrease the refcount for this mutex */
117 void SIMIX_mutex_unref(smx_mutex_t mutex)
119 if (mutex != nullptr)
120 intrusive_ptr_release(mutex);
125 void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
127 mutex->lock(simcall->issuer);
130 int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
132 return mutex->try_lock(simcall->issuer);
135 void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
137 mutex->unlock(simcall->issuer);