xref: /aosp_15_r20/system/media/audio_utils/fifo_index.cpp (revision b9df5ad1c9ac98a7fefaac271a55f7ae3db05414)
1*b9df5ad1SAndroid Build Coastguard Worker /*
2*b9df5ad1SAndroid Build Coastguard Worker  * Copyright (C) 2016 The Android Open Source Project
3*b9df5ad1SAndroid Build Coastguard Worker  *
4*b9df5ad1SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*b9df5ad1SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*b9df5ad1SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*b9df5ad1SAndroid Build Coastguard Worker  *
8*b9df5ad1SAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*b9df5ad1SAndroid Build Coastguard Worker  *
10*b9df5ad1SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*b9df5ad1SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*b9df5ad1SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*b9df5ad1SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*b9df5ad1SAndroid Build Coastguard Worker  * limitations under the License.
15*b9df5ad1SAndroid Build Coastguard Worker  */
16*b9df5ad1SAndroid Build Coastguard Worker 
17*b9df5ad1SAndroid Build Coastguard Worker #include <errno.h>
18*b9df5ad1SAndroid Build Coastguard Worker #include <limits.h>
19*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/fifo_index.h>
20*b9df5ad1SAndroid Build Coastguard Worker #include <audio_utils/futex.h>
21*b9df5ad1SAndroid Build Coastguard Worker 
22*b9df5ad1SAndroid Build Coastguard Worker // These are not implemented within <audio_utils/fifo_index.h>
23*b9df5ad1SAndroid Build Coastguard Worker // so that we don't expose futex.
24*b9df5ad1SAndroid Build Coastguard Worker 
25*b9df5ad1SAndroid Build Coastguard Worker // FIXME should inline these, so that writer_T can also inline it
26*b9df5ad1SAndroid Build Coastguard Worker 
loadSingleThreaded()27*b9df5ad1SAndroid Build Coastguard Worker uint32_t audio_utils_fifo_index::loadSingleThreaded()
28*b9df5ad1SAndroid Build Coastguard Worker {
29*b9df5ad1SAndroid Build Coastguard Worker     // TODO Should be a read from simple non-atomic variable
30*b9df5ad1SAndroid Build Coastguard Worker     return atomic_load_explicit(&mIndex, std::memory_order_relaxed);
31*b9df5ad1SAndroid Build Coastguard Worker }
32*b9df5ad1SAndroid Build Coastguard Worker 
loadAcquire()33*b9df5ad1SAndroid Build Coastguard Worker uint32_t audio_utils_fifo_index::loadAcquire()
34*b9df5ad1SAndroid Build Coastguard Worker {
35*b9df5ad1SAndroid Build Coastguard Worker     return atomic_load_explicit(&mIndex, std::memory_order_acquire);
36*b9df5ad1SAndroid Build Coastguard Worker }
37*b9df5ad1SAndroid Build Coastguard Worker 
storeSingleThreaded(uint32_t value)38*b9df5ad1SAndroid Build Coastguard Worker void audio_utils_fifo_index::storeSingleThreaded(uint32_t value)
39*b9df5ad1SAndroid Build Coastguard Worker {
40*b9df5ad1SAndroid Build Coastguard Worker     // TODO Should be a write to simple non-atomic variable
41*b9df5ad1SAndroid Build Coastguard Worker     atomic_store_explicit(&mIndex, value, std::memory_order_relaxed);
42*b9df5ad1SAndroid Build Coastguard Worker }
43*b9df5ad1SAndroid Build Coastguard Worker 
storeRelease(uint32_t value)44*b9df5ad1SAndroid Build Coastguard Worker void audio_utils_fifo_index::storeRelease(uint32_t value)
45*b9df5ad1SAndroid Build Coastguard Worker {
46*b9df5ad1SAndroid Build Coastguard Worker     atomic_store_explicit(&mIndex, value, std::memory_order_release);
47*b9df5ad1SAndroid Build Coastguard Worker }
48*b9df5ad1SAndroid Build Coastguard Worker 
wait(int op,uint32_t expected,const struct timespec * timeout)49*b9df5ad1SAndroid Build Coastguard Worker int audio_utils_fifo_index::wait(int op, uint32_t expected, const struct timespec *timeout)
50*b9df5ad1SAndroid Build Coastguard Worker {
51*b9df5ad1SAndroid Build Coastguard Worker     return sys_futex(&mIndex, op, expected, timeout, NULL, 0);
52*b9df5ad1SAndroid Build Coastguard Worker }
53*b9df5ad1SAndroid Build Coastguard Worker 
wake(int op,int waiters)54*b9df5ad1SAndroid Build Coastguard Worker int audio_utils_fifo_index::wake(int op, int waiters)
55*b9df5ad1SAndroid Build Coastguard Worker {
56*b9df5ad1SAndroid Build Coastguard Worker     return sys_futex(&mIndex, op, waiters, NULL, NULL, 0);
57*b9df5ad1SAndroid Build Coastguard Worker }
58*b9df5ad1SAndroid Build Coastguard Worker 
59*b9df5ad1SAndroid Build Coastguard Worker // ----------------------------------------------------------------------------
60*b9df5ad1SAndroid Build Coastguard Worker 
61*b9df5ad1SAndroid Build Coastguard Worker #if 0   // TODO not currently used, review this code later: bug 150627616
62*b9df5ad1SAndroid Build Coastguard Worker 
63*b9df5ad1SAndroid Build Coastguard Worker RefIndexDeferredStoreReleaseDeferredWake::RefIndexDeferredStoreReleaseDeferredWake(
64*b9df5ad1SAndroid Build Coastguard Worker         audio_utils_fifo_index& index)
65*b9df5ad1SAndroid Build Coastguard Worker     : mIndex(index), mValue(0), mWriteback(false), mWaiters(0), mWakeOp(FUTEX_WAIT_PRIVATE)
66*b9df5ad1SAndroid Build Coastguard Worker {
67*b9df5ad1SAndroid Build Coastguard Worker }
68*b9df5ad1SAndroid Build Coastguard Worker 
69*b9df5ad1SAndroid Build Coastguard Worker RefIndexDeferredStoreReleaseDeferredWake::~RefIndexDeferredStoreReleaseDeferredWake()
70*b9df5ad1SAndroid Build Coastguard Worker {
71*b9df5ad1SAndroid Build Coastguard Worker     writeback();
72*b9df5ad1SAndroid Build Coastguard Worker     wakeNowIfNeeded();
73*b9df5ad1SAndroid Build Coastguard Worker }
74*b9df5ad1SAndroid Build Coastguard Worker 
75*b9df5ad1SAndroid Build Coastguard Worker void RefIndexDeferredStoreReleaseDeferredWake::set(uint32_t value) {
76*b9df5ad1SAndroid Build Coastguard Worker     mValue = value;
77*b9df5ad1SAndroid Build Coastguard Worker     mWriteback = true;
78*b9df5ad1SAndroid Build Coastguard Worker }
79*b9df5ad1SAndroid Build Coastguard Worker 
80*b9df5ad1SAndroid Build Coastguard Worker void RefIndexDeferredStoreReleaseDeferredWake::writeback()
81*b9df5ad1SAndroid Build Coastguard Worker {
82*b9df5ad1SAndroid Build Coastguard Worker     if (mWriteback) {
83*b9df5ad1SAndroid Build Coastguard Worker         // TODO When part of a collection, should use relaxed for all but the last writeback
84*b9df5ad1SAndroid Build Coastguard Worker         mIndex.storeRelease(mValue);
85*b9df5ad1SAndroid Build Coastguard Worker         mWriteback = false;
86*b9df5ad1SAndroid Build Coastguard Worker     }
87*b9df5ad1SAndroid Build Coastguard Worker }
88*b9df5ad1SAndroid Build Coastguard Worker 
89*b9df5ad1SAndroid Build Coastguard Worker void RefIndexDeferredStoreReleaseDeferredWake::writethrough(uint32_t value) {
90*b9df5ad1SAndroid Build Coastguard Worker     set(value);
91*b9df5ad1SAndroid Build Coastguard Worker     writeback();
92*b9df5ad1SAndroid Build Coastguard Worker }
93*b9df5ad1SAndroid Build Coastguard Worker 
94*b9df5ad1SAndroid Build Coastguard Worker void RefIndexDeferredStoreReleaseDeferredWake::wakeDeferred(int op, int waiters)
95*b9df5ad1SAndroid Build Coastguard Worker {
96*b9df5ad1SAndroid Build Coastguard Worker     if (waiters <= 0) {
97*b9df5ad1SAndroid Build Coastguard Worker         return;
98*b9df5ad1SAndroid Build Coastguard Worker     }
99*b9df5ad1SAndroid Build Coastguard Worker     // default is FUTEX_WAKE_PRIVATE
100*b9df5ad1SAndroid Build Coastguard Worker     if (op == FUTEX_WAKE) {
101*b9df5ad1SAndroid Build Coastguard Worker         mWakeOp = FUTEX_WAKE;
102*b9df5ad1SAndroid Build Coastguard Worker     }
103*b9df5ad1SAndroid Build Coastguard Worker     if (waiters < INT_MAX - mWaiters) {
104*b9df5ad1SAndroid Build Coastguard Worker         mWaiters += waiters;
105*b9df5ad1SAndroid Build Coastguard Worker     } else {
106*b9df5ad1SAndroid Build Coastguard Worker         mWaiters = INT_MAX;
107*b9df5ad1SAndroid Build Coastguard Worker     }
108*b9df5ad1SAndroid Build Coastguard Worker }
109*b9df5ad1SAndroid Build Coastguard Worker 
110*b9df5ad1SAndroid Build Coastguard Worker void RefIndexDeferredStoreReleaseDeferredWake::wakeNowIfNeeded()
111*b9df5ad1SAndroid Build Coastguard Worker {
112*b9df5ad1SAndroid Build Coastguard Worker     if (mWaiters > 0) {
113*b9df5ad1SAndroid Build Coastguard Worker         mIndex.wake(mWakeOp, mWaiters);
114*b9df5ad1SAndroid Build Coastguard Worker         mWaiters = 0;
115*b9df5ad1SAndroid Build Coastguard Worker         mWakeOp = FUTEX_WAKE_PRIVATE;
116*b9df5ad1SAndroid Build Coastguard Worker     }
117*b9df5ad1SAndroid Build Coastguard Worker }
118*b9df5ad1SAndroid Build Coastguard Worker 
119*b9df5ad1SAndroid Build Coastguard Worker void RefIndexDeferredStoreReleaseDeferredWake::wakeNow(int op, int waiters)
120*b9df5ad1SAndroid Build Coastguard Worker {
121*b9df5ad1SAndroid Build Coastguard Worker     wakeDeferred(op, waiters);
122*b9df5ad1SAndroid Build Coastguard Worker     wakeNowIfNeeded();
123*b9df5ad1SAndroid Build Coastguard Worker }
124*b9df5ad1SAndroid Build Coastguard Worker 
125*b9df5ad1SAndroid Build Coastguard Worker ////
126*b9df5ad1SAndroid Build Coastguard Worker 
127*b9df5ad1SAndroid Build Coastguard Worker RefIndexCachedLoadAcquireDeferredWait::RefIndexCachedLoadAcquireDeferredWait(
128*b9df5ad1SAndroid Build Coastguard Worker         audio_utils_fifo_index& index)
129*b9df5ad1SAndroid Build Coastguard Worker     : mIndex(index), mValue(0), mLoaded(false)
130*b9df5ad1SAndroid Build Coastguard Worker {
131*b9df5ad1SAndroid Build Coastguard Worker }
132*b9df5ad1SAndroid Build Coastguard Worker 
133*b9df5ad1SAndroid Build Coastguard Worker RefIndexCachedLoadAcquireDeferredWait::~RefIndexCachedLoadAcquireDeferredWait()
134*b9df5ad1SAndroid Build Coastguard Worker {
135*b9df5ad1SAndroid Build Coastguard Worker }
136*b9df5ad1SAndroid Build Coastguard Worker 
137*b9df5ad1SAndroid Build Coastguard Worker uint32_t RefIndexCachedLoadAcquireDeferredWait::get()
138*b9df5ad1SAndroid Build Coastguard Worker {
139*b9df5ad1SAndroid Build Coastguard Worker     prefetch();
140*b9df5ad1SAndroid Build Coastguard Worker     return mValue;
141*b9df5ad1SAndroid Build Coastguard Worker }
142*b9df5ad1SAndroid Build Coastguard Worker 
143*b9df5ad1SAndroid Build Coastguard Worker void RefIndexCachedLoadAcquireDeferredWait::prefetch()
144*b9df5ad1SAndroid Build Coastguard Worker {
145*b9df5ad1SAndroid Build Coastguard Worker     if (!mLoaded) {
146*b9df5ad1SAndroid Build Coastguard Worker         // TODO When part of a collection, should use relaxed for all but the last load
147*b9df5ad1SAndroid Build Coastguard Worker         mValue = mIndex.loadAcquire();
148*b9df5ad1SAndroid Build Coastguard Worker         mLoaded = true;
149*b9df5ad1SAndroid Build Coastguard Worker     }
150*b9df5ad1SAndroid Build Coastguard Worker }
151*b9df5ad1SAndroid Build Coastguard Worker 
152*b9df5ad1SAndroid Build Coastguard Worker void RefIndexCachedLoadAcquireDeferredWait::invalidate()
153*b9df5ad1SAndroid Build Coastguard Worker {
154*b9df5ad1SAndroid Build Coastguard Worker     mLoaded = false;
155*b9df5ad1SAndroid Build Coastguard Worker }
156*b9df5ad1SAndroid Build Coastguard Worker 
157*b9df5ad1SAndroid Build Coastguard Worker #if 0
158*b9df5ad1SAndroid Build Coastguard Worker uint32_t RefIndexCachedLoadAcquireDeferredWait::readthrough()
159*b9df5ad1SAndroid Build Coastguard Worker {
160*b9df5ad1SAndroid Build Coastguard Worker     invalidate();
161*b9df5ad1SAndroid Build Coastguard Worker     return get();
162*b9df5ad1SAndroid Build Coastguard Worker }
163*b9df5ad1SAndroid Build Coastguard Worker #endif
164*b9df5ad1SAndroid Build Coastguard Worker 
165*b9df5ad1SAndroid Build Coastguard Worker int RefIndexCachedLoadAcquireDeferredWait::wait(int op, const struct timespec *timeout)
166*b9df5ad1SAndroid Build Coastguard Worker {
167*b9df5ad1SAndroid Build Coastguard Worker     if (!mLoaded) {
168*b9df5ad1SAndroid Build Coastguard Worker         return -EINVAL;
169*b9df5ad1SAndroid Build Coastguard Worker     }
170*b9df5ad1SAndroid Build Coastguard Worker     int err = mIndex.wait(op, mValue /*expected*/, timeout);
171*b9df5ad1SAndroid Build Coastguard Worker     invalidate();
172*b9df5ad1SAndroid Build Coastguard Worker     return err;
173*b9df5ad1SAndroid Build Coastguard Worker }
174*b9df5ad1SAndroid Build Coastguard Worker 
175*b9df5ad1SAndroid Build Coastguard Worker #endif  // 0
176