Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
split MutexImpl into their own files
[simgrid.git] / src / simix / MutexImpl.cpp
1 /* Copyright (c) 2007-2017. The SimGrid Team. All rights reserved.          */
2
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. */
5
6 #include "smx_private.hpp"
7 #include "src/surf/cpu_interface.hpp"
8 #include "src/surf/surf_interface.hpp"
9 #include <xbt/ex.hpp>
10 #include <xbt/log.h>
11 #include <xbt/utility.hpp>
12
13 #include "src/kernel/activity/SynchroRaw.hpp"
14 #include "src/simix/MutexImpl.hpp"
15
16 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mutex, simix_synchro, "Mutex kernel-space implementation");
17
18 namespace simgrid {
19 namespace simix {
20
21 MutexImpl::MutexImpl() : mutex_(this)
22 {
23   XBT_IN("(%p)", this);
24   XBT_OUT();
25 }
26
27 MutexImpl::~MutexImpl()
28 {
29   XBT_IN("(%p)", this);
30   XBT_OUT();
31 }
32
33 void MutexImpl::lock(smx_actor_t issuer)
34 {
35   XBT_IN("(%p; %p)", this, issuer);
36   /* FIXME: check where to validate the arguments */
37   smx_activity_t synchro = nullptr;
38
39   if (this->locked) {
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);
46   } else {
47     /* mutex free */
48     this->locked = true;
49     this->owner  = issuer;
50     SIMIX_simcall_answer(&issuer->simcall);
51   }
52   XBT_OUT();
53 }
54
55 /** Tries to lock the mutex for a process
56  *
57  * \param  issuer  the process that tries to acquire the mutex
58  * \return whether we managed to lock the mutex
59  */
60 bool MutexImpl::try_lock(smx_actor_t issuer)
61 {
62   XBT_IN("(%p, %p)", this, issuer);
63   if (this->locked) {
64     XBT_OUT();
65     return false;
66   }
67
68   this->locked = true;
69   this->owner  = issuer;
70   XBT_OUT();
71   return true;
72 }
73
74 /** Unlock a mutex for a process
75  *
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.
79  */
80 void MutexImpl::unlock(smx_actor_t issuer)
81 {
82   XBT_IN("(%p, %p)", this, issuer);
83   if (not this->locked)
84     THROWF(mismatch_error, 0, "Cannot release that mutex: it was not locked.");
85
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);
90
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;
96     this->owner        = p;
97     SIMIX_simcall_answer(&p->simcall);
98   } else {
99     /* nobody to wake up */
100     this->locked = false;
101     this->owner  = nullptr;
102   }
103   XBT_OUT();
104 }
105 }
106 }
107
108 /** Increase the refcount for this mutex */
109 smx_mutex_t SIMIX_mutex_ref(smx_mutex_t mutex)
110 {
111   if (mutex != nullptr)
112     intrusive_ptr_add_ref(mutex);
113   return mutex;
114 }
115
116 /** Decrease the refcount for this mutex */
117 void SIMIX_mutex_unref(smx_mutex_t mutex)
118 {
119   if (mutex != nullptr)
120     intrusive_ptr_release(mutex);
121 }
122
123 // Simcall handlers:
124
125 void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
126 {
127   mutex->lock(simcall->issuer);
128 }
129
130 int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
131 {
132   return mutex->try_lock(simcall->issuer);
133 }
134
135 void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
136 {
137   mutex->unlock(simcall->issuer);
138 }