]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/arm-ds5-gator.git/blobdiff - daemon/Buffer.cpp
gator: Version 5.18
[android-sdk/arm-ds5-gator.git] / daemon / Buffer.cpp
index 090a71553277b6ab74073552c106a627688b2588..93557dabed9f1835910243ab7cff0802ad3d38fe 100644 (file)
@@ -1,5 +1,5 @@
 /**
- * Copyright (C) ARM Limited 2013. All rights reserved.
+ * Copyright (C) ARM Limited 2013-2014. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include "Sender.h"
 #include "SessionData.h"
 
-#define mask (size - 1)
-
-Buffer::Buffer (const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : core(core), buftype(buftype), size(size), readPos(0), writePos(0), commitPos(0), available(true), done(false), buf(new char[size]), commitTime(gSessionData->mLiveRate), readerSem(readerSem) {
-       if ((size & mask) != 0) {
+#define mask (mSize - 1)
+
+enum {
+       CODE_PEA    = 1,
+       CODE_KEYS   = 2,
+       CODE_FORMAT = 3,
+       CODE_MAPS   = 4,
+       CODE_COMM   = 5,
+};
+
+// Summary Frame Messages
+enum {
+       MESSAGE_SUMMARY = 1,
+       MESSAGE_CORE_NAME = 3,
+};
+
+// From gator_marshaling.c
+#define NEWLINE_CANARY \
+       /* Unix */ \
+       "1\n" \
+       /* Windows */ \
+       "2\r\n" \
+       /* Mac OS */ \
+       "3\r" \
+       /* RISC OS */ \
+       "4\n\r" \
+       /* Add another character so the length isn't 0x0a bytes */ \
+       "5"
+
+Buffer::Buffer(const int32_t core, const int32_t buftype, const int size, sem_t *const readerSem) : mCore(core), mBufType(buftype), mSize(size), mReadPos(0), mWritePos(0), mCommitPos(0), mAvailable(true), mIsDone(false), mBuf(new char[mSize]), mCommitTime(gSessionData->mLiveRate), mReaderSem(readerSem) {
+       if ((mSize & mask) != 0) {
                logg->logError(__FILE__, __LINE__, "Buffer size is not a power of 2");
                handleException();
        }
        frame();
 }
 
-Buffer::~Buffer () {
-       delete [] buf;
+Buffer::~Buffer() {
+       delete [] mBuf;
 }
 
-void Buffer::write (Sender * const sender) {
+void Buffer::write(Sender *const sender) {
        if (!commitReady()) {
                return;
        }
 
        // determine the size of two halves
-       int length1 = commitPos - readPos;
-       char * buffer1 = buf + readPos;
+       int length1 = mCommitPos - mReadPos;
+       char *buffer1 = mBuf + mReadPos;
        int length2 = 0;
-       char * buffer2 = buf;
+       char *buffer2 = mBuf;
        if (length1 < 0) {
-               length1 = size - readPos;
-               length2 = commitPos;
+               length1 = mSize - mReadPos;
+               length2 = mCommitPos;
        }
 
        logg->logMessage("Sending data length1: %i length2: %i", length1, length2);
@@ -53,22 +80,22 @@ void Buffer::write (Sender * const sender) {
                sender->writeData(buffer2, length2, RESPONSE_APC_DATA);
        }
 
-       readPos = commitPos;
+       mReadPos = mCommitPos;
 }
 
-bool Buffer::commitReady () const {
-       return commitPos != readPos;
+bool Buffer::commitReady() const {
+       return mCommitPos != mReadPos;
 }
 
-int Buffer::bytesAvailable () const {
-       int filled = writePos - readPos;
+int Buffer::bytesAvailable() const {
+       int filled = mWritePos - mReadPos;
        if (filled < 0) {
-               filled += size;
+               filled += mSize;
        }
 
-       int remaining = size - filled;
+       int remaining = mSize - filled;
 
-       if (available) {
+       if (mAvailable) {
                // Give some extra room; also allows space to insert the overflow error packet
                remaining -= 200;
        } else {
@@ -79,58 +106,68 @@ int Buffer::bytesAvailable () const {
        return remaining;
 }
 
-bool Buffer::checkSpace (const int bytes) {
+bool Buffer::checkSpace(const int bytes) {
        const int remaining = bytesAvailable();
 
        if (remaining < bytes) {
-               available = false;
+               mAvailable = false;
        } else {
-               available = true;
+               mAvailable = true;
        }
 
-       return available;
+       return mAvailable;
+}
+
+int Buffer::contiguousSpaceAvailable() const {
+       int remaining = bytesAvailable();
+       int contiguous = mSize - mWritePos;
+       if (remaining < contiguous) {
+               return remaining;
+       } else {
+               return contiguous;
+       }
 }
 
-void Buffer::commit (const uint64_t time) {
+void Buffer::commit(const uint64_t time) {
        // post-populate the length, which does not include the response type length nor the length itself, i.e. only the length of the payload
        const int typeLength = gSessionData->mLocalCapture ? 0 : 1;
-       int length = writePos - commitPos;
+       int length = mWritePos - mCommitPos;
        if (length < 0) {
-               length += size;
+               length += mSize;
        }
        length = length - typeLength - sizeof(int32_t);
        for (size_t byte = 0; byte < sizeof(int32_t); byte++) {
-               buf[(commitPos + typeLength + byte) & mask] = (length >> byte * 8) & 0xFF;
+               mBuf[(mCommitPos + typeLength + byte) & mask] = (length >> byte * 8) & 0xFF;
        }
 
-       logg->logMessage("Committing data readPos: %i writePos: %i commitPos: %i", readPos, writePos, commitPos);
-       commitPos = writePos;
+       logg->logMessage("Committing data mReadPos: %i mWritePos: %i mCommitPos: %i", mReadPos, mWritePos, mCommitPos);
+       mCommitPos = mWritePos;
 
        if (gSessionData->mLiveRate > 0) {
-               while (time > commitTime) {
-                       commitTime += gSessionData->mLiveRate;
+               while (time > mCommitTime) {
+                       mCommitTime += gSessionData->mLiveRate;
                }
        }
 
-       if (!done) {
+       if (!mIsDone) {
                frame();
        }
 
        // send a notification that data is ready
-       sem_post(readerSem);
+       sem_post(mReaderSem);
 }
 
-void Buffer::check (const uint64_t time) {
-       int filled = writePos - commitPos;
+void Buffer::check(const uint64_t time) {
+       int filled = mWritePos - mCommitPos;
        if (filled < 0) {
-               filled += size;
+               filled += mSize;
        }
-       if (filled >= ((size * 3) / 4) || (gSessionData->mLiveRate > 0 && time >= commitTime)) {
+       if (filled >= ((mSize * 3) / 4) || (gSessionData->mLiveRate > 0 && time >= mCommitTime)) {
                commit(time);
        }
 }
 
-void Buffer::packInt (int32_t x) {
+void Buffer::packInt(int32_t x) {
        int packedBytes = 0;
        int more = true;
        while (more) {
@@ -144,14 +181,14 @@ void Buffer::packInt (int32_t x) {
                        b |= 0x80;
                }
 
-               buf[(writePos + packedBytes) & mask] = b;
+               mBuf[(mWritePos + packedBytes) & mask] = b;
                packedBytes++;
        }
 
-       writePos = (writePos + packedBytes) & mask;
+       mWritePos = (mWritePos + packedBytes) & mask;
 }
 
-void Buffer::packInt64 (int64_t x) {
+void Buffer::packInt64(int64_t x) {
        int packedBytes = 0;
        int more = true;
        while (more) {
@@ -165,24 +202,61 @@ void Buffer::packInt64 (int64_t x) {
                        b |= 0x80;
                }
 
-               buf[(writePos + packedBytes) & mask] = b;
+               mBuf[(mWritePos + packedBytes) & mask] = b;
                packedBytes++;
        }
 
-       writePos = (writePos + packedBytes) & mask;
+       mWritePos = (mWritePos + packedBytes) & mask;
+}
+
+void Buffer::writeBytes(const void *const data, size_t count) {
+       size_t i;
+       for (i = 0; i < count; ++i) {
+               mBuf[(mWritePos + i) & mask] = static_cast<const char *>(data)[i];
+       }
+
+       mWritePos = (mWritePos + i) & mask;
 }
 
-void Buffer::frame () {
+void Buffer::writeString(const char *const str) {
+       const int len = strlen(str);
+       packInt(len);
+       writeBytes(str, len);
+}
+
+void Buffer::frame() {
        if (!gSessionData->mLocalCapture) {
                packInt(RESPONSE_APC_DATA);
        }
        // Reserve space for the length
-       writePos += sizeof(int32_t);
-       packInt(buftype);
-       packInt(core);
+       mWritePos += sizeof(int32_t);
+       packInt(mBufType);
+       packInt(mCore);
 }
 
-bool Buffer::eventHeader (const uint64_t curr_time) {
+void Buffer::summary(const int64_t timestamp, const int64_t uptime, const int64_t monotonicDelta, const char *const uname) {
+       packInt(MESSAGE_SUMMARY);
+       writeString(NEWLINE_CANARY);
+       packInt64(timestamp);
+       packInt64(uptime);
+       packInt64(monotonicDelta);
+       writeString("uname");
+       writeString(uname);
+       writeString("");
+       check(1);
+}
+
+void Buffer::coreName(const int core, const int cpuid, const char *const name) {
+       if (checkSpace(3 * MAXSIZE_PACK32 + 0x100)) {
+               packInt(MESSAGE_CORE_NAME);
+               packInt(core);
+               packInt(cpuid);
+               writeString(name);
+       }
+       check(1);
+}
+
+bool Buffer::eventHeader(const uint64_t curr_time) {
        bool retval = false;
        if (checkSpace(MAXSIZE_PACK32 + MAXSIZE_PACK64)) {
                packInt(0);     // key of zero indicates a timestamp
@@ -193,9 +267,9 @@ bool Buffer::eventHeader (const uint64_t curr_time) {
        return retval;
 }
 
-bool Buffer::eventTid (const int tid) {
+bool Buffer::eventTid(const int tid) {
        bool retval = false;
-       if (checkSpace(2*MAXSIZE_PACK32)) {
+       if (checkSpace(2 * MAXSIZE_PACK32)) {
                packInt(1);     // key of 1 indicates a tid
                packInt(tid);
                retval = true;
@@ -204,25 +278,94 @@ bool Buffer::eventTid (const int tid) {
        return retval;
 }
 
-void Buffer::event (const int32_t key, const int32_t value) {
+void Buffer::event(const int32_t key, const int32_t value) {
        if (checkSpace(2 * MAXSIZE_PACK32)) {
                packInt(key);
                packInt(value);
        }
 }
 
-void Buffer::event64 (const int64_t key, const int64_t value) {
+void Buffer::event64(const int64_t key, const int64_t value) {
        if (checkSpace(2 * MAXSIZE_PACK64)) {
                packInt64(key);
                packInt64(value);
        }
 }
 
-void Buffer::setDone () {
-       done = true;
+void Buffer::pea(const struct perf_event_attr *const pea, int key) {
+       if (checkSpace(2 * MAXSIZE_PACK32 + pea->size)) {
+               packInt(CODE_PEA);
+               writeBytes(pea, pea->size);
+               packInt(key);
+       } else {
+               logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
+               handleException();
+       }
+       // Don't know the real perf time so use 1 as it will work for now
+       check(1);
+}
+
+void Buffer::keys(const int count, const __u64 *const ids, const int *const keys) {
+       if (checkSpace(2 * MAXSIZE_PACK32 + count * (MAXSIZE_PACK32 + MAXSIZE_PACK64))) {
+               packInt(CODE_KEYS);
+               packInt(count);
+               for (int i = 0; i < count; ++i) {
+                       packInt64(ids[i]);
+                       packInt(keys[i]);
+               }
+       } else {
+               logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
+               handleException();
+       }
+       check(1);
+}
+
+void Buffer::format(const int length, const char *const format) {
+       if (checkSpace(MAXSIZE_PACK32 + length + 1)) {
+               packInt(CODE_FORMAT);
+               writeBytes(format, length + 1);
+       } else {
+               logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
+               handleException();
+       }
+       check(1);
+}
+
+void Buffer::maps(const int pid, const int tid, const char *const maps) {
+       const int mapsLen = strlen(maps) + 1;
+       if (checkSpace(3 * MAXSIZE_PACK32 + mapsLen)) {
+               packInt(CODE_MAPS);
+               packInt(pid);
+               packInt(tid);
+               writeBytes(maps, mapsLen);
+       } else {
+               logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
+               handleException();
+       }
+       check(1);
+}
+
+void Buffer::comm(const int pid, const int tid, const char *const image, const char *const comm) {
+       const int imageLen = strlen(image) + 1;
+       const int commLen = strlen(comm) + 1;
+       if (checkSpace(3 * MAXSIZE_PACK32 + imageLen + commLen)) {
+               packInt(CODE_COMM);
+               packInt(pid);
+               packInt(tid);
+               writeBytes(image, imageLen);
+               writeBytes(comm, commLen);
+       } else {
+               logg->logError(__FILE__, __LINE__, "Ran out of buffer space for perf attrs");
+               handleException();
+       }
+       check(1);
+}
+
+void Buffer::setDone() {
+       mIsDone = true;
        commit(0);
 }
 
-bool Buffer::isDone () const {
-       return done && readPos == commitPos && commitPos == writePos;
+bool Buffer::isDone() const {
+       return mIsDone && mReadPos == mCommitPos && mCommitPos == mWritePos;
 }