Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
rename synchro logging categories (simix->ker)
[simgrid.git] / src / kernel / activity / MutexImpl.cpp
1 /* Copyright (c) 2007-2021. 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 #if SIMGRID_HAVE_MC
10 #include "simgrid/modelchecker.h"
11 #include "src/mc/mc_safety.hpp"
12 #define MC_CHECK_NO_DPOR()                                                                                             \
13   xbt_assert(not MC_is_active() || mc::reduction_mode != mc::ReductionMode::dpor,                                      \
14              "Mutex is currently not supported with DPOR,  use --cfg=model-check/reduction:none")
15 #else
16 #define MC_CHECK_NO_DPOR() (void)0
17 #endif
18
19 XBT_LOG_NEW_DEFAULT_SUBCATEGORY(ker_mutex, ker_synchro, "Mutex kernel-space implementation");
20
21 namespace simgrid {
22 namespace kernel {
23 namespace activity {
24
25 void MutexImpl::lock(actor::ActorImpl* issuer)
26 {
27   XBT_IN("(%p; %p)", this, issuer);
28   MC_CHECK_NO_DPOR();
29
30   if (locked_) {
31     /* FIXME: check if the host is active ? */
32     /* Somebody using the mutex, use a synchronization to get host failures */
33     RawImplPtr synchro(new RawImpl([this, issuer]() { this->remove_sleeping_actor(*issuer); }));
34     (*synchro).set_host(issuer->get_host()).start();
35     synchro->register_simcall(&issuer->simcall_);
36     sleeping_.push_back(*issuer);
37   } else {
38     /* mutex free */
39     locked_ = true;
40     owner_  = issuer;
41     issuer->simcall_answer();
42   }
43   XBT_OUT();
44 }
45
46 /** Tries to lock the mutex for a actor
47  *
48  * @param  issuer  the actor that tries to acquire the mutex
49  * @return whether we managed to lock the mutex
50  */
51 bool MutexImpl::try_lock(actor::ActorImpl* issuer)
52 {
53   XBT_IN("(%p, %p)", this, issuer);
54   MC_CHECK_NO_DPOR();
55   if (locked_) {
56     XBT_OUT();
57     return false;
58   }
59
60   locked_ = true;
61   owner_  = issuer;
62   XBT_OUT();
63   return true;
64 }
65
66 /** Unlock a mutex for a actor
67  *
68  * Unlocks the mutex and gives it to a actor waiting for it.
69  * If the unlocker is not the owner of the mutex nothing happens.
70  * If there are no actor waiting, it sets the mutex as free.
71  */
72 void MutexImpl::unlock(actor::ActorImpl* issuer)
73 {
74   XBT_IN("(%p, %p)", this, issuer);
75   xbt_assert(locked_, "Cannot release that mutex: it was not locked.");
76   xbt_assert(issuer == owner_, "Cannot release that mutex: it was locked by %s (pid:%ld), not by you.",
77              owner_->get_cname(), owner_->get_pid());
78
79   if (not sleeping_.empty()) {
80     /* Give the ownership to the first waiting actor */
81     owner_ = &sleeping_.front();
82     sleeping_.pop_front();
83     owner_->waiting_synchro_ = nullptr;
84     owner_->simcall_answer();
85   } else {
86     /* nobody to wake up */
87     locked_ = false;
88     owner_  = nullptr;
89   }
90   XBT_OUT();
91 }
92 /** Increase the refcount for this mutex */
93 MutexImpl* MutexImpl::ref()
94 {
95   intrusive_ptr_add_ref(this);
96   return this;
97 }
98
99 /** Decrease the refcount for this mutex */
100 void MutexImpl::unref()
101 {
102   intrusive_ptr_release(this);
103 }
104
105 } // namespace activity
106 } // namespace kernel
107 } // namespace simgrid