23 int apply(
AdvisoryOwner& owner,
Grant request,
bool wait, PosixAdvisoryAdmission admission,
26 if (!open(owner, request)) {
27 SYSCALL_ERROR(BadFileDescriptor);
30 Error::PosixError result = Error::NoError;
31 size_t slot = MaximumWaiters;
34 bool converted =
false;
36 if (__atomic_load_n(&owner.m_State, __ATOMIC_ACQUIRE) == AdvisoryOwner::Closed) {
37 result = Error::BadFileDescriptor;
40 if (admission && !admission(context)) {
43 result = Error::BadFileDescriptor;
46 if (!converted && request.name == Namespace::Flock && request.type != Type::Unlock) {
47 for (
size_t i = 0; i < m_Table.count(); ++i) {
48 const Grant& existing = m_Table.at(i);
49 if (existing.owner == request.owner && existing.inode == request.inode &&
50 existing.name == Namespace::Flock && existing.type != request.type) {
51 Grant unlock = request;
52 unlock.type = Type::Unlock;
53 const PosixAdvisory::Result released = m_Table.apply(unlock);
54 assert(released == PosixAdvisory::Result::Success);
61 const PosixAdvisory::Result applied = m_Table.apply(request);
62 if (applied == PosixAdvisory::Result::Success) {
66 if (applied == PosixAdvisory::Result::Full) {
67 result = Error::NoLocksAvailable;
71 result = Error::NoMoreProcesses;
74 if (m_Table.wouldDeadlock(request, m_Waiters, MaximumWaiters)) {
75 result = Error::Deadlock;
78 if (slot == MaximumWaiters) {
79 for (
size_t i = 0; i < MaximumWaiters; ++i) {
82 m_Waiters[i] = &request;
86 if (slot == MaximumWaiters) {
87 result = Error::NoLocksAvailable;
91 ConditionVariable::Error error = ConditionVariable::NoError;
92 if (!m_Changed.
wait(m_Lock, error)) {
94 result = Error::Interrupted;
99 if (slot != MaximumWaiters && m_Waiters[slot] == &request)
100 m_Waiters[slot] =
nullptr;
102 if (result != Error::NoError) {
103 syscallError(result);
111 if (!open(owner, request)) {
112 SYSCALL_ERROR(BadFileDescriptor);
116 if (__atomic_load_n(&owner.m_State, __ATOMIC_ACQUIRE) == AdvisoryOwner::Closed) {
117 SYSCALL_ERROR(BadFileDescriptor);
120 found = m_Table.query(request, conflict);
124 void descriptorClosed(
AdvisoryOwner& owner, uintptr_t inode) {
125 if (!inode || __atomic_load_n(&owner.m_State, __ATOMIC_ACQUIRE) != AdvisoryOwner::Open)
129 m_Table.removeOwner(owner.m_Id, inode);
136 const uint8_t previous =
137 __atomic_exchange_n(&owner.m_State, AdvisoryOwner::Closed, __ATOMIC_ACQ_REL);
138 if (previous != AdvisoryOwner::Open)
141 m_Table.removeOwner(owner.m_Id);
142 for (
auto&
waiter : m_Waiters) {
151 uint8_t expected = AdvisoryOwner::Unused;
152 __atomic_compare_exchange_n(&owner.m_State, &expected, AdvisoryOwner::Open,
false,
153 __ATOMIC_ACQ_REL, __ATOMIC_ACQUIRE);
154 if (expected == AdvisoryOwner::Closed)
156 request.owner = owner.m_Id;
157 request.kind = owner.m_Kind;
158 if (owner.m_Kind == AdvisoryOwner::Kind::OpenDescription)
165 Grant m_First[MaximumGrants];
166 Grant m_Second[MaximumGrants];
167 Table m_Table{m_First, m_Second, MaximumGrants};
168 const Grant* m_Waiters[MaximumWaiters] = {};