Home | History | Annotate | Download | only in common
      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