304 |
304 |
305 |
305 |
306 /* LOGGING |
306 /* LOGGING |
307 */ |
307 */ |
308 |
308 |
|
309 #define LOG_LEVELS 4 |
|
310 #define LOG_CRITICAL 0 |
|
311 #define LOG_WARNING 1 |
|
312 #define LOG_INFO 2 |
|
313 #define LOG_DEBUG 4 |
|
314 |
309 #define LOG_BUFFER_SIZE (1<<14) /*16Ko*/ |
315 #define LOG_BUFFER_SIZE (1<<14) /*16Ko*/ |
310 #define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1) |
316 #define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1) |
311 static char LogBuff[LOG_BUFFER_SIZE]; |
317 static char LogBuff[LOG_LEVELS][LOG_BUFFER_SIZE]; |
312 void inline copy_to_log(uint32_t buffpos, void* buf, uint32_t size){ |
318 void inline copy_to_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ |
313 if(buffpos + size < LOG_BUFFER_SIZE){ |
319 if(buffpos + size < LOG_BUFFER_SIZE){ |
314 memcpy(&LogBuff[buffpos], buf, size); |
320 memcpy(&LogBuff[level][buffpos], buf, size); |
315 }else{ |
321 }else{ |
316 uint32_t remaining = LOG_BUFFER_SIZE - buffpos - 1; |
322 uint32_t remaining = LOG_BUFFER_SIZE - buffpos - 1; |
317 memcpy(&LogBuff[buffpos], buf, remaining); |
323 memcpy(&LogBuff[level][buffpos], buf, remaining); |
318 memcpy(LogBuff, buf + remaining, size - remaining); |
324 memcpy(LogBuff[level], buf + remaining, size - remaining); |
319 } |
325 } |
320 } |
326 } |
321 void inline copy_from_log(uint32_t buffpos, void* buf, uint32_t size){ |
327 void inline copy_from_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ |
322 if(buffpos + size < LOG_BUFFER_SIZE){ |
328 if(buffpos + size < LOG_BUFFER_SIZE){ |
323 memcpy(buf, &LogBuff[buffpos], size); |
329 memcpy(buf, &LogBuff[level][buffpos], size); |
324 }else{ |
330 }else{ |
325 uint32_t remaining = LOG_BUFFER_SIZE - buffpos; |
331 uint32_t remaining = LOG_BUFFER_SIZE - buffpos; |
326 memcpy(buf, &LogBuff[buffpos], remaining); |
332 memcpy(buf, &LogBuff[level][buffpos], remaining); |
327 memcpy(buf + remaining, LogBuff, size - remaining); |
333 memcpy(buf + remaining, LogBuff[level], size - remaining); |
328 } |
334 } |
329 } |
335 } |
330 |
336 |
331 /* Log buffer structure |
337 /* Log buffer structure |
332 |
338 |
343 |
349 |
344 /* Log cursor : 64b |
350 /* Log cursor : 64b |
345 |63 ... 32|31 ... 0| |
351 |63 ... 32|31 ... 0| |
346 | Message | Buffer | |
352 | Message | Buffer | |
347 | counter | Index | */ |
353 | counter | Index | */ |
348 static uint64_t LogCursor = 0x0; |
354 static uint64_t LogCursor[LOG_LEVELS] = {0x0,0x0,0x0,0x0}; |
349 |
355 |
350 /* Store one log message of give size */ |
356 /* Store one log message of give size */ |
351 int LogMessage(char* buf, uint32_t size){ |
357 int LogMessage(uint8_t level, char* buf, uint32_t size){ |
352 if(size < LOG_BUFFER_SIZE - sizeof(mTail)){ |
358 if(size < LOG_BUFFER_SIZE - sizeof(mTail)){ |
353 uint32_t buffpos; |
359 uint32_t buffpos; |
354 mTail tail; |
360 mTail tail; |
355 /* We cannot increment both msg index and string pointer |
361 /* We cannot increment both msg index and string pointer |
356 in a single atomic operation but we can detect having been interrupted. |
362 in a single atomic operation but we can detect having been interrupted. |
357 So we can try with atomic compare and swap in a loop until operation |
363 So we can try with atomic compare and swap in a loop until operation |
358 succeeds non interrupted */ |
364 succeeds non interrupted */ |
359 uint64_t new_cursor, old_cursor; |
365 uint64_t new_cursor, old_cursor; |
360 do{ |
366 do{ |
361 old_cursor = LogCursor; |
367 old_cursor = LogCursor[level]; |
362 buffpos = (uint32_t)old_cursor; |
368 buffpos = (uint32_t)old_cursor; |
363 tail.msgidx = (old_cursor >> 32); |
369 tail.msgidx = (old_cursor >> 32); |
364 new_cursor = ((uint64_t)(tail.msgidx + 1)<<32) |
370 new_cursor = ((uint64_t)(tail.msgidx + 1)<<32) |
365 | (uint64_t)((buffpos + size + sizeof(mTail)) & LOG_BUFFER_MASK); |
371 | (uint64_t)((buffpos + size + sizeof(mTail)) & LOG_BUFFER_MASK); |
366 }while(!__sync_bool_compare_and_swap(&LogCursor,old_cursor,new_cursor)); |
372 }while(!__sync_bool_compare_and_swap(&LogCursor[level],old_cursor,new_cursor)); |
367 |
373 |
368 copy_to_log(buffpos, buf, size); |
374 copy_to_log(level, buffpos, buf, size); |
369 tail.msgsize = size; |
375 tail.msgsize = size; |
370 /*XXX tick*/ |
376 /*XXX tick*/ |
371 /*XXX RTC*/ |
377 /*XXX RTC*/ |
372 copy_to_log((buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); |
378 copy_to_log(level, (buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); |
373 |
379 |
374 return 1; /* Success */ |
380 return 1; /* Success */ |
375 }else{ |
381 }else{ |
376 char mstr[] = "Logging error : message too big"; |
382 char mstr[] = "Logging error : message too big"; |
377 LogMessage(mstr, sizeof(mstr)); |
383 LogMessage(LOG_CRITICAL, mstr, sizeof(mstr)); |
378 } |
384 } |
379 return 0; |
385 return 0; |
380 } |
386 } |
381 |
387 |
382 uint32_t GetLogCount(){ |
388 uint32_t GetLogCount(uint8_t level){ |
383 return (uint64_t)LogCursor >> 32; |
389 return (uint64_t)LogCursor[level] >> 32; |
384 } |
390 } |
385 |
391 |
386 /* Return message size and content */ |
392 /* Return message size and content */ |
387 uint32_t GetLogMessage(uint32_t msgidx, char* buf, uint32_t max_size){ |
393 uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size){ |
388 uint64_t cursor = LogCursor; |
394 uint64_t cursor = LogCursor[level]; |
389 if(cursor){ |
395 if(cursor){ |
390 /* seach cursor */ |
396 /* seach cursor */ |
391 uint32_t stailpos = (uint32_t)cursor; |
397 uint32_t stailpos = (uint32_t)cursor; |
392 uint32_t smsgidx; |
398 uint32_t smsgidx; |
393 mTail tail; |
399 mTail tail; |
396 |
402 |
397 /* Message search loop */ |
403 /* Message search loop */ |
398 do { |
404 do { |
399 smsgidx = tail.msgidx; |
405 smsgidx = tail.msgidx; |
400 stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK; |
406 stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK; |
401 copy_from_log(stailpos, &tail, sizeof(mTail)); |
407 copy_from_log(level, stailpos, &tail, sizeof(mTail)); |
402 }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx)); |
408 }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx)); |
403 |
409 |
404 if(tail.msgidx == msgidx){ |
410 if(tail.msgidx == msgidx){ |
405 uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; |
411 uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; |
406 uint32_t totalsize = tail.msgsize; /*sizeof(mTail);*/ |
412 uint32_t totalsize = tail.msgsize; /*sizeof(mTail);*/ |
407 copy_from_log(sbuffpos, buf, totalsize > max_size ? max_size : totalsize); |
413 copy_from_log(level, sbuffpos, buf, totalsize > max_size ? max_size : totalsize); |
408 return totalsize; |
414 return totalsize; |
409 } |
415 } |
410 } |
416 } |
411 return 0; |
417 return 0; |
412 } |
418 } |