Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Modernize simcall mutex_trylock.
[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 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     /* Give the ownership to the first waiting actor */
72     owner_ = &sleeping_.front();
73     sleeping_.pop_front();
74     owner_->waiting_synchro_ = nullptr;
75     owner_->simcall_answer();
76   } else {
77     /* nobody to wake up */
78     locked_ = false;
79     owner_  = nullptr;
80   }
81   XBT_OUT();
82 }
83 /** Increase the refcount for this mutex */
84 MutexImpl* MutexImpl::ref()
85 {
86   intrusive_ptr_add_ref(this);
87   return this;
88 }
89
90 /** Decrease the refcount for this mutex */
91 void MutexImpl::unref()
92 {
93   intrusive_ptr_release(this);
94 }
95
96 } // namespace activity
97 } // namespace kernel
98 } // namespace simgrid
99
100 // Simcall handlers:
101
102 void simcall_HANDLER_mutex_lock(smx_simcall_t simcall, smx_mutex_t mutex)
103 {
104   mutex->lock(simcall->issuer_);
105 }