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