Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
7d528fa056814c70c580a271d8af4988886403cb
[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     issuer->simcall_answer();
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   xbt_assert(locked_, "Cannot release that mutex: it was not locked.");
67   xbt_assert(issuer == owner_, "Cannot release that mutex: it was locked by %s (pid:%ld), not by you.",
68              owner_->get_cname(), owner_->get_pid());
69
70   if (not sleeping_.empty()) {
71     /* pick one actor to wake up */
72     actor::ActorImpl* act = &sleeping_.front();
73     sleeping_.pop_front();
74     act->waiting_synchro = nullptr;
75     owner_             = act;
76     act->simcall_answer();
77   } else {
78     /* nobody to wake up */
79     locked_ = false;
80     owner_  = nullptr;
81   }
82   XBT_OUT();
83 }
84 /** Increase the refcount for this mutex */
85 MutexImpl* MutexImpl::ref()
86 {
87   intrusive_ptr_add_ref(this);
88   return this;
89 }
90
91 /** Decrease the refcount for this mutex */
92 void MutexImpl::unref()
93 {
94   intrusive_ptr_release(this);
95 }
96
97 } // namespace activity
98 } // namespace kernel
99 } // namespace simgrid
100
101 // Simcall handlers:
102
103 void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
104 {
105   mutex->lock(simcall->issuer);
106 }
107
108 int simcall_HANDLER_mutex_trylock(smx_simcall_t simcall, smx_mutex_t mutex)
109 {
110   return mutex->try_lock(simcall->issuer);
111 }
112
113 void simcall_HANDLER_mutex_unlock(smx_simcall_t simcall, smx_mutex_t mutex)
114 {
115   mutex->unlock(simcall->issuer);
116 }