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