From db21facb37a7c0d917e646a69a72f90a04d71e42 Mon Sep 17 00:00:00 2001 From: rusEfi Date: Sun, 16 Nov 2014 18:03:30 -0600 Subject: [PATCH] auto-sync --- firmware/console_util/datalogging.c | 71 +++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 18 deletions(-) diff --git a/firmware/console_util/datalogging.c b/firmware/console_util/datalogging.c index 59dcfe5daa..e9e6797bd6 100644 --- a/firmware/console_util/datalogging.c +++ b/firmware/console_util/datalogging.c @@ -46,16 +46,33 @@ // we use this magic constant to make sure it's not just a random non-zero int in memory #define MAGIC_LOGGING_FLAG 45234441 +typedef char log_buf_t[DL_OUTPUT_BUFFER]; + +/** + * we need to leave a byte for zero terminator, also two bytes for the \r\n in + * printWithLength, also couple of bytes just in case + */ +#define MAX_DL_CAPACITY (DL_OUTPUT_BUFFER - 5) + +static log_buf_t pendingBuffers0 CCM_OPTIONAL +; +static log_buf_t pendingBuffers1 +; + /** * This is the buffer into which all the data providers write */ -static char pendingBuffer[DL_OUTPUT_BUFFER] CCM_OPTIONAL -; +static char *accumulationBuffer; + +/** + * amount of data accumulated so far + */ +static uint32_t accumulatedSize; /** * We copy all the pending data into this buffer once we are ready to push it out */ -static char outputBuffer[DL_OUTPUT_BUFFER]; +static char * outputBuffer; static MemoryStream intermediateLoggingBuffer; static uint8_t intermediateLoggingBufferData[INTERMEDIATE_LOGGING_BUFFER_SIZE] CCM_OPTIONAL @@ -87,6 +104,9 @@ void append(Logging *logging, const char *text) { return; } strcpy(logging->linePointer, text); + /** + * And now we are pointing at the zero char at the end of the buffer again + */ logging->linePointer += extraLen; } @@ -313,6 +333,7 @@ void resetLogging(Logging *logging) { return; } logging->linePointer = buffer; + logging->linePointer[0] = 0; } /** @@ -363,25 +384,19 @@ void scheduleLogging(Logging *logging) { int newLength = efiStrlen(logging->buffer); bool alreadyLocked = lockOutputBuffer(); - // I hope this is fast enough to operate under sys lock - int curLength = efiStrlen(pendingBuffer); - if (curLength + newLength >= DL_OUTPUT_BUFFER) { + if (accumulatedSize + newLength >= MAX_DL_CAPACITY) { /** * if no one is consuming the data we have to drop it - * this happens in case of serial-over-USB, todo: find a better solution - * + * this happens in case of serial-over-USB, todo: find a better solution? */ -// strcpy(fatalMessage, "datalogging.c: output buffer overflow: "); -// strcat(fatalMessage, logging->name); -// fatal(fatalMessage); if (!alreadyLocked) { unlockOutputBuffer(); } resetLogging(logging); return; } - - strcat(pendingBuffer, logging->buffer); + strcpy(accumulationBuffer + accumulatedSize, logging->buffer); + accumulatedSize += newLength; if (!alreadyLocked) { unlockOutputBuffer(); } @@ -393,21 +408,41 @@ uint32_t remainingSize(Logging *logging) { } /** - * This method actually sends all the pending data to the communication layer + * This method actually sends all the pending data to the communication layer. + * This method is invoked by the main thread - that's the only thread which should be sending + * actual data to console in order to avoid concurrent access to serial hardware. */ void printPending(void) { lockOutputBuffer(); - // we cannot output under syslock, so another buffer - strcpy(outputBuffer, pendingBuffer); - pendingBuffer[0] = 0; // reset pending buffer + /** + * we cannot output under syslock, we simply rotate which buffer is which + */ + char *temp = outputBuffer; + + int expectedOutputSize = accumulatedSize; + outputBuffer = accumulationBuffer; + + accumulationBuffer = temp; + accumulatedSize = 0; + accumulationBuffer[0] = 0; + unlockOutputBuffer(); - if (efiStrlen(outputBuffer) > 0) { + int actualOutputBuffer = efiStrlen(outputBuffer); + efiAssertVoid(actualOutputBuffer == expectedOutputSize, "out constr"); + + if (actualOutputBuffer > 0) { printWithLength(outputBuffer); } } void initIntermediateLoggingBuffer(void) { + pendingBuffers0[0] = 0; + pendingBuffers1[0] = 0; + accumulationBuffer = pendingBuffers0; + outputBuffer = pendingBuffers1; + accumulatedSize = 0; + msObjectInit(&intermediateLoggingBuffer, intermediateLoggingBufferData, INTERMEDIATE_LOGGING_BUFFER_SIZE, 0); intermediateLoggingBufferInited = TRUE; }