Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
reservation.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 Stanford University, NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// reservations for Realm
19
20#ifndef REALM_RESERVATION_H
21#define REALM_RESERVATION_H
22
23#include "realm/realm_c.h"
24
25#include "realm/atomics.h"
26#include "realm/event.h"
27
28namespace Realm {
29
31 public:
34 bool operator<(const Reservation &rhs) const { return id < rhs.id; }
35 bool operator==(const Reservation &rhs) const { return id == rhs.id; }
36 bool operator!=(const Reservation &rhs) const { return id != rhs.id; }
37
39
40 bool exists(void) const { return id != 0; }
41
42 // requests ownership (either exclusive or shared) of the reservation with a
43 // specified mode - returns an event that will trigger when the reservation
44 // is granted
45 Event acquire(unsigned mode = 0, bool exclusive = true,
46 Event wait_on = Event::NO_EVENT) const;
47
48 // tries to acquire ownership of the reservation with the given 'mode' and
49 // 'exclusive'ity if immediately successful, returns Event::NO_EVENT - check with
50 // exists(), not has_triggered()! if not, the reservation is NOT acquired (ever), and
51 // it returns an Event that should be
52 // allowed to trigger before the caller tries again - also, the caller MUST retry
53 // until successful, setting 'retry' to true on subsequent attempts
54 Event try_acquire(bool retry, unsigned mode = 0, bool exclusive = true,
55 Event wait_on = Event::NO_EVENT) const;
56
57 // releases a held reservation - release can be deferred until an event triggers
58 void release(Event wait_on = Event::NO_EVENT) const;
59
60 // Create a new reservation, destroy an existing reservation
62
63 void destroy_reservation(Event wait_on = Event::NO_EVENT);
64 };
65
66 inline std::ostream &operator<<(std::ostream &os, Reservation r)
67 {
68 return os << std::hex << r.id << std::dec;
69 }
70
71 // a FastReservation is a wrapper around a Reservation that signficantly
72 // reduces overhead for repeated use of the same Reservation within a
73 // (coherent) address space. Unlike Reservation's, a FastReservation is
74 // an opaque object that is not copyable or transferrable. However, a
75 // FastReservation _does_ play nice with other users of the underlying
76 // Reservation, on the same node or on others
77
79 public:
80 FastReservation(Reservation _rsrv = Reservation::NO_RESERVATION);
82
83 private:
84 // NOT copyable
86 FastReservation &operator=(const FastReservation &);
87
88 public:
90 {
91 SPIN, // keep trying until lock is available
92 ALWAYS_SPIN, // spin, even if holder is suspended (DANGEROUS)
93 WAIT, // wait on Realm::Event, allowing other tasks to run
94 EXTERNAL_WAIT, // wait on kernel mutex, for non-Realm threads
95 };
96
97 // these are inlined and cover the fast (i.e. uncontended) cases - they
98 // automatically fall back to the ..._slow versions below when needed
99 // if the lock cannot be obtained without waiting, these calls return an
100 // Event that the caller should wait on before trying again
101 // Note #1: use exists() (not has_triggered()!) to check if the acquisition
102 // failed and needs to be retried
103 // Note #2: unlike try_acquire above, the caller is NOT required to try again
104 Event lock(WaitMode mode = SPIN); // synonym for wrlock()
105 Event wrlock(WaitMode mode = SPIN);
106 Event rdlock(WaitMode mode = SPIN);
107 void unlock(void);
108
109 // non-blocking versions return true if the lock is granted, false if
110 // waiting/spinning would have been required
111 // Note: when a FastReservation has a backing Reservation, these calls can
112 // fail even if no other thread holds the FastReservation - in such cases,
113 // the only recourse is to keep attempting the acquisition until it
114 // succeeds (this can be problematic if the holder needs the same processor)
115 bool trylock(void); // synonym for trywrlock()
116 bool trywrlock(void);
117 bool tryrdlock(void);
118
119 // in general, a thread holding a lock should not go to sleep on other
120 // events, as another thread waiting on the lock may spin and prevent the
121 // holding thread from running on that core
122 // to avoid this, a thread holding the lock that intends to sleep should
123 // create a UserEvent and advise on entry/exit from the region in which
124 // sleeping might occur (do not provide the event the holder is waiting
125 // for - the user event must be triggered after the advise_sleep_exit call)
126 void advise_sleep_entry(UserEvent guard_event);
128
129 // the fast path stores several things in a 32-bit word that can be
130 // atomically updated
131 typedef uint32_t State;
132 static const State STATE_READER_COUNT_MASK = 0x03ffffff;
133 static const State STATE_SLEEPER = 0x04000000;
134 static const State STATE_WRITER = 0x08000000;
135 static const State STATE_WRITER_WAITING = 0x10000000;
136 static const State STATE_BASE_RSRV = 0x20000000;
137 static const State STATE_BASE_RSRV_WAITING = 0x40000000;
138 static const State STATE_SLOW_FALLBACK = 0x80000000;
139
140 protected:
143 void unlock_slow(void);
144 bool trywrlock_slow(void);
145 bool tryrdlock_slow(void);
146
147 friend struct FastRsrvState;
148
149 // we will make use of atomics for the fast path, so make sure we take
150 // a full cache line for our data to avoid false sharing
151 static const size_t CACHE_LINE_SIZE = 64;
153 State_aligned state;
154 // this is slightly fragile, but we want to have enough room to store
155 // the implementation-specific stuff without another layer of
156 // indirection
157 char opaque[CACHE_LINE_SIZE * 4 - sizeof(atomic<State>)];
158 };
159
160}; // namespace Realm
161
162#include "realm/reservation.inl"
163
164#endif // ifndef REALM_RESERVATION_H
Definition event.h:50
Definition reservation.h:78
State_aligned state
Definition reservation.h:153
Event wrlock(WaitMode mode=SPIN)
Event rdlock_slow(WaitMode mode)
Event wrlock_slow(WaitMode mode)
Event rdlock(WaitMode mode=SPIN)
uint32_t State
Definition reservation.h:131
void advise_sleep_exit(void)
WaitMode
Definition reservation.h:90
@ EXTERNAL_WAIT
Definition reservation.h:94
@ SPIN
Definition reservation.h:91
@ ALWAYS_SPIN
Definition reservation.h:92
@ WAIT
Definition reservation.h:93
REALM_ALIGNED_TYPE_CONST(State_aligned, atomic< State >, 16)
FastReservation(Reservation _rsrv=Reservation::NO_RESERVATION)
Event lock(WaitMode mode=SPIN)
void advise_sleep_entry(UserEvent guard_event)
Definition reservation.h:30
bool operator!=(const Reservation &rhs) const
Definition reservation.h:36
bool exists(void) const
Definition reservation.h:40
static const Reservation NO_RESERVATION
Definition reservation.h:38
void release(Event wait_on=Event::NO_EVENT) const
static Reservation create_reservation()
id_t id
Definition reservation.h:33
bool operator<(const Reservation &rhs) const
Definition reservation.h:34
::realm_id_t id_t
Definition reservation.h:32
void destroy_reservation(Event wait_on=Event::NO_EVENT)
Event acquire(unsigned mode=0, bool exclusive=true, Event wait_on=Event::NO_EVENT) const
Event try_acquire(bool retry, unsigned mode=0, bool exclusive=true, Event wait_on=Event::NO_EVENT) const
bool operator==(const Reservation &rhs) const
Definition reservation.h:35
Definition event.h:205
Definition atomics.h:31
#define REALM_PUBLIC_API
Definition compiler_support.h:217
Definition activemsg.h:38
std::ostream & operator<<(std::ostream &os, const DenseRectangleList< N, T > &drl)
unsigned long long realm_id_t
Definition realm_c.h:64