]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blob - daemon/Fifo.cpp
gator: Use for_each_kernel_tracepoint in Linux 3.15
[android-sdk/arm-ds5-gator.git] / daemon / Fifo.cpp
1 /**
2  * Copyright (C) ARM Limited 2010-2014. All rights reserved.
3  *
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.
7  */
9 #include "Fifo.h"
11 #include <stdlib.h>
12 #ifdef WIN32
13 #define valloc malloc
14 #endif
16 #include "Logging.h"
18 // bufferSize is the amount of data to be filled
19 // singleBufferSize is the maximum size that may be filled during a single write
20 // (bufferSize + singleBufferSize) will be allocated
21 Fifo::Fifo(int singleBufferSize, int bufferSize, sem_t* readerSem) {
22   mWrite = mRead = mReadCommit = mRaggedEnd = 0;
23   mWrapThreshold = bufferSize;
24   mSingleBufferSize = singleBufferSize;
25   mReaderSem = readerSem;
26   mBuffer = (char*)valloc(bufferSize + singleBufferSize);
27   mEnd = false;
29   if (mBuffer == NULL) {
30     logg->logError(__FILE__, __LINE__, "failed to allocate %d bytes", bufferSize + singleBufferSize);
31     handleException();
32   }
34   if (sem_init(&mWaitForSpaceSem, 0, 0)) {
35     logg->logError(__FILE__, __LINE__, "sem_init() failed");
36     handleException();
37   }
38 }
40 Fifo::~Fifo() {
41   free(mBuffer);
42   sem_destroy(&mWaitForSpaceSem);
43 }
45 int Fifo::numBytesFilled() const {
46   return mWrite - mRead + mRaggedEnd;
47 }
49 char* Fifo::start() const {
50   return mBuffer;
51 }
53 bool Fifo::isEmpty() const {
54   return mRead == mWrite && mRaggedEnd == 0;
55 }
57 bool Fifo::isFull() const {
58   return willFill(0);
59 }
61 // Determines if the buffer will fill assuming 'additional' bytes will be added to the buffer
62 // 'full' means there is less than singleBufferSize bytes available contiguously; it does not mean there are zero bytes available
63 bool Fifo::willFill(int additional) const {
64   if (mWrite > mRead) {
65     if (numBytesFilled() + additional < mWrapThreshold) {
66       return false;
67     }
68   } else {
69     if (numBytesFilled() + additional < mWrapThreshold - mSingleBufferSize) {
70       return false;
71     }
72   }
73   return true;
74 }
76 // This function will stall until contiguous singleBufferSize bytes are available
77 char* Fifo::write(int length) {
78   if (length <= 0) {
79     length = 0;
80     mEnd = true;
81   }
83   // update the write pointer
84   mWrite += length;
86   // handle the wrap-around
87   if (mWrite >= mWrapThreshold) {
88     mRaggedEnd = mWrite;
89     mWrite = 0;
90   }
92   // send a notification that data is ready
93   sem_post(mReaderSem);
95   // wait for space
96   while (isFull()) {
97     sem_wait(&mWaitForSpaceSem);
98   }
100   return &mBuffer[mWrite];
103 void Fifo::release() {
104   // update the read pointer now that the data has been handled
105   mRead = mReadCommit;
107   // handle the wrap-around
108   if (mRead >= mWrapThreshold) {
109     mRaggedEnd = mRead = mReadCommit = 0;
110   }
112   // send a notification that data is free (space is available)
113   sem_post(&mWaitForSpaceSem);
116 // This function will return null if no data is available
117 char* Fifo::read(int *const length) {
118   // wait for data
119   if (isEmpty() && !mEnd) {
120     return NULL;
121   }
123   // obtain the length
124   do {
125     mReadCommit = mRaggedEnd ? mRaggedEnd : mWrite;
126     *length = mReadCommit - mRead;
127   } while (*length < 0); // plugs race condition without using semaphores
129   return &mBuffer[mRead];