Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
281cca447c83f82c7990b45272a3aa84f6ba2c6b
[simgrid.git] / src / kernel / activity / MutexImpl.cpp
1 /* Copyright (c) 2007-2019. 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 "src/kernel/activity/MutexImpl.hpp"
7 #include "src/kernel/activity/SynchroRaw.hpp"
8
9 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(simix_mutex, simix_synchro, "Mutex kernel-space implementation");
10
11 namespace simgrid {
12 namespace kernel {
13 namespace activity {
14
15 void MutexImpl::lock(actor::ActorImpl* issuer)
16 {
17   XBT_IN("(%p; %p)", this, issuer);
18   /* FIXME: check where to validate the arguments */
19   RawImplPtr synchro = nullptr;
20
21   if (locked_) {
22     /* FIXME: check if the host is active ? */
23     /* Somebody using the mutex, use a synchronization to get host failures */
24     synchro = RawImplPtr(new RawImpl());
25     (*synchro).set_host(issuer->get_host()).start();
26     synchro->simcalls_.push_back(&issuer->simcall);
27     issuer->waiting_synchro = synchro;
28     sleeping_.push_back(*issuer);
29   } else {
30     /* mutex free */
31     locked_ = true;
32     owner_  = issuer;
33     SIMIX_simcall_answer(&issuer->simcall);
34   }
35   XBT_OUT();
36 }
37
38 /** Tries to lock the mutex for a process
39  *
40  * @param  issuer  the process that tries to acquire the mutex
41  * @return whether we managed to lock the mutex
42  */
43 bool MutexImpl::try_lock(actor::ActorImpl* issuer)
44 {
45   XBT_IN("(%p, %p)", this, issuer);
46   if (locked_) {
47     XBT_OUT();
48     return false;
49   }
50
51   locked_ = true;
52   owner_  = issuer;
53   XBT_OUT();
54   return true;
55 }
56
57 /** Unlock a mutex for a process
58  *
59  * Unlocks the mutex and gives it to a process waiting for it.
60  * If the unlocker is not the owner of the mutex nothing happens.
61  * If there are no process waiting, it sets the mutex as free.
62  */
63 void MutexImpl::unlock(actor::ActorImpl* issuer)
64 {
65   XBT_IN("(%p, %p)", this, issuer);
66   if (not locked_)
67     THROWF(mismatch_error, 0, "Cannot release that mutex: it was not locked.");
68
69   /* If the mutex is not owned by the issuer, that's not good */
70   if (issuer != owner_)
71     THROWF(mismatch_error, 0, "Cannot release that mutex: it was locked by %s (pid:%ld), not by you.",
72            owner_->get_cname(), owner_->get_pid());
73
74   if (not sleeping_.empty()) {
75     /*process to wake up */
76     actor::ActorImpl* p = &sleeping_.front();
77     sleeping_.pop_front();
78     p->waiting_synchro = nullptr;
79     owner_             = p;
80     SIMIX_simcall_answer(&p->simcall);
81   } else {
82     /* nobody to wake up */
83     locked_ = false;
84     owner_  = nullptr;
85   }
86   XBT_OUT();
87 }
88 /** Increase the refcount for this mutex */
89 MutexImpl* MutexImpl::ref()
90 {
91   intrusive_ptr_add_ref(this);
92   return this;
93 }
94
95 /** Decrease the refcount for this mutex */
96 void MutexImpl::unref()
97 {
98   intrusive_ptr_release(this);
99 }
100
101 } // namespace activity
102 } // namespace kernel
103 } // namespace simgrid
104
105 // Simcall handlers:
106
107 void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
108 {
109   mutex->lock(simcall->issuer);
110 }
111
112 int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
113 {
114   return mutex->try_lock(simcall->issuer);
115 }
116
117 void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
118 {
119   mutex->unlock(simcall->issuer);
120 }