1 /*
2 * Copyright (C) 2015 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 "ring.h"
18
19 #include <stdlib.h>
20 #include <string.h>
21 #include <atomic>
22
23 namespace android {
24
RingBuffer(size_t size)25 RingBuffer::RingBuffer(size_t size)
26 : mSize(size),
27 mData((sensors_event_t *)malloc(sizeof(sensors_event_t) * mSize)),
28 mReadPos(0),
29 mWritePos(0) {
30 }
31
~RingBuffer()32 RingBuffer::~RingBuffer() {
33 free(mData);
34 mData = NULL;
35 }
36
write(const sensors_event_t * ev,size_t size)37 ssize_t RingBuffer::write(const sensors_event_t *ev, size_t size) {
38 Mutex::Autolock autoLock(mLock);
39
40 size_t numAvailableToRead = mWritePos - mReadPos;
41 size_t numAvailableToWrite = mSize - numAvailableToRead;
42
43 if (size > numAvailableToWrite) {
44 size = numAvailableToWrite;
45 }
46
47 size_t writePos = (mWritePos % mSize);
48 size_t copy = mSize - writePos;
49
50 if (copy > size) {
51 copy = size;
52 }
53
54 memcpy(&mData[writePos], ev, copy * sizeof(sensors_event_t));
55
56 if (size > copy) {
57 memcpy(mData, &ev[copy], (size - copy) * sizeof(sensors_event_t));
58 }
59
60 mWritePos += size;
61
62 if (numAvailableToRead == 0 && size > 0) {
63 mNotEmptyCondition.broadcast();
64 }
65
66 return size;
67 }
68
read(sensors_event_t * ev,size_t size)69 ssize_t RingBuffer::read(sensors_event_t *ev, size_t size) {
70 Mutex::Autolock autoLock(mLock);
71
72 size_t numAvailableToRead;
73 for (;;) {
74 numAvailableToRead = mWritePos - mReadPos;
75 if (numAvailableToRead > 0) {
76 break;
77 }
78
79 mNotEmptyCondition.wait(mLock);
80 }
81
82 if (size > numAvailableToRead) {
83 size = numAvailableToRead;
84 }
85
86 size_t readPos = (mReadPos % mSize);
87 size_t copy = mSize - readPos;
88
89 if (copy > size) {
90 copy = size;
91 }
92
93 memcpy(ev, &mData[readPos], copy * sizeof(sensors_event_t));
94
95 if (size > copy) {
96 memcpy(&ev[copy], mData, (size - copy) * sizeof(sensors_event_t));
97 }
98
99 mReadPos += size;
100
101 return size;
102 }
103
LockfreeBuffer(void * buf,size_t size)104 LockfreeBuffer::LockfreeBuffer(void* buf, size_t size)
105 : mData((sensors_event_t *)buf), mSize(size/sizeof(sensors_event_t)),
106 mWritePos(0), mCounter(1) {
107 memset(mData, 0, size);
108 }
109
~LockfreeBuffer()110 LockfreeBuffer::~LockfreeBuffer() {
111 memset(mData, 0, mSize*sizeof(sensors_event_t));
112 }
113
write(const sensors_event_t * ev,size_t size)114 void LockfreeBuffer::write(const sensors_event_t *ev, size_t size) {
115 if (!mSize) {
116 return;
117 }
118
119 while(size--) {
120 // part before reserved0 field
121 memcpy(&mData[mWritePos], ev, offsetof(sensors_event_t, reserved0));
122 // part after reserved0 field
123 memcpy(reinterpret_cast<char *>(&mData[mWritePos]) + offsetof(sensors_event_t, timestamp),
124 reinterpret_cast<const char *>(ev) + offsetof(sensors_event_t, timestamp),
125 sizeof(sensors_event_t) - offsetof(sensors_event_t, timestamp));
126 // barrier before writing the atomic counter
127 std::atomic_thread_fence(std::memory_order_release);
128 mData[mWritePos].reserved0 = mCounter++;
129 // barrier after writing the atomic counter
130 std::atomic_thread_fence(std::memory_order_release);
131 ++ev;
132
133 if (++mWritePos >= mSize) {
134 mWritePos = 0;
135 }
136 }
137 }
138
139 } // namespace android
140
141