openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

soc_log_buf.c (15606B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  * File: soc_log_buf.c
      7  * Purpose: Thread safe circular buffer for logs
      8  */
      9 
     10 #include <shared/bsl.h>
     11 
     12 #include <soc/soc_log_buf.h>
     13 #include <soc/debug.h>
     14 #include <soc/error.h>
     15 #include <sal/appl/sal.h>
     16 
     17 typedef struct _soc_log_buf_s {
     18     int first_entry;
     19     int last_entry;
     20     int buf_size;
     21     sal_mutex_t mutex;  
     22     int boot_count;
     23 } _soc_log_buf_t;
     24 
     25 typedef struct _soc_log_entry_hdr_s {
     26     int id;
     27     int size;
     28 } _soc_log_entry_hdr_t;
     29 
     30 sal_mutex_t
     31 soc_log_buf_get_mutex(void *location)
     32 {
     33     _soc_log_buf_t *buf = location;
     34     return buf->mutex;
     35 }
     36 
     37 int 
     38 soc_log_buf_set_mutex(void *location, sal_mutex_t mutex)
     39 {
     40     _soc_log_buf_t *buf = location;
     41     if (location == NULL) {
     42         return SOC_E_PARAM;
     43     }
     44     buf->mutex = mutex;
     45     return SOC_E_NONE;
     46 }
     47 
     48 STATIC int 
     49 _soc_log_buf_read(void *location, int offset, void *data, int size)
     50 {
     51     _soc_log_buf_t *buf_hdr = location;
     52     char *buf = (char*)location + sizeof(_soc_log_buf_t);
     53     int fixed_offset = offset % buf_hdr->buf_size;
     54     char *cur_log = buf + fixed_offset;
     55     int part_one = buf_hdr->buf_size - fixed_offset;
     56 
     57     if (part_one >= size) { /* There is no overrun */
     58         memcpy(data, cur_log, size);
     59     } else { /* The read must be broken into two parts */
     60         int part_two = size - part_one;
     61         char *cur_dst = data;
     62         memcpy(cur_dst, cur_log, part_one);
     63         cur_dst += part_one;
     64         cur_log = buf;
     65         memcpy(cur_dst, cur_log, part_two);
     66     }
     67 
     68     return SOC_E_NONE;
     69 }
     70 
     71 /* write from the buffer accouting for splits */
     72 STATIC int 
     73 _soc_log_buf_write(void *location, int offset, void *data, int size)
     74 {
     75     _soc_log_buf_t *buf_hdr = location;
     76     char *buf = (char*)location + sizeof(_soc_log_buf_t);
     77     int fixed_offset = offset % buf_hdr->buf_size;
     78     char *cur_log = buf + fixed_offset;
     79     int part_one = buf_hdr->buf_size - fixed_offset;
     80 
     81     if (part_one >= size) { /* There is no overrun */
     82         memcpy(cur_log, data, size);
     83     } else { /* The write must be split into two parts */
     84         int part_two = size - part_one;
     85         char *cur_dst = data;
     86         memcpy(cur_log, cur_dst, part_one);
     87         cur_dst += part_one;
     88         cur_log = buf;
     89         memcpy(cur_log, cur_dst, part_two);
     90     }
     91 
     92     return SOC_E_NONE;
     93 }
     94 
     95 STATIC int 
     96 _soc_log_buf_clear(void *location, int offset, int size)
     97 {
     98     _soc_log_buf_t *buf_hdr = location;
     99     char *buf = (char*)location + sizeof(_soc_log_buf_t);
    100     int fixed_offset = offset % buf_hdr->buf_size; /* Incase incoming offset is beyond buffer */
    101     char *cur_log = buf + fixed_offset;
    102     int part_one = buf_hdr->buf_size - fixed_offset;
    103 
    104     if (part_one >= size) { /* There is no overrun */
    105         sal_memset(cur_log, 0, size);
    106     } else { /* The write must be split into two parts */
    107         int part_two = size - part_one;
    108         sal_memset(cur_log, 0, part_one);
    109         cur_log = buf;
    110         sal_memset(cur_log, 0, part_two);
    111     }
    112 
    113     return SOC_E_NONE;
    114 }
    115 
    116 STATIC int 
    117 _soc_log_buf_entry_next(void *location, int offset)
    118 {
    119     _soc_log_entry_hdr_t hdr;
    120     _soc_log_buf_t *buf_hdr = location;
    121 
    122     _soc_log_buf_read(location, offset, &hdr, sizeof(_soc_log_entry_hdr_t));
    123     return (hdr.size + sizeof(_soc_log_entry_hdr_t) + offset) % buf_hdr->buf_size;
    124 }
    125 
    126 STATIC int 
    127 _soc_log_buf_entry_find(void *location, int id)
    128 {
    129     _soc_log_entry_hdr_t hdr;
    130     _soc_log_buf_t *buf_hdr = location;
    131     int cur_entry = buf_hdr->first_entry;
    132 
    133     while (1) {
    134         _soc_log_buf_read(location, cur_entry, &hdr, sizeof(_soc_log_entry_hdr_t));
    135         if (hdr.id == id) {
    136             return cur_entry;
    137         }
    138         if (cur_entry == buf_hdr->last_entry) {
    139             return SOC_E_NOT_FOUND;
    140         }
    141         cur_entry = _soc_log_buf_entry_next(location, cur_entry);
    142     }
    143 }
    144 
    145 int
    146 soc_log_buf_init(void *location, int size, sal_mutex_t mutex) 
    147 {
    148     _soc_log_buf_t *buf = location;
    149     _soc_log_entry_hdr_t *entry = (_soc_log_entry_hdr_t*)((char*)location + sizeof(_soc_log_buf_t));
    150 
    151     if (location == NULL) {
    152         return SOC_E_PARAM;
    153     }
    154 
    155     sal_mutex_take(mutex, sal_mutex_FOREVER);
    156 
    157     if (size <= (sizeof(_soc_log_buf_t) + sizeof(_soc_log_entry_hdr_t))) {
    158         sal_mutex_give(mutex);
    159         return SOC_E_PARAM;
    160     }
    161 
    162     buf->first_entry = 0;
    163     buf->last_entry = 0;
    164     buf->buf_size = size - sizeof(_soc_log_buf_t);
    165     buf->boot_count = 0;
    166     buf->mutex = mutex;
    167     
    168     entry->id = 0;
    169     entry->size = 0;
    170 
    171     sal_mutex_give(mutex);
    172 
    173     return SOC_E_NONE;
    174 }
    175 
    176 int
    177 soc_log_buf_add(void *location, int size)
    178 {
    179     _soc_log_buf_t *buf_hdr = location;
    180     _soc_log_entry_hdr_t temp_entry_header;
    181     int new_entry_location;
    182     int free_space;
    183     int amount_to_write = size + sizeof(_soc_log_entry_hdr_t);
    184     int new_id;
    185 
    186     if (location == NULL) {
    187         return SOC_E_PARAM;
    188     }
    189 
    190     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    191 
    192     if (amount_to_write > buf_hdr->buf_size) {
    193         sal_mutex_give(buf_hdr->mutex);
    194         return SOC_E_PARAM;
    195     }
    196 
    197     _soc_log_buf_read(location, buf_hdr->last_entry, &temp_entry_header,
    198         sizeof(_soc_log_entry_hdr_t));
    199 
    200     new_entry_location = _soc_log_buf_entry_next(location, buf_hdr->last_entry);
    201 
    202     if (new_entry_location > buf_hdr->first_entry) {
    203         free_space = buf_hdr->buf_size - 
    204             (new_entry_location - buf_hdr->first_entry);
    205     } else {
    206         free_space = buf_hdr->first_entry - new_entry_location;
    207     }
    208 
    209     while ((free_space < amount_to_write) && (free_space != 0)) {
    210         buf_hdr->first_entry =
    211             _soc_log_buf_entry_next(location, buf_hdr->first_entry);
    212 
    213         if (new_entry_location > buf_hdr->first_entry) {
    214             free_space = buf_hdr->buf_size -
    215                 (new_entry_location - buf_hdr->first_entry);
    216         } else {
    217             free_space = buf_hdr->first_entry - new_entry_location;
    218         }
    219     }
    220 
    221     temp_entry_header.size = size;
    222     temp_entry_header.id++;
    223     if (temp_entry_header.id == 0) { /* Zero is reserved */
    224         temp_entry_header.id++; 
    225     }
    226     new_id = temp_entry_header.id;
    227     _soc_log_buf_write(location, new_entry_location, 
    228         &temp_entry_header, sizeof(_soc_log_entry_hdr_t));
    229     buf_hdr->last_entry = new_entry_location;
    230     _soc_log_buf_clear(location, new_entry_location + 
    231         sizeof(_soc_log_entry_hdr_t), size); 
    232 
    233     sal_mutex_give(buf_hdr->mutex);
    234 
    235     return new_id;
    236 }
    237 
    238 int
    239 soc_log_buf_inc_boot_count(void *location)
    240 {
    241     _soc_log_buf_t *buf_hdr = location;
    242 
    243     if (location == NULL) {
    244         return SOC_E_PARAM;
    245     }
    246 
    247     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    248     buf_hdr->boot_count++;
    249     sal_mutex_give(buf_hdr->mutex);
    250 
    251     return SOC_E_NONE;
    252 }
    253 
    254 int 
    255 soc_log_buf_get_boot_count(void *location)
    256 {
    257     _soc_log_buf_t *buf_hdr = location;
    258     int boot_count;
    259 
    260     if (location == NULL) {
    261         return SOC_E_PARAM;
    262     }
    263 
    264     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    265     boot_count = buf_hdr->boot_count;
    266     sal_mutex_give(buf_hdr->mutex);
    267 
    268     return boot_count;
    269 }
    270 
    271 /* Get the size of an entries data */
    272 int
    273 soc_log_buf_entry_get_size(void *location, int id, int *size)
    274 {
    275     _soc_log_buf_t *buf_hdr = location;
    276     _soc_log_entry_hdr_t hdr;
    277     int entry_offset;
    278 
    279     if (location == NULL) {
    280         return SOC_E_PARAM;
    281     }
    282 
    283     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    284 
    285     entry_offset = _soc_log_buf_entry_find(location, id);
    286     if (entry_offset < 0) {
    287         sal_mutex_give(buf_hdr->mutex);
    288         return SOC_E_PARAM; /*invalid entry id */
    289     }
    290 
    291     _soc_log_buf_read(location, entry_offset, &hdr,
    292         sizeof(_soc_log_entry_hdr_t));
    293 
    294     sal_mutex_give(buf_hdr->mutex);
    295 
    296     *size = hdr.size;
    297 
    298     return SOC_E_NONE;
    299 }
    300 
    301 /* Copy a section of an entry to a buffer */
    302 int 
    303 soc_log_buf_entry_read(void *location,
    304                         int id, 
    305                         int offset, 
    306                         int size, 
    307                         void *data)
    308 {
    309     _soc_log_buf_t *buf_hdr = location;
    310     _soc_log_entry_hdr_t hdr;
    311     int entry_offset;
    312 
    313     if (location == NULL) {
    314         return SOC_E_PARAM;
    315     }
    316 
    317     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    318 
    319     entry_offset = _soc_log_buf_entry_find(location, id);
    320     if (entry_offset < 0) {
    321         sal_mutex_give(buf_hdr->mutex);
    322         return SOC_E_PARAM;
    323     }
    324 
    325     _soc_log_buf_read(location, entry_offset, &hdr,
    326         sizeof(_soc_log_entry_hdr_t));
    327 
    328     if ((offset + size) > hdr.size) { 
    329         sal_mutex_give(buf_hdr->mutex);
    330         return SOC_E_PARAM;
    331     }
    332 
    333     _soc_log_buf_read(location, 
    334         entry_offset + offset + sizeof(_soc_log_entry_hdr_t), data, size);
    335     
    336     sal_mutex_give(buf_hdr->mutex);
    337     return SOC_E_NONE;
    338 }
    339 
    340 /* write to a section of an entry */
    341 int 
    342 soc_log_buf_entry_write(void *location,
    343                         int id, 
    344                         int offset, 
    345                         int size, 
    346                         void *data)
    347 {
    348     _soc_log_entry_hdr_t hdr;
    349     _soc_log_buf_t *buf_hdr = location;
    350     int entry_offset;
    351 
    352     if (location == NULL) {
    353         return SOC_E_PARAM;
    354     }
    355 
    356     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    357 
    358     entry_offset = _soc_log_buf_entry_find(location, id);
    359     if (entry_offset < 0) {
    360         sal_mutex_give(buf_hdr->mutex);
    361         return SOC_E_PARAM;
    362     }
    363 
    364     _soc_log_buf_read(location, entry_offset, &hdr,
    365         sizeof(_soc_log_entry_hdr_t));
    366 
    367     if ((offset + size) > hdr.size) { 
    368         sal_mutex_give(buf_hdr->mutex);
    369         return SOC_E_PARAM;
    370     }
    371 
    372     _soc_log_buf_write(location,
    373         entry_offset + offset + sizeof(_soc_log_entry_hdr_t), data, size);
    374     
    375     sal_mutex_give(buf_hdr->mutex);
    376     return SOC_E_NONE;
    377 }
    378 
    379 int 
    380 soc_log_buf_entry_valid(void *location, int id)
    381 {
    382     _soc_log_entry_hdr_t hdr;
    383     _soc_log_buf_t *buf_hdr = location;
    384     int entry_offset;
    385 
    386     if (location == NULL) {
    387         return SOC_E_PARAM;
    388     }
    389 
    390     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    391 
    392     entry_offset = _soc_log_buf_entry_find(location, id);
    393     if (entry_offset < 0) {
    394         sal_mutex_give(buf_hdr->mutex);
    395         return SOC_E_PARAM; /*invalid entry id */
    396     }
    397 
    398     _soc_log_buf_read(location,
    399         entry_offset, &hdr, sizeof(_soc_log_entry_hdr_t));
    400     if ((hdr.size < 0) || (hdr.size > buf_hdr->buf_size)) {
    401         sal_mutex_give(buf_hdr->mutex);
    402         return SOC_E_INTERNAL;
    403     }
    404 
    405     sal_mutex_give(buf_hdr->mutex);
    406     return SOC_E_NONE;
    407 }
    408 
    409 STATIC int
    410 _soc_log_buf_print_hdr(void *location)
    411 {
    412     _soc_log_buf_t *buf_hdr = location;
    413 
    414     LOG_ERROR(BSL_LS_SOC_COMMON,
    415               (BSL_META("Log Buffer Header\n")));
    416     LOG_ERROR(BSL_LS_SOC_COMMON,
    417               (BSL_META("\tfirst_entry: %d\n"), buf_hdr->first_entry));
    418     LOG_ERROR(BSL_LS_SOC_COMMON,
    419               (BSL_META("\tlast_entry: %d\n"), buf_hdr->last_entry));
    420     LOG_ERROR(BSL_LS_SOC_COMMON,
    421               (BSL_META("\tbuf_size: %d\n"), buf_hdr->buf_size));
    422     LOG_ERROR(BSL_LS_SOC_COMMON,
    423               (BSL_META("\tmutex: %p\n"), (char*)(buf_hdr->mutex)));
    424     LOG_ERROR(BSL_LS_SOC_COMMON,
    425               (BSL_META("\tboot_count: %d\n"), buf_hdr->boot_count));
    426 
    427     return SOC_E_NONE;
    428 }
    429 
    430 #define _SOC_LOG_BUF_PRINT_BUFFER_SIZE 16
    431 STATIC int
    432 _soc_log_buf_print_entry(void *location, int offset)
    433 {
    434     _soc_log_entry_hdr_t hdr;
    435     int index;
    436     char temp_buf[_SOC_LOG_BUF_PRINT_BUFFER_SIZE];
    437 
    438     _soc_log_buf_read(location, offset, &hdr, sizeof(_soc_log_entry_hdr_t));
    439 
    440     LOG_ERROR(BSL_LS_SOC_COMMON,
    441               (BSL_META("Log Entry Header\n")));
    442     LOG_ERROR(BSL_LS_SOC_COMMON,
    443               (BSL_META("\toffset: %d\n"), offset));
    444     LOG_ERROR(BSL_LS_SOC_COMMON,
    445               (BSL_META("\tid: %d\n"), hdr.id));
    446     LOG_ERROR(BSL_LS_SOC_COMMON,
    447               (BSL_META("\tsize: %d\n"), hdr.size));
    448     LOG_ERROR(BSL_LS_SOC_COMMON,
    449               (BSL_META("\tdata: \n\t\t")));
    450 
    451     _soc_log_buf_read(location, 
    452         offset+sizeof(_soc_log_entry_hdr_t),
    453         &temp_buf, _SOC_LOG_BUF_PRINT_BUFFER_SIZE);
    454     for (index = 0; index < hdr.size; index++) {
    455         LOG_ERROR(BSL_LS_SOC_COMMON,
    456                   (BSL_META("%02x "),
    457                    temp_buf[index%_SOC_LOG_BUF_PRINT_BUFFER_SIZE]));
    458         if (((index+1)%_SOC_LOG_BUF_PRINT_BUFFER_SIZE) == 0) {
    459             LOG_ERROR(BSL_LS_SOC_COMMON,
    460                       (BSL_META("\n\t\t")));
    461             _soc_log_buf_read(location, 
    462                 offset+sizeof(_soc_log_entry_hdr_t) + index + 1, 
    463                 &temp_buf, 
    464                 _SOC_LOG_BUF_PRINT_BUFFER_SIZE);
    465         }
    466     }
    467     if ((index%_SOC_LOG_BUF_PRINT_BUFFER_SIZE) != 0) {
    468         LOG_ERROR(BSL_LS_SOC_COMMON,
    469                   (BSL_META("\n")));
    470     }
    471 
    472     return SOC_E_NONE;
    473 }
    474 
    475 int 
    476 soc_log_buf_print(void *location)
    477 {
    478     _soc_log_buf_t *buf_hdr = location;
    479     int offset;
    480     
    481     if (location == NULL) {
    482         return SOC_E_PARAM;
    483     }
    484 
    485     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    486 
    487     offset = buf_hdr->first_entry;
    488     _soc_log_buf_print_hdr(location);
    489     while (1) {
    490         _soc_log_buf_print_entry(location, offset);
    491         if (offset == buf_hdr->last_entry) {
    492             break;
    493         }
    494         offset = _soc_log_buf_entry_next(location, offset);
    495     }
    496 
    497     sal_mutex_give(buf_hdr->mutex);
    498 
    499     return SOC_E_NONE;
    500 }
    501 
    502 int 
    503 soc_log_buf_get_next_id(void *location, int id)
    504 {
    505     _soc_log_buf_t *buf_hdr = location;
    506     _soc_log_entry_hdr_t hdr;
    507     int offset = 0;
    508     
    509     if (location == NULL) {
    510         return 0;
    511     }
    512 
    513     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    514 
    515     if (id == 0) {
    516         _soc_log_buf_read(location, buf_hdr->first_entry, &hdr, sizeof(_soc_log_entry_hdr_t));
    517         if (hdr.id != 0) {
    518             sal_mutex_give(buf_hdr->mutex);
    519             return hdr.id;
    520         }
    521     }
    522 
    523     _soc_log_buf_read(location, buf_hdr->last_entry, &hdr, sizeof(_soc_log_entry_hdr_t));
    524     if (id == hdr.id) {
    525         sal_mutex_give(buf_hdr->mutex);
    526         return 0;
    527     }
    528 
    529     offset = _soc_log_buf_entry_find(location, id);
    530     offset = _soc_log_buf_entry_next(location, offset);
    531     _soc_log_buf_read(location, offset, &hdr, sizeof(_soc_log_entry_hdr_t));
    532     sal_mutex_give(buf_hdr->mutex);
    533     return hdr.id;
    534 }
    535 
    536 int
    537 soc_log_buf_search(void *location,
    538                    void *buffer,
    539                    int buf_size,
    540                    void *criteria, 
    541                    int (*match)(void * crit, void * entry))
    542 {
    543     _soc_log_entry_hdr_t hdr;
    544     _soc_log_buf_t *buf_hdr = location;
    545     int cur_entry;
    546 
    547     if (location == NULL) {
    548         return SOC_E_PARAM;
    549     }
    550 
    551     cur_entry = buf_hdr->first_entry;
    552 
    553     sal_mutex_take(buf_hdr->mutex, sal_mutex_FOREVER);
    554 
    555     while (1) {
    556         /* read the current header */
    557         _soc_log_buf_read(location, cur_entry, &hdr, sizeof(_soc_log_entry_hdr_t));
    558 
    559         if (hdr.size > buf_size) {
    560             sal_mutex_give(buf_hdr->mutex);
    561             return SOC_E_PARAM;
    562         }
    563 
    564         _soc_log_buf_read(location, cur_entry + sizeof(_soc_log_entry_hdr_t),
    565             buffer, hdr.size);
    566 
    567         /* if match returns true, we've found what we were looking for */
    568         if ((hdr.id != 0) && (match(criteria, buffer))) {
    569             sal_mutex_give(buf_hdr->mutex);
    570             return hdr.id;
    571         }
    572 
    573         if (cur_entry == buf_hdr->last_entry) {
    574             sal_mutex_give(buf_hdr->mutex);
    575             return SOC_E_NOT_FOUND;
    576         }
    577         cur_entry = _soc_log_buf_entry_next(location, cur_entry);
    578     }
    579 
    580     sal_mutex_give(buf_hdr->mutex);
    581 
    582     return SOC_E_NOT_FOUND;
    583 }
    584 
    585