Misc changes, fixing problems with long log strings
[tpg/acess2.git] / Kernel / logging.c
1 /*
2  * Acess 2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * logging.c - Kernel Logging Service
6  */
7 #include <acess.h>
8
9 #define PRINT_ON_APPEND 1
10 #define USE_RING_BUFFER 1
11 #define RING_BUFFER_SIZE        4096
12
13 // === CONSTANTS ===
14 enum eLogLevels
15 {
16         LOG_LEVEL_KPANIC,
17         LOG_LEVEL_PANIC,
18         LOG_LEVEL_FATAL,
19         LOG_LEVEL_ERROR,
20         LOG_LEVEL_WARNING,
21         LOG_LEVEL_NOTICE,
22         LOG_LEVEL_LOG,
23         LOG_LEVEL_DEBUG,
24         NUM_LOG_LEVELS
25 };
26 const char      *csaLevelColours[] = {
27                 "\x1B[35m", "\x1B[34m", "\x1B[36m", "\x1B[31m",
28                 "\x1B[33m", "\x1B[32m", "\x1B[0m", "\x1B[0m"
29                 };
30 const char      *csaLevelCodes[] =  {"k","p","f","e","w","n","l","d"};
31
32 // === TYPES ===
33 typedef struct sLogEntry
34 {
35         struct sLogEntry        *Next;
36         struct sLogEntry        *LevelNext;
37         Sint64  Time;
38          int    Level;
39          int    Length;
40         char    Ident[9];
41         char    Data[];
42 }       tLogEntry;
43 typedef struct sLogList
44 {
45         tLogEntry       *Head;
46         tLogEntry       *Tail;
47 }       tLogList;
48
49 // === PROTOTYPES ===
50 void    Log_AddEvent(const char *Ident, int Level, const char *Format, va_list Args);
51 static void     Log_Int_PrintMessage(tLogEntry *Entry);
52 //void  Log_KernelPanic(const char *Ident, const char *Message, ...);
53 //void  Log_Panic(const char *Ident, const char *Message, ...);
54 //void  Log_Error(const char *Ident, const char *Message, ...);
55 //void  Log_Warning(const char *Ident, const char *Message, ...);
56 //void  Log_Notice(const char *Ident, const char *Message, ...);
57 //void  Log_Log(const char *Ident, const char *Message, ...);
58 //void  Log_Debug(const char *Ident, const char *Message, ...);
59
60 // === EXPORTS ===
61 EXPORT(Log_Panic);
62 EXPORT(Log_Error);
63 EXPORT(Log_Warning);
64 EXPORT(Log_Notice);
65 EXPORT(Log_Log);
66 EXPORT(Log_Debug);
67
68 // === GLOBALS ===
69 tShortSpinlock  glLogOutput;
70 #if USE_RING_BUFFER
71 Uint8   gaLog_RingBufferData[sizeof(tRingBuffer)+RING_BUFFER_SIZE];
72 tRingBuffer     *gpLog_RingBuffer = (void*)gaLog_RingBufferData;
73 #else
74 tMutex  glLog;
75 tLogList        gLog;
76 tLogList        gLog_Levels[NUM_LOG_LEVELS];
77 #endif
78
79 // === CODE ===
80 /**
81  * \brief Adds an event to the log
82  */
83 void Log_AddEvent(const char *Ident, int Level, const char *Format, va_list Args)
84 {
85          int    len;
86         tLogEntry       *ent;
87         va_list args_tmp;
88         
89         if( Level >= NUM_LOG_LEVELS )   return;
90         
91         va_copy(args_tmp, Args);
92         len = vsnprintf(NULL, 256, Format, args_tmp);
93         
94         //Log("len = %i", len);
95         
96         #if USE_RING_BUFFER
97         {
98         char    buf[sizeof(tLogEntry)+len+1];
99         ent = (void*)buf;
100         #else
101         ent = malloc(sizeof(tLogEntry)+len+1);
102         #endif
103         ent->Time = now();
104         strncpy(ent->Ident, Ident, 8);
105         ent->Ident[8] = '\0';
106         ent->Level = Level;
107         ent->Length = len;
108         vsnprintf( ent->Data, len+1, Format, Args );
109         
110         #if USE_RING_BUFFER
111         {
112                 #define LOG_HDR_LEN     (14+1+2+8+2)
113                 char    newData[ LOG_HDR_LEN + len + 2 + 1 ];
114                 char    _ident[9];
115                 strncpy(_ident, Ident, 9);
116                 sprintf( newData, "%014lli%s [%+8s] ",
117                         ent->Time, csaLevelCodes[Level], Ident);
118                 strcpy( newData + LOG_HDR_LEN, ent->Data );
119                 strcpy( newData + LOG_HDR_LEN + len, "\r\n" );
120                 gpLog_RingBuffer->Space = RING_BUFFER_SIZE;     // Needed to init the buffer
121                 RingBuffer_Write( gpLog_RingBuffer, newData, LOG_HDR_LEN + len + 2 );
122         }
123         #else
124         Mutex_Acquire( &glLog );
125         
126         ent->Next = gLog.Tail;
127         if(gLog.Head)
128                 gLog.Tail = ent;
129         else
130                 gLog.Tail = gLog.Head = ent;
131         
132         ent->LevelNext = gLog_Levels[Level].Tail;
133         if(gLog_Levels[Level].Head)
134                 gLog_Levels[Level].Tail = ent;
135         else
136                 gLog_Levels[Level].Tail = gLog_Levels[Level].Head = ent;
137         
138         Mutex_Release( &glLog );
139         #endif
140         
141         #if PRINT_ON_APPEND
142         Log_Int_PrintMessage( ent );
143         #endif
144         
145         #if USE_RING_BUFFER
146         }
147         #endif
148 }
149
150 /**
151  * \brief Prints a log message to the debug console
152  */
153 void Log_Int_PrintMessage(tLogEntry *Entry)
154 {
155         SHORTLOCK( &glLogOutput );
156         LogF("%s%014lli%s [%+8s] %s",
157                 csaLevelColours[Entry->Level],
158                 Entry->Time,
159                 csaLevelCodes[Entry->Level],
160                 Entry->Ident,
161                 Entry->Data
162                 );
163         LogF("\x1B[0m\r\n");    // Separate in case Entry->Data is too long
164         SHORTREL( &glLogOutput );
165 }
166
167 /**
168  * \brief KERNEL PANIC!!!!
169  */
170 void Log_KernelPanic(const char *Ident, const char *Message, ...)
171 {
172         va_list args;   
173         va_start(args, Message);
174         Log_AddEvent(Ident, LOG_LEVEL_KPANIC, Message, args);
175         va_end(args);
176 }
177
178 /**
179  * \brief Panic Message - Driver Unrecoverable error
180  */
181 void Log_Panic(const char *Ident, const char *Message, ...)
182 {
183         va_list args;   
184         va_start(args, Message);
185         Log_AddEvent(Ident, LOG_LEVEL_PANIC, Message, args);
186         va_end(args);
187 }
188
189 /**
190  * \brief Error Message - Recoverable Error
191  */
192 void Log_Error(const char *Ident, const char *Message, ...)
193 {
194         va_list args;   
195         va_start(args, Message);
196         Log_AddEvent(Ident, LOG_LEVEL_ERROR, Message, args);
197         va_end(args);
198 }
199
200 /**
201  * \brief Warning Message - Something the user should know
202  */
203 void Log_Warning(const char *Ident, const char *Message, ...)
204 {
205         va_list args;
206         
207         va_start(args, Message);
208         Log_AddEvent(Ident, LOG_LEVEL_WARNING, Message, args);
209         va_end(args);
210 }
211
212 /**
213  * \brief Notice Message - Something the user might like to know
214  */
215 void Log_Notice(const char *Ident, const char *Message, ...)
216 {
217         va_list args;   
218         va_start(args, Message);
219         Log_AddEvent(Ident, LOG_LEVEL_NOTICE, Message, args);
220         va_end(args);
221 }
222
223 /**
224  * \brief Log Message - Possibly useful information
225  */
226 void Log_Log(const char *Ident, const char *Message, ...)
227 {
228         va_list args;   
229         va_start(args, Message);
230         Log_AddEvent(Ident, LOG_LEVEL_LOG, Message, args);
231         va_end(args);
232 }
233
234 /**
235  * \brief Debug Message - Only a developer would want this info
236  */
237 void Log_Debug(const char *Ident, const char *Message, ...)
238 {
239         va_list args;   
240         va_start(args, Message);
241         Log_AddEvent(Ident, LOG_LEVEL_DEBUG, Message, args);
242         va_end(args);
243 }

UCC git Repository :: git.ucc.asn.au