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