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