NBLog.h revision ab7d72f0804fbb7e91ad9d2a16f826d97e20e5d0
1/* 2 * Copyright (C) 2013 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// Non-blocking event logger intended for safe communication between processes via shared memory 18 19#ifndef ANDROID_MEDIA_NBLOG_H 20#define ANDROID_MEDIA_NBLOG_H 21 22#include <binder/IMemory.h> 23#include <utils/Mutex.h> 24#include <media/nbaio/roundup.h> 25 26namespace android { 27 28class NBLog { 29 30public: 31 32class Writer; 33class Reader; 34 35private: 36 37enum Event { 38 EVENT_RESERVED, 39 EVENT_STRING, // ASCII string, not NUL-terminated 40 EVENT_TIMESTAMP, // clock_gettime(CLOCK_MONOTONIC) 41}; 42 43// --------------------------------------------------------------------------- 44 45// representation of a single log entry in private memory 46struct Entry { 47 Entry(Event event, const void *data, size_t length) 48 : mEvent(event), mLength(length), mData(data) { } 49 /*virtual*/ ~Entry() { } 50 51 int readAt(size_t offset) const; 52 53private: 54 friend class Writer; 55 Event mEvent; // event type 56 size_t mLength; // length of additional data, 0 <= mLength <= 255 57 const void *mData; // event type-specific data 58}; 59 60// representation of a single log entry in shared memory 61// byte[0] mEvent 62// byte[1] mLength 63// byte[2] mData[0] 64// ... 65// byte[2+i] mData[i] 66// ... 67// byte[2+mLength-1] mData[mLength-1] 68// byte[2+mLength] duplicate copy of mLength to permit reverse scan 69// byte[3+mLength] start of next log entry 70 71// located in shared memory 72struct Shared { 73 Shared() : mRear(0) { } 74 /*virtual*/ ~Shared() { } 75 76 volatile int32_t mRear; // index one byte past the end of most recent Entry 77 char mBuffer[0]; // circular buffer for entries 78}; 79 80public: 81 82// --------------------------------------------------------------------------- 83 84// FIXME Timeline was intended to wrap Writer and Reader, but isn't actually used yet. 85// For now it is just a namespace for sharedSize(). 86class Timeline : public RefBase { 87public: 88#if 0 89 Timeline(size_t size, void *shared = NULL); 90 virtual ~Timeline(); 91#endif 92 93 static size_t sharedSize(size_t size); 94 95#if 0 96private: 97 friend class Writer; 98 friend class Reader; 99 100 const size_t mSize; // circular buffer size in bytes, must be a power of 2 101 bool mOwn; // whether I own the memory at mShared 102 Shared* const mShared; // pointer to shared memory 103#endif 104}; 105 106// --------------------------------------------------------------------------- 107 108// Writer is thread-safe with respect to Reader, but not with respect to multiple threads 109// calling Writer methods. If you need multi-thread safety for writing, use LockedWriter. 110class Writer : public RefBase { 111public: 112 Writer(); // dummy nop implementation without shared memory 113 Writer(size_t size, void *shared); 114 Writer(size_t size, const sp<IMemory>& iMemory); 115 virtual ~Writer() { } 116 117 virtual void log(const char *string); 118 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 119 virtual void logvf(const char *fmt, va_list ap); 120 virtual void logTimestamp(); 121 virtual void logTimestamp(const struct timespec& ts); 122 123 virtual bool isEnabled() const; 124 125 // return value for all of these is the previous isEnabled() 126 virtual bool setEnabled(bool enabled); // but won't enable if no shared memory 127 bool enable() { return setEnabled(true); } 128 bool disable() { return setEnabled(false); } 129 130 sp<IMemory> getIMemory() const { return mIMemory; } 131 132private: 133 void log(Event event, const void *data, size_t length); 134 void log(const Entry *entry, bool trusted = false); 135 136 const size_t mSize; // circular buffer size in bytes, must be a power of 2 137 Shared* const mShared; // raw pointer to shared memory 138 const sp<IMemory> mIMemory; // ref-counted version 139 int32_t mRear; // my private copy of mShared->mRear 140 bool mEnabled; // whether to actually log 141}; 142 143// --------------------------------------------------------------------------- 144 145// Similar to Writer, but safe for multiple threads to call concurrently 146class LockedWriter : public Writer { 147public: 148 LockedWriter(); 149 LockedWriter(size_t size, void *shared); 150 151 virtual void log(const char *string); 152 virtual void logf(const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); 153 virtual void logvf(const char *fmt, va_list ap); 154 virtual void logTimestamp(); 155 virtual void logTimestamp(const struct timespec& ts); 156 157 virtual bool isEnabled() const; 158 virtual bool setEnabled(bool enabled); 159 160private: 161 mutable Mutex mLock; 162}; 163 164// --------------------------------------------------------------------------- 165 166class Reader : public RefBase { 167public: 168 Reader(size_t size, const void *shared); 169 Reader(size_t size, const sp<IMemory>& iMemory); 170 virtual ~Reader() { } 171 172 void dump(int fd, size_t indent = 0); 173 bool isIMemory(const sp<IMemory>& iMemory) const; 174 175private: 176 const size_t mSize; // circular buffer size in bytes, must be a power of 2 177 const Shared* const mShared; // raw pointer to shared memory 178 const sp<IMemory> mIMemory; // ref-counted version 179 int32_t mFront; // index of oldest acknowledged Entry 180 181 static const size_t kSquashTimestamp = 5; // squash this many or more adjacent timestamps 182}; 183 184}; // class NBLog 185 186} // namespace android 187 188#endif // ANDROID_MEDIA_NBLOG_H 189