2 * Copyright (C) ARM Limited 2010-2014. All rights reserved.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
15 // bufferSize is the amount of data to be filled
16 // singleBufferSize is the maximum size that may be filled during a single write
17 // (bufferSize + singleBufferSize) will be allocated
18 Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) {
19 mWrite = mRead = mReadCommit = mRaggedEnd = 0;
20 mWrapThreshold = bufferSize;
21 mSingleBufferSize = singleBufferSize;
22 mReaderSem = readerSem;
23 mBuffer = (char*)malloc(bufferSize + singleBufferSize);
26 if (mBuffer == NULL) {
27 logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize);
31 if (sem_init(&mWaitForSpaceSem, 0, 0)) {
32 logg->logError(__FILE__, __LINE__, "sem_init() failed");
39 sem_destroy(&mWaitForSpaceSem);
42 int Fifo::numBytesFilled() const {
43 return mWrite - mRead + mRaggedEnd;
46 char* Fifo::start() const {
50 bool Fifo::isEmpty() const {
51 return mRead == mWrite && mRaggedEnd == 0;
54 bool Fifo::isFull() const {
58 // Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer
59 // 'full' means there is less than singleBufferSize bytes available contiguously; it does not mean there are zero bytes available
60 bool Fifo::willFill(int additional) const {
62 if (numBytesFilled() + additional < mWrapThreshold) {
66 if (numBytesFilled() + additional < mWrapThreshold - mSingleBufferSize) {
73 // This function will stall until contiguous singleBufferSize bytes are available
74 char* Fifo::write(int length) {
80 // update the write pointer
83 // handle the wrap-around
84 if (mWrite >= mWrapThreshold) {
89 // send a notification that data is ready
94 sem_wait(&mWaitForSpaceSem);
97 return &mBuffer[mWrite];
100 void Fifo::release() {
101 // update the read pointer now that the data has been handled
104 // handle the wrap-around
105 if (mRead >= mWrapThreshold) {
106 mRaggedEnd = mRead = mReadCommit = 0;
109 // send a notification that data is free (space is available)
110 sem_post(&mWaitForSpaceSem);
113 // This function will return null if no data is available
114 char* Fifo::read(int *const length) {
116 if (isEmpty() && !mEnd) {
122 mReadCommit = mRaggedEnd ? mRaggedEnd : mWrite;
123 *length = mReadCommit - mRead;
124 } while (*length < 0); // plugs race condition without using semaphores
126 return &mBuffer[mRead];