1*be431cd8SAndroid Build Coastguard Worker /*
2*be431cd8SAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*be431cd8SAndroid Build Coastguard Worker *
4*be431cd8SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*be431cd8SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*be431cd8SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*be431cd8SAndroid Build Coastguard Worker *
8*be431cd8SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*be431cd8SAndroid Build Coastguard Worker *
10*be431cd8SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*be431cd8SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*be431cd8SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*be431cd8SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*be431cd8SAndroid Build Coastguard Worker * limitations under the License.
15*be431cd8SAndroid Build Coastguard Worker */
16*be431cd8SAndroid Build Coastguard Worker
17*be431cd8SAndroid Build Coastguard Worker #pragma once
18*be431cd8SAndroid Build Coastguard Worker
19*be431cd8SAndroid Build Coastguard Worker #include <assert.h>
20*be431cd8SAndroid Build Coastguard Worker #include <string>
21*be431cd8SAndroid Build Coastguard Worker
22*be431cd8SAndroid Build Coastguard Worker namespace android {
23*be431cd8SAndroid Build Coastguard Worker namespace hardware {
24*be431cd8SAndroid Build Coastguard Worker
25*be431cd8SAndroid Build Coastguard Worker enum MQFlavor : uint32_t {
26*be431cd8SAndroid Build Coastguard Worker /*
27*be431cd8SAndroid Build Coastguard Worker * kSynchronizedReadWrite represents the wait-free synchronized flavor of the
28*be431cd8SAndroid Build Coastguard Worker * FMQ. It is intended to be have a single reader and single writer.
29*be431cd8SAndroid Build Coastguard Worker * Attempts to overflow/underflow returns a failure.
30*be431cd8SAndroid Build Coastguard Worker */
31*be431cd8SAndroid Build Coastguard Worker kSynchronizedReadWrite = 0x01,
32*be431cd8SAndroid Build Coastguard Worker /*
33*be431cd8SAndroid Build Coastguard Worker * kUnsynchronizedWrite represents the flavor of FMQ where writes always
34*be431cd8SAndroid Build Coastguard Worker * succeed. This flavor allows one writer and many readers. A read operation
35*be431cd8SAndroid Build Coastguard Worker * can detect an overwrite and reset the read counter.
36*be431cd8SAndroid Build Coastguard Worker */
37*be431cd8SAndroid Build Coastguard Worker kUnsynchronizedWrite = 0x02
38*be431cd8SAndroid Build Coastguard Worker };
39*be431cd8SAndroid Build Coastguard Worker
40*be431cd8SAndroid Build Coastguard Worker struct GrantorDescriptor {
41*be431cd8SAndroid Build Coastguard Worker uint32_t flags __attribute__((aligned(4)));
42*be431cd8SAndroid Build Coastguard Worker uint32_t fdIndex __attribute__((aligned(4)));
43*be431cd8SAndroid Build Coastguard Worker uint32_t offset __attribute__((aligned(4)));
44*be431cd8SAndroid Build Coastguard Worker uint64_t extent __attribute__((aligned(8)));
45*be431cd8SAndroid Build Coastguard Worker };
46*be431cd8SAndroid Build Coastguard Worker
47*be431cd8SAndroid Build Coastguard Worker static_assert(offsetof(GrantorDescriptor, flags) == 0, "wrong offset");
48*be431cd8SAndroid Build Coastguard Worker static_assert(offsetof(GrantorDescriptor, fdIndex) == 4, "wrong offset");
49*be431cd8SAndroid Build Coastguard Worker static_assert(offsetof(GrantorDescriptor, offset) == 8, "wrong offset");
50*be431cd8SAndroid Build Coastguard Worker static_assert(offsetof(GrantorDescriptor, extent) == 16, "wrong offset");
51*be431cd8SAndroid Build Coastguard Worker static_assert(sizeof(GrantorDescriptor) == 24, "wrong size");
52*be431cd8SAndroid Build Coastguard Worker static_assert(__alignof(GrantorDescriptor) == 8, "wrong alignment");
53*be431cd8SAndroid Build Coastguard Worker
54*be431cd8SAndroid Build Coastguard Worker namespace details {
55*be431cd8SAndroid Build Coastguard Worker
56*be431cd8SAndroid Build Coastguard Worker void logError(const std::string& message);
57*be431cd8SAndroid Build Coastguard Worker void errorWriteLog(int tag, const char* message);
58*be431cd8SAndroid Build Coastguard Worker void check(bool exp, const char* message);
59*be431cd8SAndroid Build Coastguard Worker
60*be431cd8SAndroid Build Coastguard Worker typedef uint64_t RingBufferPosition;
61*be431cd8SAndroid Build Coastguard Worker enum GrantorType : int { READPTRPOS = 0, WRITEPTRPOS, DATAPTRPOS, EVFLAGWORDPOS };
62*be431cd8SAndroid Build Coastguard Worker /*
63*be431cd8SAndroid Build Coastguard Worker * There should at least be GrantorDescriptors for the read counter, write
64*be431cd8SAndroid Build Coastguard Worker * counter and data buffer. A GrantorDescriptor for an EventFlag word is
65*be431cd8SAndroid Build Coastguard Worker * not required if there is no need for blocking FMQ operations.
66*be431cd8SAndroid Build Coastguard Worker */
67*be431cd8SAndroid Build Coastguard Worker static constexpr int32_t kMinGrantorCount = DATAPTRPOS + 1;
68*be431cd8SAndroid Build Coastguard Worker
69*be431cd8SAndroid Build Coastguard Worker /*
70*be431cd8SAndroid Build Coastguard Worker * Minimum number of GrantorDescriptors required if EventFlag support is
71*be431cd8SAndroid Build Coastguard Worker * needed for blocking FMQ operations.
72*be431cd8SAndroid Build Coastguard Worker */
73*be431cd8SAndroid Build Coastguard Worker static constexpr int32_t kMinGrantorCountForEvFlagSupport = EVFLAGWORDPOS + 1;
74*be431cd8SAndroid Build Coastguard Worker
alignToWordBoundary(size_t length)75*be431cd8SAndroid Build Coastguard Worker static inline size_t alignToWordBoundary(size_t length) {
76*be431cd8SAndroid Build Coastguard Worker constexpr size_t kAlignmentSize = 64;
77*be431cd8SAndroid Build Coastguard Worker static_assert(kAlignmentSize % sizeof(long) == 0, "Incompatible word size");
78*be431cd8SAndroid Build Coastguard Worker
79*be431cd8SAndroid Build Coastguard Worker /*
80*be431cd8SAndroid Build Coastguard Worker * Check if alignment to word boundary would cause an overflow.
81*be431cd8SAndroid Build Coastguard Worker */
82*be431cd8SAndroid Build Coastguard Worker check(length <= SIZE_MAX - kAlignmentSize / 8 + 1, "Queue size too large");
83*be431cd8SAndroid Build Coastguard Worker
84*be431cd8SAndroid Build Coastguard Worker return (length + kAlignmentSize / 8 - 1) & ~(kAlignmentSize / 8 - 1U);
85*be431cd8SAndroid Build Coastguard Worker }
86*be431cd8SAndroid Build Coastguard Worker
isAlignedToWordBoundary(size_t offset)87*be431cd8SAndroid Build Coastguard Worker static inline size_t isAlignedToWordBoundary(size_t offset) {
88*be431cd8SAndroid Build Coastguard Worker constexpr size_t kAlignmentSize = 64;
89*be431cd8SAndroid Build Coastguard Worker return (offset & (kAlignmentSize / 8 - 1)) == 0;
90*be431cd8SAndroid Build Coastguard Worker }
91*be431cd8SAndroid Build Coastguard Worker
92*be431cd8SAndroid Build Coastguard Worker } // namespace details
93*be431cd8SAndroid Build Coastguard Worker } // namespace hardware
94*be431cd8SAndroid Build Coastguard Worker } // namespace android
95