xref: /aosp_15_r20/system/libfmq/base/fmq/MQDescriptorBase.h (revision be431cd81a9a2349eaea34eb56fcf6d1608da596)
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