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 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 32 RingBuffer::~RingBuffer() { 33 free(mData); 34 mData = NULL; 35 } 36 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 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 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 110 LockfreeBuffer::~LockfreeBuffer() { 111 memset(mData, 0, mSize*sizeof(sensors_event_t)); 112 } 113 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