diff options
Diffstat (limited to 'src/usr/trace')
-rw-r--r-- | src/usr/trace/daemon/daemon.C | 215 | ||||
-rw-r--r-- | src/usr/trace/daemon/daemon.H | 14 | ||||
-rw-r--r-- | src/usr/trace/daemonif.H | 22 | ||||
-rw-r--r-- | src/usr/trace/debug.C | 2 | ||||
-rw-r--r-- | src/usr/trace/debug.H | 18 | ||||
-rw-r--r-- | src/usr/trace/interface.C | 4 | ||||
-rw-r--r-- | src/usr/trace/service.C | 25 | ||||
-rw-r--r-- | src/usr/trace/service.H | 4 |
8 files changed, 281 insertions, 23 deletions
diff --git a/src/usr/trace/daemon/daemon.C b/src/usr/trace/daemon/daemon.C index 9f5a856fb..cbed7b262 100644 --- a/src/usr/trace/daemon/daemon.C +++ b/src/usr/trace/daemon/daemon.C @@ -29,6 +29,8 @@ #include "../compdesc.H" #include "../debug.H" +#include <errno.h> + #include <initservice/taskargs.H> #include <initservice/initserviceif.H> @@ -39,6 +41,8 @@ #include <targeting/common/commontargeting.H> #include <devicefw/userif.H> +#include <mbox/mboxif.H> + namespace TRACE { // Functions from DaemonIf that are only used by the daemon itself, @@ -76,6 +80,16 @@ namespace TRACEDAEMON iv_service = Service::getGlobalInstance(); iv_service->iv_daemon->start(); + // Register messages with mailbox daemon. + { + errlHndl_t l_errl = MBOX::msgq_register(MBOX::HB_TRACE_MSGQ, + iv_service->iv_daemon->iv_queue); + if (l_errl) + { + errlCommit(l_errl, HBTRACE_COMP_ID); + } + } + // Register shutdown events with init service. // Do one at the "beginning" and "end" of shutdown processesing. // The one at the beginning will flush out everything prior to @@ -109,6 +123,7 @@ namespace TRACEDAEMON pruneTraceEntries(); coalescePages(); + msg->data[0] = msg->data[1] = 0; break; } @@ -120,10 +135,94 @@ namespace TRACEDAEMON break; } + // Continuous trace state. + case DaemonIf::TRACE_CONT_TRACE_STATE: + { + if (msg->data[0] == 0) + { + g_debugSettings.contTraceOverride = + DebugSettings::CONT_TRACE_FORCE_DISABLE; + } + else if (msg->data[0] == 1) + { + g_debugSettings.contTraceOverride = + DebugSettings::CONT_TRACE_FORCE_ENABLE; + } + + msg->data[0] = msg->data[1] = 0; + break; + } + + // Reset trace buffers. + case DaemonIf::TRACE_RESET_BUFFERS: + { + // Collect current trace entries from client. + collectTracePages(); + + // Prune all trace entries. + pruneTraceEntries(true); + coalescePages(); + + msg->data[0] = msg->data[1] = 0; + break; + } + + // Enable / disable debug state. + case DaemonIf::TRACE_ENABLE_DEBUG: + case DaemonIf::TRACE_DISABLE_DEBUG: + { + bool enable = (msg->type == DaemonIf::TRACE_ENABLE_DEBUG); + + // An empty string indicates request to modify the global + // override setting. + if ('\0' == *reinterpret_cast<char*>(&msg->data[0])) + { + g_debugSettings.globalDebugEnable = enable; + msg->data[0] = msg->data[1] = 0; + } + // Otherwise, data0/1 are a 16-char array of the + // component name. extra_data gives us the '\0' + // terminator if the full 16 are needed. + else + { + ComponentDesc* iv_comp = + iv_service->iv_compList->getDescriptor( + reinterpret_cast<const char*>(&msg->data[0]), + 0); + + if (iv_comp == NULL) + { + msg->data[0] = EBADF; + msg->data[1] = 0; + } + else + { + iv_comp->iv_debugEnabled = enable; + msg->data[0] = msg->data[1] = 0; + } + } + break; + } + + case DaemonIf::TRACE_EXTRACT_BUFFERS: + { + // Collect current trace entries from client. + collectTracePages(); + + // Extract trace buffers. + extractTraceBuffer(); + + msg->data[0] = msg->data[1] = 0; + break; + } + default: { - assert(0); + // Since we can get messages from the FSP (of unknown + // quality), we don't want to assert here. Not really + // much we can do, so blindly ignore this condition. + msg->data[0] = EINVAL; break; } } @@ -240,6 +339,7 @@ namespace TRACEDAEMON if (NULL != contBuffer) { sendContBuffer(contBuffer, contBufferSize); + // contBuffer pointer is transfered to mailbox now. } contBuffer = reinterpret_cast<char*>(malloc(PAGESIZE)); @@ -283,6 +383,7 @@ namespace TRACEDAEMON if (contBufferSize > 1) { sendContBuffer(contBuffer, contBufferSize); + // contBuffer pointer is transfered to mailbox now. } else { @@ -330,9 +431,11 @@ namespace TRACEDAEMON // Determine if continuous trace is currently enabled. bool contEnabled = hbSettings.traceContinuous; - if (g_debugSettings.contTraceOverride != 0) + if (g_debugSettings.contTraceOverride != + DebugSettings::CONT_TRACE_USE_ATTR) { - contEnabled = (g_debugSettings.contTraceOverride == 2); + contEnabled = (g_debugSettings.contTraceOverride == + DebugSettings::CONT_TRACE_FORCE_ENABLE); } if (!contEnabled) @@ -344,8 +447,18 @@ namespace TRACEDAEMON { if (spFunctions.mailboxEnabled) { - // TODO: Send message to FSP. - free(i_buffer); + msg_t* msg = msg_allocate(); + msg->type = DaemonIf::TRACE_CONT_TRACE_BUFFER; + msg->data[1] = i_size; + msg->extra_data = i_buffer; + + errlHndl_t l_errl = MBOX::send(MBOX::FSP_TRACE_MSGQ, msg); + if (l_errl) + { + errlCommit(l_errl, HBTRACE_COMP_ID); + free(i_buffer); + msg_free(msg); + } } else { @@ -359,6 +472,28 @@ namespace TRACEDAEMON } } + void Daemon::sendExtractBuffer(void* i_buffer, size_t i_size) + { + // Send buffer message. + // We don't need to check for mailbox attributes or readiness + // because we should only be sending this message if we were + // requested to by the SP. + + msg_t* msg = msg_allocate(); + msg->type = DaemonIf::TRACE_BUFFER; + msg->data[1] = i_size; + msg->extra_data = i_buffer; + + errlHndl_t l_errl = MBOX::send(MBOX::FSP_TRACE_MSGQ, msg); + if (l_errl) + { + errlCommit(l_errl, HBTRACE_COMP_ID); + free(i_buffer); + msg_free(msg); + } + } + + void Daemon::replaceEntry(Entry* from, Entry* to) { do @@ -413,7 +548,7 @@ namespace TRACEDAEMON } while (1); } - void Daemon::pruneTraceEntries() + void Daemon::pruneTraceEntries(bool i_all) { ComponentList::List::iterator component; @@ -427,7 +562,10 @@ namespace TRACEDAEMON Entry* orig_entry = entry; // Invalidate entries until the component is small enough. - while((entry) && (component->iv_curSize > component->iv_maxSize)) + while((entry) && + ((component->iv_curSize > component->iv_maxSize) || + i_all) + ) { if (!reinterpret_cast<BufferPage*>( ALIGN_PAGE_DOWN( @@ -553,6 +691,69 @@ namespace TRACEDAEMON } + void Daemon::extractTraceBuffer() + { + char* curBuffer = NULL; + size_t curBufferSize = 0; + + for(BufferPage* page = iv_first; page != NULL; page = page->prev) + { + size_t offset = 0; + while (offset < page->usedSize) + { + Entry* entry = reinterpret_cast<Entry*>(&page->data[offset]); + + if (NULL != entry->comp) + { + // Calculate entry size. + size_t entryDataLength = + reinterpret_cast<trace_bin_entry_t*>(&entry->data[0]) + ->head.length + sizeof(trace_bin_entry_t); + + size_t entrySize = entry->comp->iv_compNameLen + + entryDataLength; + + // Allocate new page / send old page, if needed. + if ((NULL == curBuffer) || + ((curBufferSize + entrySize) >= PAGESIZE)) + { + if (NULL != curBuffer) + { + sendExtractBuffer(curBuffer, curBufferSize); + // curBuffer pointer is transfered to mailbox now. + } + + curBuffer = reinterpret_cast<char*>(malloc(PAGESIZE)); + memset(curBuffer, '\0', PAGESIZE); + curBuffer[0] = TRACE_BUF_CONT; + curBufferSize = 1; + } + + // Copy entry into buffer. + memcpy(&curBuffer[curBufferSize], + entry->comp->iv_compName, + entry->comp->iv_compNameLen); + curBufferSize += entry->comp->iv_compNameLen; + + memcpy(&curBuffer[curBufferSize], + &entry->data[0], + entryDataLength); + curBufferSize += entryDataLength; + } + + offset += entry->size + sizeof(Entry); + } + } + + // Send remaining buffer page to SP. + if (NULL != curBuffer) + { + sendExtractBuffer(curBuffer, curBufferSize); + // curBuffer pointer is transfered to mailbox now. + } + + } + void Daemon::writeScratchReg(uint64_t i_value) { size_t l_size = sizeof(uint64_t); diff --git a/src/usr/trace/daemon/daemon.H b/src/usr/trace/daemon/daemon.H index e6d2f5606..ad0028be4 100644 --- a/src/usr/trace/daemon/daemon.H +++ b/src/usr/trace/daemon/daemon.H @@ -74,12 +74,22 @@ namespace TRACEDAEMON /** Gather trace pages from client-side buffers. */ void collectTracePages(); - /** Send continuous trace buffer to SP. */ + /** Send continuous trace buffer to SP. + * + * Ownership of i_buffer is transfered to mailbox. + */ void sendContBuffer(void* i_buffer, size_t i_size); + /** Send extract trace buffer to SP. + * + * Ownership of i_buffer is transfered to mailbox. + */ + void sendExtractBuffer(void* i_buffer, size_t i_size); /** Reduce component trace buffers if exceeded max size. */ - void pruneTraceEntries(); + void pruneTraceEntries(bool i_all = false); /** Combine trace buffer pages to remove pruned entries. */ void coalescePages(); + /** Extract all trace buffers down to the SP. */ + void extractTraceBuffer(); /** Locklessly move a trace entry from one location to another. */ void replaceEntry(TRACE::Entry* from, TRACE::Entry* to); diff --git a/src/usr/trace/daemonif.H b/src/usr/trace/daemonif.H index 9e59fe58a..9b28f43e0 100644 --- a/src/usr/trace/daemonif.H +++ b/src/usr/trace/daemonif.H @@ -78,9 +78,27 @@ namespace TRACE enum MSG_TYPES { /** Client work is ready to be performed; flush buffers. */ - TRACE_DAEMON_SIGNAL = MBOX::FIRST_SECURE_MSG | 0, + TRACE_DAEMON_SIGNAL = MBOX::FIRST_UNSECURE_MSG | 0, + /** Flush continuous trace buffers. */ + TRACE_CONT_TRACE_FLUSH = TRACE_DAEMON_SIGNAL, /** Daemon should shutdown. */ - TRACE_DAEMON_SHUTDOWN = MBOX::FIRST_UNSECURE_MSG | 1, + TRACE_DAEMON_SHUTDOWN = MBOX::FIRST_SECURE_MSG | 1, + /** Modify continuous trace state. */ + TRACE_CONT_TRACE_STATE = MBOX::FIRST_UNSECURE_MSG | 2, + /** Reset trace buffers. */ + TRACE_RESET_BUFFERS = MBOX::FIRST_UNSECURE_MSG | 3, + /** Enable Debug state (TRACS mode). */ + TRACE_ENABLE_DEBUG = MBOX::FIRST_UNSECURE_MSG | 4, + /** Disable Debug state (TRACS mode). */ + TRACE_DISABLE_DEBUG = MBOX::FIRST_UNSECURE_MSG | 5, + /** Extract all buffers. */ + TRACE_EXTRACT_BUFFERS = MBOX::FIRST_UNSECURE_MSG | 6, + }; + + enum FSP_MSG_TYPES + { + TRACE_CONT_TRACE_BUFFER = 0, + TRACE_BUFFER = 1, }; // Since the below functions are only used by the daemon, they diff --git a/src/usr/trace/debug.C b/src/usr/trace/debug.C index cc1856918..542e6aa25 100644 --- a/src/usr/trace/debug.C +++ b/src/usr/trace/debug.C @@ -25,6 +25,6 @@ namespace TRACE { - DebugSettings g_debugSettings = { 0, 0, NULL }; + DebugSettings g_debugSettings = { 0, false, 0, NULL }; } diff --git a/src/usr/trace/debug.H b/src/usr/trace/debug.H index c9a14f91e..11ece2ee8 100644 --- a/src/usr/trace/debug.H +++ b/src/usr/trace/debug.H @@ -34,17 +34,25 @@ namespace TRACE */ struct DebugSettings { + enum + { + /** Use attribute (default). */ + CONT_TRACE_USE_ATTR = 0, + /** Force disable. */ + CONT_TRACE_FORCE_DISABLE = 1, + /** Force enable. */ + CONT_TRACE_FORCE_ENABLE = 2, + }; + // Continuous Trace: - /** Override of attribute setting. - * 0 - Use attribute (default). - * 1 - Force Disable - * 2 - Force Enable - */ uint8_t contTraceOverride; + /** Global switch for debug trace (TRACS). */ + bool globalDebugEnable; /** Size of continuous trace buffer. */ uint16_t bufferSize; /** Pointer to continuous trace buffer. */ void* bufferPage; + }; extern DebugSettings g_debugSettings; diff --git a/src/usr/trace/interface.C b/src/usr/trace/interface.C index 659179233..1b51bc1bb 100644 --- a/src/usr/trace/interface.C +++ b/src/usr/trace/interface.C @@ -71,7 +71,7 @@ namespace TRACE const trace_hash_val i_hash, const char * i_fmt, const uint32_t i_line, - const int32_t i_type, ...) + const uint32_t i_type, ...) { va_list args; va_start(args, i_type); @@ -87,7 +87,7 @@ namespace TRACE const uint32_t i_line, const void * i_ptr, const uint32_t i_size, - const int32_t i_type) + const uint32_t i_type) { Singleton<Service>::instance().writeBinEntry(io_td, i_hash, i_line, i_ptr, i_size, i_type); diff --git a/src/usr/trace/service.C b/src/usr/trace/service.C index 6c52efb18..15c69cb7a 100644 --- a/src/usr/trace/service.C +++ b/src/usr/trace/service.C @@ -25,6 +25,7 @@ #include "entry.H" #include "compdesc.H" #include "daemonif.H" +#include "debug.H" #include <sys/time.h> #include <sys/task.h> @@ -54,9 +55,19 @@ namespace TRACE trace_hash_val i_hash, const char * i_fmt, uint32_t i_line, - int32_t i_type, + uint32_t i_type, va_list i_args) { + // Skip writing trace if debug is disabled. + if (unlikely(i_type == TRACE_DEBUG)) + { + if ((!i_td->iv_debugEnabled) || + (!g_debugSettings.globalDebugEnable)) + { + return; + } + } + do { // Get the right buffer for this component. @@ -200,8 +211,18 @@ namespace TRACE uint32_t i_line, const void* i_ptr, uint32_t i_size, - int32_t i_type) + uint32_t i_type) { + // Skip writing trace if debug is disabled. + if (unlikely(i_type == TRACE_DEBUG)) + { + if ((!i_td->iv_debugEnabled) || + (!g_debugSettings.globalDebugEnable)) + { + return; + } + } + do { // Get the right buffer for this component. diff --git a/src/usr/trace/service.H b/src/usr/trace/service.H index 2a5218cab..1f81d9a2f 100644 --- a/src/usr/trace/service.H +++ b/src/usr/trace/service.H @@ -99,7 +99,7 @@ namespace TRACE trace_hash_val i_hash, const char * i_fmt, uint32_t i_line, - int32_t i_type, + uint32_t i_type, va_list i_args); /** @brief Write a binary entry to a trace buffer. @@ -117,7 +117,7 @@ namespace TRACE uint32_t i_line, const void* i_ptr, uint32_t i_size, - int32_t i_type); + uint32_t i_type); /** @brief Extract a component's trace buffer. * |