1c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev/* 2c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Copyright (C) Texas Instruments - http://www.ti.com/ 3c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * 4c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Licensed under the Apache License, Version 2.0 (the "License"); 5c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * you may not use this file except in compliance with the License. 6c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * You may obtain a copy of the License at 7c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * 8c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * http://www.apache.org/licenses/LICENSE-2.0 9c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * 10c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * Unless required by applicable law or agreed to in writing, software 11c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * distributed under the License is distributed on an "AS IS" BASIS, 12c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * See the License for the specific language governing permissions and 14c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev * limitations under the License. 15c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev */ 16c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 17c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#ifndef DEBUG_UTILS_H 18c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev#define DEBUG_UTILS_H 19c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 20f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#include <android/log.h> 21f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#include <utils/threads.h> 22f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#include <utils/Vector.h> 23c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 24c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 25c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 26c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 27f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsnamespace Ti { 28f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 29f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 30f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 31f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 32f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons// use 2 space characters for call stack indent 33f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsstatic const int kFunctionLoggerIndentSize = 2; 34f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 35f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 36f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 37f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 38f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonstemplate <int Size = kFunctionLoggerIndentSize> 39f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsclass IndentString 40f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 41f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonspublic: 42f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons IndentString(int length); 43f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 44f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const char * string() const; 45f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 46f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 47f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons int calculateOffset(int length) const; 48f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 49f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 50f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const int mOffset; 51f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons}; 52f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 53f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 54f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 55f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 56f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsclass Debug 57f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 58f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonspublic: 59f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons static Debug * instance(); 60f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 61f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons int offsetForCurrentThread(); 62f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons void log(int priority, const char * format, ...); 63f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 64f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 65f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons class ThreadInfo 66f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { 67f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons public: 68f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo() : 69f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons threadId(0), callOffset(0) 70f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons {} 71f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 72f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons volatile int32_t threadId; 73f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons int callOffset; 74f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons }; 75f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 76f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons class Data : public android::RefBase 77f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { 78f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons public: 79f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::Vector<ThreadInfo*> threads; 80f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons }; 81f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 82f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 83f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // called from FunctionLogger 84f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons void increaseOffsetForCurrentThread(); 85f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons void decreaseOffsetForCurrentThread(); 86f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 87f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 88f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons Debug(); 89f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 90f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons void grow(); 91f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo * registerThread(Data * data, int32_t threadId); 92f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo * findCurrentThreadInfo(); 93f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons void addOffsetForCurrentThread(int offset); 94f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 95f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 96f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons static Debug sInstance; 97f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 98f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mutable android::Mutex mMutex; 99f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::sp<Data> mData; 100f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 101f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons friend class FunctionLogger; 102f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons}; 103f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 104f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 105f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 106f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 107f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsclass FunctionLogger 108f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 109f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonspublic: 110f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons FunctionLogger(const char * file, int line, const char * function); 111f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ~FunctionLogger(); 112f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 113f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons void setExitLine(int line); 114f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 115f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsprivate: 116f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const char * const mFile; 117f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const int mLine; 118f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const char * const mFunction; 119f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const void * const mThreadId; 120f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons int mExitLine; 121f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons}; 122f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 123f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 124f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 125f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 126f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#ifdef TI_UTILS_FUNCTION_LOGGER_ENABLE 127f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define LOG_FUNCTION_NAME Ti::FunctionLogger __function_logger_instance(__FILE__, __LINE__, __FUNCTION__); 128f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define LOG_FUNCTION_NAME_EXIT __function_logger_instance.setExitLine(__LINE__); 129f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#else 130f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define LOG_FUNCTION_NAME int __function_logger_instance; 131f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define LOG_FUNCTION_NAME_EXIT (void*)__function_logger_instance; 132f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#endif 133f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 134f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#ifdef TI_UTILS_DEBUG_USE_TIMESTAMPS 135f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // truncate timestamp to 1000 seconds to fit into 6 characters 136f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define TI_UTILS_DEBUG_TIMESTAMP_TOKEN "[%06d] " 137f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define TI_UTILS_DEBUG_TIMESTAMP_VARIABLE static_cast<int>(nanoseconds_to_milliseconds(systemTime()) % 1000000), 138f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#else 139f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define TI_UTILS_DEBUG_TIMESTAMP_TOKEN 140f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons# define TI_UTILS_DEBUG_TIMESTAMP_VARIABLE 141f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#endif 142f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 143f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 144f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 145f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 146f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGV_FULL(priority, file, line, function, format, ...) \ 147f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons do \ 148f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 149f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons Ti::Debug * const debug = Ti::Debug::instance(); \ 150f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons debug->log(priority, format, \ 151f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_VARIABLE \ 152f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons reinterpret_cast<int>(androidGetThreadId()), \ 153f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons Ti::IndentString<>(debug->offsetForCurrentThread()).string(), \ 154f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons file, line, function, __VA_ARGS__); \ 155f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } while (0) 156f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 157f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGV(...) DBGUTILS_LOGV_FULL(ANDROID_LOG_VERBOSE, __FILE__, __LINE__, __FUNCTION__, TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - " __VA_ARGS__, "") 158f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGD(...) DBGUTILS_LOGV_FULL(ANDROID_LOG_DEBUG, __FILE__, __LINE__, __FUNCTION__, TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - " __VA_ARGS__, "") 159f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGI(...) DBGUTILS_LOGV_FULL(ANDROID_LOG_INFO, __FILE__, __LINE__, __FUNCTION__, TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - " __VA_ARGS__, "") 160f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGW(...) DBGUTILS_LOGV_FULL(ANDROID_LOG_WARN, __FILE__, __LINE__, __FUNCTION__, TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - " __VA_ARGS__, "") 161f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGE(...) DBGUTILS_LOGV_FULL(ANDROID_LOG_ERROR, __FILE__, __LINE__, __FUNCTION__, TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - " __VA_ARGS__, "") 162f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGF(...) DBGUTILS_LOGV_FULL(ANDROID_LOG_FATAL, __FILE__, __LINE__, __FUNCTION__, TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - " __VA_ARGS__, "") 163f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 164f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGVA DBGUTILS_LOGV 165f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGVB DBGUTILS_LOGV 166f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 167f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGDA DBGUTILS_LOGD 168f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGDB DBGUTILS_LOGD 169f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 170f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGEA DBGUTILS_LOGE 171f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_LOGEB DBGUTILS_LOGE 172f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 173f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons// asserts 174f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define _DBGUTILS_PLAIN_ASSERT(condition) \ 175f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons do \ 176f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 177f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( !(condition) ) \ 178f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 179f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons __android_log_print(ANDROID_LOG_FATAL, "Ti::Debug", \ 180f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons "Condition failed: " #condition); \ 181f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons __android_log_print(ANDROID_LOG_FATAL, "Ti::Debug", \ 182f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons "Aborting process..."); \ 183f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons abort(); \ 184f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } \ 185f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } while (0) 186f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 187f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define _DBGUTILS_PLAIN_ASSERT_X(condition, ...) \ 188f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons do \ 189f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 190f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( !(condition) ) \ 191f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 192f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons __android_log_print(ANDROID_LOG_FATAL, "Ti::Debug", \ 193f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons "Condition failed: " #condition ": " __VA_ARGS__); \ 194f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons __android_log_print(ANDROID_LOG_FATAL, "Ti::Debug", \ 195f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons "Aborting process..."); \ 196f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons abort(); \ 197f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } \ 198f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } while (0) 199f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 200f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_ASSERT(condition) \ 201f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons do \ 202f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 203f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( !(condition) ) \ 204f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 205f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons DBGUTILS_LOGF("Condition failed: " #condition); \ 206f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons DBGUTILS_LOGF("Aborting process..."); \ 207f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons abort(); \ 208f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } \ 209f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } while (0) 210c322989ae6ff6769490828de1b5eda12b749cce9Iliyan Malchev 211f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#define DBGUTILS_ASSERT_X(condition, ...) \ 212f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons do \ 213f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 214f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( !(condition) ) \ 215f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { \ 216f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons DBGUTILS_LOGF("Condition failed: " #condition ": " __VA_ARGS__); \ 217f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons DBGUTILS_LOGF("Aborting process..."); \ 218f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons abort(); \ 219f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } \ 220f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } while (0) 221f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 222f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 223f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 224f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 225f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsstatic const int kIndentStringMaxLength = 128; 226f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 227f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonstemplate <int Size> 228f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline int IndentString<Size>::calculateOffset(const int length) const 229f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 230f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const int offset = kIndentStringMaxLength - length*Size; 231f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return offset < 0 ? 0 : offset; 232f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 233f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 234f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonstemplate <int Size> 235f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline IndentString<Size>::IndentString(const int length) : 236f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mOffset(calculateOffset(length)) 237f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{} 238f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 239f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonstemplate <int Size> 240f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline const char * IndentString<Size>::string() const 241f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 242f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons extern const char sIndentStringBuffer[]; 243f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return sIndentStringBuffer + mOffset; 244f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 245f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 246f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 247f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 248f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 249f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline Debug * Debug::instance() 250f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ return &sInstance; } 251f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 252f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 253f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline Debug::ThreadInfo * Debug::findCurrentThreadInfo() 254f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 255f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // retain reference to threads data 256f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android::sp<Data> data = mData; 257f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 258f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // iterate over threads to locate thread id, 259f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // this is safe from race conditions because each thread 260f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // is able to modify only his own ThreadInfo structure 261f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const int32_t threadId = reinterpret_cast<int32_t>(androidGetThreadId()); 262f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons const int size = int(data->threads.size()); 263f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons for ( int i = 0; i < size; ++i ) 264f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { 265f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo * const threadInfo = data->threads.itemAt(i); 266f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( threadInfo->threadId == threadId ) 267f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return threadInfo; 268f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 269f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 270f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // this thread has not been registered yet, 271f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // try to fing empty thread info slot 272f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons while ( true ) 273f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { 274f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo * const threadInfo = registerThread(data.get(), threadId); 275f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( threadInfo ) 276f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return threadInfo; 277f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 278f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // failed registering thread, because all slots are occupied 279f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // grow the data and try again 280f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons grow(); 281f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 282f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons data = mData; 283f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 284f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 285f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // should never reach here 286f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons _DBGUTILS_PLAIN_ASSERT(false); 287f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return 0; 288f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 289f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 290f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 291f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline void Debug::addOffsetForCurrentThread(const int offset) 292f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 293f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( offset == 0 ) 294f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return; 295f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 296f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo * const threadInfo = findCurrentThreadInfo(); 297f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons _DBGUTILS_PLAIN_ASSERT(threadInfo); 298f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 299f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons threadInfo->callOffset += offset; 300f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 301f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( threadInfo->callOffset == 0 ) 302f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { 303f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons // thread call stack has dropped to zero, unregister it 304f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android_atomic_acquire_store(0, &threadInfo->threadId); 305f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 306f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 307f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 308f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 309f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline int Debug::offsetForCurrentThread() 310f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 311f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#ifdef TI_UTILS_FUNCTION_LOGGER_ENABLE 312f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons ThreadInfo * const threadInfo = findCurrentThreadInfo(); 313f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons _DBGUTILS_PLAIN_ASSERT(threadInfo); 314f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 315f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return threadInfo->callOffset; 316f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#else 317f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons return 0; 318f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#endif 319f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 320f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 321f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 322f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline void Debug::increaseOffsetForCurrentThread() 323f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 324f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#ifdef TI_UTILS_FUNCTION_LOGGER_ENABLE 325f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons addOffsetForCurrentThread(1); 326f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#endif 327f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 328f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 329f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 330f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline void Debug::decreaseOffsetForCurrentThread() 331f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 332f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#ifdef TI_UTILS_FUNCTION_LOGGER_ENABLE 333f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons addOffsetForCurrentThread(-1); 334f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#endif 335f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 336f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 337f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 338f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline void Debug::log(const int priority, const char * const format, ...) 339f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 340f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons va_list args; 341f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons va_start(args, format); 342f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons __android_log_vprint(priority, LOG_TAG, format, args); 343f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons va_end(args); 344f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 345f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 346f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 347f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 348f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 349f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline FunctionLogger::FunctionLogger(const char * const file, const int line, const char * const function) : 350f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mFile(file), mLine(line), mFunction(function), mThreadId(androidGetThreadId()), mExitLine(-1) 351f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 352f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons Debug * const debug = Debug::instance(); 353f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons debug->increaseOffsetForCurrentThread(); 354f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android_printLog(ANDROID_LOG_DEBUG, LOG_TAG, 355f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s+ %s:%d %s - ENTER", 356f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_VARIABLE 357f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons (int)mThreadId, IndentString<>(debug->offsetForCurrentThread()).string(), 358f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mFile, mLine, mFunction); 359f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 360f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 361f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 362f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline FunctionLogger::~FunctionLogger() 363f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 364f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons Debug * const debug = Debug::instance(); 365f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android_printLog(ANDROID_LOG_DEBUG, LOG_TAG, 366f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s- %s:%d %s - EXIT", 367f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_VARIABLE 368f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons (int)mThreadId, IndentString<>(debug->offsetForCurrentThread()).string(), 369f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mFile, mExitLine == -1 ? mLine : mExitLine, mFunction); 370f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons debug->decreaseOffsetForCurrentThread(); 371f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 372f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 373f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 374f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmonsinline void FunctionLogger::setExitLine(const int line) 375f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons{ 376f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons if ( mExitLine != -1 ) 377f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons { 378f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons Debug * const debug = Debug::instance(); 379f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons android_printLog(ANDROID_LOG_DEBUG, LOG_TAG, 380f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_TOKEN "(%x) %s %s:%d %s - Double function exit trace detected. Previous: %d", 381f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons TI_UTILS_DEBUG_TIMESTAMP_VARIABLE 382f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons (int)mThreadId, IndentString<>(debug->offsetForCurrentThread()).string(), 383f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mFile, line, mFunction, mExitLine); 384f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons } 385f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 386f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons mExitLine = line; 387f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} 388f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 389f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 390f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 391f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 392f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons} // namespace Ti 393f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 394f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 395f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 396f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons 397f7a4d11e9f710e2cd0592310ac1baecccb85f1d1Jason Simmons#endif //DEBUG_UTILS_H 398