* logging.c - Kernel Logging Service
*/
#include <acess.h>
+#include <adt.h>
+#define CACHE_MESSAGES 0
#define PRINT_ON_APPEND 1
+#define USE_RING_BUFFER 1
+#define RING_BUFFER_SIZE 4096
// === CONSTANTS ===
enum eLogLevels
LOG_LEVEL_DEBUG,
NUM_LOG_LEVELS
};
-const char *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"};
+const char *csaLevelColours[] = {
+ "\x1B[35m", "\x1B[34m", "\x1B[36m", "\x1B[31m",
+ "\x1B[33m", "\x1B[32m", "\x1B[0m", "\x1B[0m"
+ };
+const char *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"};
// === TYPES ===
typedef struct sLogEntry
struct sLogEntry *Next;
struct sLogEntry *LevelNext;
Sint64 Time;
- char Ident[8];
int Level;
int Length;
+ char Ident[9];
char Data[];
} tLogEntry;
typedef struct sLogList
} tLogList;
// === PROTOTYPES ===
-void Log_AddEvent(char *Ident, int Level, char *Format, va_list Args);
+void Log_AddEvent(const char *Ident, int Level, const char *Format, va_list Args);
static void Log_Int_PrintMessage(tLogEntry *Entry);
-void Log_KernelPanic(char *Ident, char *Message, ...);
-void Log_Panic(char *Ident, char *Message, ...);
-void Log_Error(char *Ident, char *Message, ...);
-void Log_Warning(char *Ident, char *Message, ...);
-void Log_Notice(char *Ident, char *Message, ...);
-void Log_Log(char *Ident, char *Message, ...);
-void Log_Debug(char *Ident, char *Message, ...);
-//static Uint64 Log_Int_GetIdent(const char *Str);
+//void Log_KernelPanic(const char *Ident, const char *Message, ...);
+//void Log_Panic(const char *Ident, const char *Message, ...);
+//void Log_Error(const char *Ident, const char *Message, ...);
+//void Log_Warning(const char *Ident, const char *Message, ...);
+//void Log_Notice(const char *Ident, const char *Message, ...);
+//void Log_Log(const char *Ident, const char *Message, ...);
+//void Log_Debug(const char *Ident, const char *Message, ...);
// === EXPORTS ===
-EXPORT(Log_KernelPanic);
EXPORT(Log_Panic);
EXPORT(Log_Error);
EXPORT(Log_Warning);
EXPORT(Log_Debug);
// === GLOBALS ===
-tSpinlock glLog;
+tShortSpinlock glLogOutput;
+#if USE_RING_BUFFER
+Uint8 gaLog_RingBufferData[sizeof(tRingBuffer)+RING_BUFFER_SIZE];
+tRingBuffer *gpLog_RingBuffer = (void*)gaLog_RingBufferData;
+#else
+tMutex glLog;
tLogList gLog;
tLogList gLog_Levels[NUM_LOG_LEVELS];
+#endif
// === CODE ===
/**
* \brief Adds an event to the log
*/
-void Log_AddEvent(char *Ident, int Level, char *Format, va_list Args)
+void Log_AddEvent(const char *Ident, int Level, const char *Format, va_list Args)
{
int len;
tLogEntry *ent;
+ va_list args_tmp;
if( Level >= NUM_LOG_LEVELS ) return;
- len = vsnprintf(NULL, 256, Format, Args);
+ va_copy(args_tmp, Args);
+ len = vsnprintf(NULL, 256, Format, args_tmp);
//Log("len = %i", len);
+ #if USE_RING_BUFFER || !CACHE_MESSAGES
+ {
+ char buf[sizeof(tLogEntry)+len+1];
+ ent = (void*)buf;
+ #else
ent = malloc(sizeof(tLogEntry)+len+1);
+ #endif
ent->Time = now();
- strncpy(ent->Ident, Ident, 7);
+ strncpy(ent->Ident, Ident, 8);
+ ent->Ident[8] = '\0';
ent->Level = Level;
ent->Length = len;
- vsnprintf( ent->Data, 256, Format, Args );
-
- //Log("ent->Ident = '%s'", ent->Ident);
- //Log("ent->Data = '%s'", ent->Data);
-
- LOCK( &glLog );
+ vsnprintf( ent->Data, len+1, Format, Args );
+
+ #if CACHE_MESSAGES
+ # if USE_RING_BUFFER
+ {
+ #define LOG_HDR_LEN (14+1+2+8+2)
+ char newData[ LOG_HDR_LEN + len + 2 + 1 ];
+ char _ident[9];
+ strncpy(_ident, Ident, 9);
+ sprintf( newData, "%014lli%s [%-8s] ",
+ ent->Time, csaLevelCodes[Level], Ident);
+ strcpy( newData + LOG_HDR_LEN, ent->Data );
+ strcpy( newData + LOG_HDR_LEN + len, "\r\n" );
+ gpLog_RingBuffer->Space = RING_BUFFER_SIZE; // Needed to init the buffer
+ RingBuffer_Write( gpLog_RingBuffer, newData, LOG_HDR_LEN + len + 2 );
+ }
+ # else
+ Mutex_Acquire( &glLog );
ent->Next = gLog.Tail;
if(gLog.Head)
else
gLog_Levels[Level].Tail = gLog_Levels[Level].Head = ent;
- RELEASE( &glLog );
+ Mutex_Release( &glLog );
+ # endif
+ #endif
- #if PRINT_ON_APPEND
+ #if PRINT_ON_APPEND || !CACHE_MESSAGES
Log_Int_PrintMessage( ent );
#endif
+ #if USE_RING_BUFFER || !CACHE_MESSAGES
+ }
+ #endif
}
/**
*/
void Log_Int_PrintMessage(tLogEntry *Entry)
{
- LogF("%018lli%s [%8s] %s\n",
+ SHORTLOCK( &glLogOutput );
+ LogF("%s%014lli%s [%-8s] %i - %s",
+ csaLevelColours[Entry->Level],
Entry->Time,
csaLevelCodes[Entry->Level],
Entry->Ident,
+ Threads_GetTID(),
Entry->Data
);
+ LogF("\x1B[0m\r\n"); // Separate in case Entry->Data is too long
+ SHORTREL( &glLogOutput );
}
/**
* \brief KERNEL PANIC!!!!
*/
-void Log_KernelPanic(char *Ident, char *Message, ...)
+void Log_KernelPanic(const char *Ident, const char *Message, ...)
{
va_list args;
va_start(args, Message);
Log_AddEvent(Ident, LOG_LEVEL_KPANIC, Message, args);
va_end(args);
+ Panic("Log_KernelPanic - %s", Ident);
}
/**
* \brief Panic Message - Driver Unrecoverable error
*/
-void Log_Panic(char *Ident, char *Message, ...)
+void Log_Panic(const char *Ident, const char *Message, ...)
{
va_list args;
va_start(args, Message);
/**
* \brief Error Message - Recoverable Error
*/
-void Log_Error(char *Ident, char *Message, ...)
+void Log_Error(const char *Ident, const char *Message, ...)
{
va_list args;
va_start(args, Message);
/**
* \brief Warning Message - Something the user should know
*/
-void Log_Warning(char *Ident, char *Message, ...)
+void Log_Warning(const char *Ident, const char *Message, ...)
{
va_list args;
/**
* \brief Notice Message - Something the user might like to know
*/
-void Log_Notice(char *Ident, char *Message, ...)
+void Log_Notice(const char *Ident, const char *Message, ...)
{
va_list args;
va_start(args, Message);
/**
* \brief Log Message - Possibly useful information
*/
-void Log_Log(char *Ident, char *Message, ...)
+void Log_Log(const char *Ident, const char *Message, ...)
{
va_list args;
va_start(args, Message);
/**
* \brief Debug Message - Only a developer would want this info
*/
-void Log_Debug(char *Ident, char *Message, ...)
+void Log_Debug(const char *Ident, const char *Message, ...)
{
va_list args;
va_start(args, Message);