182 BufferIterator(varp, vartype, 0); |
182 BufferIterator(varp, vartype, 0); |
183 } |
183 } |
184 |
184 |
185 extern int TryEnterDebugSection(void); |
185 extern int TryEnterDebugSection(void); |
186 extern long AtomicCompareExchange(long*, long, long); |
186 extern long AtomicCompareExchange(long*, long, long); |
|
187 extern long long AtomicCompareExchange64(long long* , long long , long long); |
187 extern void LeaveDebugSection(void); |
188 extern void LeaveDebugSection(void); |
188 extern void ValidateRetainBuffer(void); |
189 extern void ValidateRetainBuffer(void); |
189 extern void InValidateRetainBuffer(void); |
190 extern void InValidateRetainBuffer(void); |
190 |
191 |
191 void __publish_debug(void) |
192 void __publish_debug(void) |
300 *buffer = debug_buffer; |
301 *buffer = debug_buffer; |
301 } |
302 } |
302 return wait_error; |
303 return wait_error; |
303 } |
304 } |
304 |
305 |
|
306 |
|
307 /* LOGGING |
|
308 */ |
|
309 |
|
310 #define LOG_LEVELS 4 |
|
311 #define LOG_CRITICAL 0 |
|
312 #define LOG_WARNING 1 |
|
313 #define LOG_INFO 2 |
|
314 #define LOG_DEBUG 3 |
|
315 |
|
316 #ifndef LOG_BUFFER_SIZE |
|
317 #define LOG_BUFFER_SIZE (1<<14) /*16Ko*/ |
|
318 #endif |
|
319 #define LOG_BUFFER_MASK (LOG_BUFFER_SIZE-1) |
|
320 static char LogBuff[LOG_LEVELS][LOG_BUFFER_SIZE]; |
|
321 void inline copy_to_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ |
|
322 if(buffpos + size < LOG_BUFFER_SIZE){ |
|
323 memcpy(&LogBuff[level][buffpos], buf, size); |
|
324 }else{ |
|
325 uint32_t remaining = LOG_BUFFER_SIZE - buffpos - 1; |
|
326 memcpy(&LogBuff[level][buffpos], buf, remaining); |
|
327 memcpy(LogBuff[level], buf + remaining, size - remaining); |
|
328 } |
|
329 } |
|
330 void inline copy_from_log(uint8_t level, uint32_t buffpos, void* buf, uint32_t size){ |
|
331 if(buffpos + size < LOG_BUFFER_SIZE){ |
|
332 memcpy(buf, &LogBuff[level][buffpos], size); |
|
333 }else{ |
|
334 uint32_t remaining = LOG_BUFFER_SIZE - buffpos; |
|
335 memcpy(buf, &LogBuff[level][buffpos], remaining); |
|
336 memcpy(buf + remaining, LogBuff[level], size - remaining); |
|
337 } |
|
338 } |
|
339 |
|
340 /* Log buffer structure |
|
341 |
|
342 |<-Tail1.msgsize->|<-sizeof(mTail)->|<--Tail2.msgsize-->|<-sizeof(mTail)->|... |
|
343 | Message1 Body | Tail1 | Message2 Body | Tail2 | |
|
344 |
|
345 */ |
|
346 typedef struct { |
|
347 uint32_t msgidx; |
|
348 uint32_t msgsize; |
|
349 unsigned long tick; |
|
350 IEC_TIME time; |
|
351 } mTail; |
|
352 |
|
353 /* Log cursor : 64b |
|
354 |63 ... 32|31 ... 0| |
|
355 | Message | Buffer | |
|
356 | counter | Index | */ |
|
357 static uint64_t LogCursor[LOG_LEVELS] = {0x0,0x0,0x0,0x0}; |
|
358 |
|
359 /* Store one log message of give size */ |
|
360 int LogMessage(uint8_t level, char* buf, uint32_t size){ |
|
361 if(size < LOG_BUFFER_SIZE - sizeof(mTail)){ |
|
362 uint32_t buffpos; |
|
363 uint64_t new_cursor, old_cursor; |
|
364 |
|
365 mTail tail; |
|
366 tail.msgsize = size; |
|
367 tail.tick = __tick; |
|
368 PLC_GetTime(&tail.time); |
|
369 |
|
370 /* We cannot increment both msg index and string pointer |
|
371 in a single atomic operation but we can detect having been interrupted. |
|
372 So we can try with atomic compare and swap in a loop until operation |
|
373 succeeds non interrupted */ |
|
374 do{ |
|
375 old_cursor = LogCursor[level]; |
|
376 buffpos = (uint32_t)old_cursor; |
|
377 tail.msgidx = (old_cursor >> 32); |
|
378 new_cursor = ((uint64_t)(tail.msgidx + 1)<<32) |
|
379 | (uint64_t)((buffpos + size + sizeof(mTail)) & LOG_BUFFER_MASK); |
|
380 }while(AtomicCompareExchange64( |
|
381 (long long*)&LogCursor[level], |
|
382 (long long)old_cursor, |
|
383 (long long)new_cursor)!=old_cursor); |
|
384 |
|
385 copy_to_log(level, buffpos, buf, size); |
|
386 copy_to_log(level, (buffpos + size) & LOG_BUFFER_MASK, &tail, sizeof(mTail)); |
|
387 |
|
388 return 1; /* Success */ |
|
389 }else{ |
|
390 char mstr[] = "Logging error : message too big"; |
|
391 LogMessage(LOG_CRITICAL, mstr, sizeof(mstr)); |
|
392 } |
|
393 return 0; |
|
394 } |
|
395 |
|
396 uint32_t GetLogCount(uint8_t level){ |
|
397 return (uint64_t)LogCursor[level] >> 32; |
|
398 } |
|
399 |
|
400 /* Return message size and content */ |
|
401 uint32_t GetLogMessage(uint8_t level, uint32_t msgidx, char* buf, uint32_t max_size, uint32_t* tick, uint32_t* tv_sec, uint32_t* tv_nsec){ |
|
402 uint64_t cursor = LogCursor[level]; |
|
403 if(cursor){ |
|
404 /* seach cursor */ |
|
405 uint32_t stailpos = (uint32_t)cursor; |
|
406 uint32_t smsgidx; |
|
407 mTail tail; |
|
408 tail.msgidx = cursor >> 32; |
|
409 tail.msgsize = 0; |
|
410 |
|
411 /* Message search loop */ |
|
412 do { |
|
413 smsgidx = tail.msgidx; |
|
414 stailpos = (stailpos - sizeof(mTail) - tail.msgsize ) & LOG_BUFFER_MASK; |
|
415 copy_from_log(level, stailpos, &tail, sizeof(mTail)); |
|
416 }while((tail.msgidx == smsgidx - 1) && (tail.msgidx > msgidx)); |
|
417 |
|
418 if(tail.msgidx == msgidx){ |
|
419 uint32_t sbuffpos = (stailpos - tail.msgsize ) & LOG_BUFFER_MASK; |
|
420 uint32_t totalsize = tail.msgsize; |
|
421 *tick = tail.tick; |
|
422 *tv_sec = tail.time.tv_sec; |
|
423 *tv_nsec = tail.time.tv_nsec; |
|
424 copy_from_log(level, sbuffpos, buf, |
|
425 totalsize > max_size ? max_size : totalsize); |
|
426 return totalsize; |
|
427 } |
|
428 } |
|
429 return 0; |
|
430 } |