thread.c (19177B)
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 * 7 * File: thread.c 8 * Purpose: Defines SAL routines for Unix threads 9 * 10 * Thread Abstraction 11 * 12 * POSIX does not keep thread names. The keep the names, we have a 13 * linked list of all threads we create. If your OS has the ability to 14 * retrieve the thread name, most of this code can be deleted. If you 15 * don't care about thread names, you may just have sal_thread_name 16 * always return the empty string. 17 * 18 * The most important use for thread names is in sal/appl/xxx/console.c, 19 * where the console output of background tasks can be prefixed by the 20 * task name. 21 */ 22 23 #include <pthread.h> 24 #include <sys/types.h> 25 #include <sys/time.h> 26 #include <sys/param.h> 27 #include <sys/prctl.h> 28 #include <sys/syscall.h> 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <signal.h> 32 #include <string.h> 33 #include <unistd.h> 34 35 #include <assert.h> 36 #include <sal/core/thread.h> 37 #include <sal/core/sync.h> 38 #include <sal/core/time.h> 39 #include <sal/core/spl.h> 40 #include <sal/limits.h> 41 42 #if defined (__STRICT_ANSI__) 43 #define NO_CONTROL_C 44 #endif 45 46 #ifndef SAL_THREAD_RT_PRIO_HIGHEST 47 #define SAL_THREAD_RT_PRIO_HIGHEST 90 48 #endif 49 50 static pthread_mutex_t _sal_thread_lock = PTHREAD_MUTEX_INITIALIZER; 51 52 #define THREAD_LOCK() pthread_mutex_lock(&_sal_thread_lock) 53 #define THREAD_UNLOCK() pthread_mutex_unlock(&_sal_thread_lock) 54 55 #if defined(BROADCOM_DEBUG) && defined(INCLUDE_BCM_SAL_PROFILE) 56 static unsigned int _sal_thread_count_curr; 57 static unsigned int _sal_thread_count_max; 58 static unsigned int _sal_thread_stack_size_curr; 59 static unsigned int _sal_thread_stack_size_max; 60 #define SAL_THREAD_RESOURCE_USAGE_INCR(a_cnt, a_cnt_max, a_sz, \ 61 a_sz_max, n_ssize, ilock) \ 62 a_cnt++; \ 63 a_sz += (n_ssize); \ 64 a_cnt_max = ((a_cnt) > (a_cnt_max)) ? (a_cnt) : (a_cnt_max); \ 65 a_sz_max = ((a_sz) > (a_sz_max)) ? (a_sz) : (a_sz_max) 66 67 #define SAL_THREAD_RESOURCE_USAGE_DECR(a_count, a_ssize, n_ssize, ilock)\ 68 a_count--; \ 69 a_ssize -= (n_ssize) 70 71 /* 72 * Function: 73 * sal_thread_resource_usage_get 74 * Purpose: 75 * Provides count of active threads and stack allocation 76 * Parameters: 77 * alloc_curr - Current memory usage. 78 * alloc_max - Memory usage high water mark 79 */ 80 81 void 82 sal_thread_resource_usage_get(unsigned int *sal_thread_count_curr, 83 unsigned int *sal_stack_size_curr, 84 unsigned int *sal_thread_count_max, 85 unsigned int *sal_stack_size_max) 86 { 87 if (sal_thread_count_curr != NULL) { 88 *sal_thread_count_curr = _sal_thread_count_curr; 89 } 90 if (sal_stack_size_curr != NULL) { 91 *sal_stack_size_curr = _sal_thread_stack_size_curr; 92 } 93 if (sal_thread_count_max != NULL) { 94 *sal_thread_count_max = _sal_thread_count_max; 95 } 96 if (sal_stack_size_max != NULL) { 97 *sal_stack_size_max = _sal_thread_stack_size_max; 98 } 99 } 100 101 #else 102 /* Resource tracking disabled */ 103 #define SAL_THREAD_RESOURCE_USAGE_INCR(a_cnt, a_cnt_max, a_sz, \ 104 a_sz_max, n_ssize, ilock) 105 #define SAL_THREAD_RESOURCE_USAGE_DECR(a_count, a_ssize, n_ssize, ilock) 106 #endif 107 108 /* If user defined min stack size in Make.local 109 * then undefine local stack min 110 * and set user defined value as the new min 111 */ 112 #ifdef SAL_THREAD_STACK_MIN 113 #ifdef PTHREAD_STACK_MIN 114 #undef PTHREAD_STACK_MIN 115 #endif 116 #define PTHREAD_STACK_MIN SAL_THREAD_STACK_MIN 117 #else 118 /* If no user defined min stack size 119 * and if no local stack min 120 * define local stack min 121 */ 122 #ifndef PTHREAD_STACK_MIN 123 #define PTHREAD_STACK_MIN 16384 124 #endif 125 #endif 126 127 /* 128 * Function: 129 * thread_boot 130 * Purpose: 131 * Entry point for each new thread created 132 * Parameters: 133 * ti - information about thread being created 134 * Notes: 135 * Signals and other parameters are configured before jumping to 136 * the actual thread's main routine. 137 */ 138 139 typedef struct thread_info_s { 140 void (*f)(void *); 141 char *name; 142 pthread_t id; 143 void *arg; 144 int ss; 145 sal_sem_t sem; 146 struct thread_info_s *next; 147 } thread_info_t; 148 149 static thread_info_t *thread_head = NULL; 150 151 static void * 152 thread_boot(void *ti_void) 153 { 154 155 thread_info_t *ti = ti_void; 156 void (*f)(void *); 157 void *arg; 158 #ifndef NO_CONTROL_C 159 sigset_t new_mask, orig_mask; 160 161 /* Make sure no child thread catches Control-C */ 162 sigemptyset(&new_mask); 163 sigaddset(&new_mask, SIGINT); 164 sigprocmask(SIG_BLOCK, &new_mask, &orig_mask); 165 #endif 166 167 /* Ensure that we give up all resources upon exit */ 168 pthread_detach(pthread_self()); 169 170 #ifdef PR_SET_NAME 171 prctl(PR_SET_NAME, ti->name, 0, 0, 0); 172 #endif 173 174 #ifndef netbsd 175 /* not supported */ 176 pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); 177 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); 178 #endif /* netbsd */ 179 180 f = ti->f; 181 arg = ti->arg; 182 183 ti->id = pthread_self(); 184 185 /* Notify parent to continue */ 186 sal_sem_give(ti->sem); 187 188 /* Call thread function */ 189 (*f)(arg); 190 191 /* Thread function did not call sal_thread_exit() */ 192 sal_thread_exit(0); 193 194 /* Will never get here */ 195 return NULL; 196 } 197 198 /* 199 * Function: 200 * sal_thread_create 201 * Purpose: 202 * Abstraction for task creation 203 * Parameters: 204 * name - name of task 205 * ss - stack size requested 206 * prio - scheduling prio (0 = highest, 255 = lowest) 207 * func - address of function to call 208 * arg - argument passed to func. 209 * Returns: 210 * Thread ID 211 */ 212 213 sal_thread_t 214 sal_thread_create(char *name, int ss, int prio, void (f)(void *), void *arg) 215 { 216 pthread_attr_t attribs; 217 struct sched_param param; 218 thread_info_t *ti; 219 pthread_t id; 220 sal_sem_t sem; 221 222 if (pthread_attr_init(&attribs)) { 223 return(SAL_THREAD_ERROR); 224 } 225 226 ss += PTHREAD_STACK_MIN; 227 pthread_attr_setstacksize(&attribs, ss); 228 229 if (prio == SAL_THREAD_PRIO_NO_PREEMPT) { 230 pthread_attr_setinheritsched(&attribs, PTHREAD_EXPLICIT_SCHED); 231 pthread_attr_setschedpolicy(&attribs, SCHED_FIFO); 232 param.sched_priority = SAL_THREAD_RT_PRIO_HIGHEST; 233 pthread_attr_setschedparam(&attribs, ¶m); 234 } 235 236 if ((ti = malloc(sizeof (*ti))) == NULL) { 237 return SAL_THREAD_ERROR; 238 } 239 240 if ((sem = sal_sem_create("threadBoot", 1, 0)) == NULL) { 241 free(ti); 242 return SAL_THREAD_ERROR; 243 } 244 ti->name = NULL; 245 if ((ti->name = malloc(strlen(name)+1)) == NULL) { 246 free(ti); 247 sal_sem_destroy(sem); 248 return SAL_THREAD_ERROR; 249 } 250 /* coverity[secure_coding] */ 251 strcpy(ti->name, name); 252 253 ti->f = f; 254 255 ti->arg = arg; 256 ti->id = (pthread_t)0; 257 ti->ss = ss; 258 ti->sem = sem; 259 260 THREAD_LOCK(); 261 ti->next = thread_head; 262 thread_head = ti; 263 THREAD_UNLOCK(); 264 265 if (pthread_create(&id, &attribs, thread_boot, (void *)ti)) { 266 THREAD_LOCK(); 267 thread_head = thread_head->next; 268 THREAD_UNLOCK(); 269 if (ti->name != NULL) { 270 free(ti->name); 271 } 272 free(ti); 273 sal_sem_destroy(sem); 274 return(SAL_THREAD_ERROR); 275 } 276 277 SAL_THREAD_RESOURCE_USAGE_INCR( 278 _sal_thread_count_curr, 279 _sal_thread_count_max, 280 _sal_thread_stack_size_curr, 281 _sal_thread_stack_size_max, 282 ss, 283 ilock); 284 285 /* 286 * Note that at this point ti can no longer be safely 287 * dereferenced, as the thread we just created may have 288 * exited already. Instead we wait for the new thread 289 * to update thread_info_t and tell us to continue. 290 */ 291 sal_sem_take(sem, sal_sem_FOREVER); 292 sal_sem_destroy(sem); 293 294 return ((sal_thread_t)id); 295 } 296 297 /* 298 * Function: 299 * sal_thread_destroy 300 * Purpose: 301 * Abstraction for task deletion 302 * Parameters: 303 * thread - thread ID 304 * Returns: 305 * 0 on success, -1 on failure 306 * Notes: 307 * This routine is not generally used by Broadcom drivers because 308 * it's unsafe. If a task is destroyed while holding a mutex or 309 * other resource, system operation becomes unpredictable. Also, 310 * some RTOS's do not include kill routines. 311 * 312 * Instead, Broadcom tasks are written so they can be notified via 313 * semaphore when it is time to exit, at which time they call 314 * sal_thread_exit(). 315 */ 316 317 int 318 sal_thread_destroy(sal_thread_t thread) 319 { 320 #ifdef netbsd 321 /* not supported */ 322 return -1; 323 #else 324 thread_info_t *ti, **tp; 325 pthread_t id = (pthread_t) thread; 326 327 if (pthread_cancel(id)) { 328 return -1; 329 } 330 331 ti = NULL; 332 333 THREAD_LOCK(); 334 for (tp = &thread_head; (*tp) != NULL; tp = &(*tp)->next) { 335 if ((*tp)->id == id) { 336 ti = (*tp); 337 (*tp) = (*tp)->next; 338 break; 339 } 340 } 341 THREAD_UNLOCK(); 342 343 if (ti) { 344 SAL_THREAD_RESOURCE_USAGE_DECR( 345 _sal_thread_count_curr, 346 _sal_thread_stack_size_curr, 347 ti->ss, 348 ilock); 349 if (ti->name != NULL) { 350 free(ti->name); 351 } 352 free(ti); 353 } 354 355 return 0; 356 #endif 357 } 358 359 /* 360 * Function: 361 * sal_thread_self 362 * Purpose: 363 * Return thread ID of caller 364 * Parameters: 365 * None 366 * Returns: 367 * Thread ID 368 */ 369 370 sal_thread_t 371 sal_thread_self(void) 372 { 373 return (sal_thread_t) pthread_self(); 374 } 375 376 int 377 sal_thread_id_get(void) 378 { 379 return syscall(SYS_gettid); 380 } 381 382 /* 383 * Function: 384 * sal_thread_name 385 * Purpose: 386 * Return name given to thread when it was created 387 * Parameters: 388 * thread - thread ID 389 * thread_name - buffer to return thread name; 390 * gets empty string if not available 391 * thread_name_size - maximum size of buffer 392 * Returns: 393 * NULL, if name not available 394 * thread_name, if name available 395 */ 396 char * 397 sal_thread_name(sal_thread_t thread, char *thread_name, int thread_name_size) 398 { 399 thread_info_t *ti; 400 char *name; 401 402 name = NULL; 403 404 THREAD_LOCK(); 405 for (ti = thread_head; ti != NULL; ti = ti->next) { 406 if (ti->id == (pthread_t)thread) { 407 strncpy(thread_name, ti->name, thread_name_size); 408 thread_name[thread_name_size - 1] = 0; 409 name = thread_name; 410 break; 411 } 412 } 413 THREAD_UNLOCK(); 414 415 if (name == NULL) { 416 thread_name[0] = 0; 417 } 418 419 return name; 420 } 421 422 /* 423 * Function: 424 * sal_thread_exit 425 * Purpose: 426 * Exit the calling thread 427 * Parameters: 428 * rc - return code from thread. 429 * Notes: 430 * Never returns. 431 */ 432 433 void 434 sal_thread_exit(int rc) 435 { 436 thread_info_t *ti, **tp; 437 pthread_t id = pthread_self(); 438 439 ti = NULL; 440 441 THREAD_LOCK(); 442 for (tp = &thread_head; (*tp) != NULL; tp = &(*tp)->next) { 443 if ((*tp)->id == id) { 444 ti = (*tp); 445 (*tp) = (*tp)->next; 446 break; 447 } 448 } 449 THREAD_UNLOCK(); 450 451 if (ti) { 452 SAL_THREAD_RESOURCE_USAGE_DECR( 453 _sal_thread_count_curr, 454 _sal_thread_stack_size_curr, 455 ti->ss, 456 ilock); 457 if (ti->name != NULL) { 458 free(ti->name); 459 } 460 free(ti); 461 } 462 463 pthread_exit(INT_TO_PTR(rc)); 464 } 465 466 /* 467 * Function: 468 * sal_thread_yield 469 * Purpose: 470 * Yield the processor to other tasks. 471 * Parameters: 472 * None 473 */ 474 475 void 476 sal_thread_yield(void) 477 { 478 sal_usleep(1); 479 } 480 481 /* 482 * Function: 483 * sal_thread_main_set 484 * Purpose: 485 * Set which thread is the main thread 486 * Parameters: 487 * thread - thread ID 488 * Notes: 489 * The main thread is the one that runs in the foreground on the 490 * console. It prints normally, takes keyboard signals, etc. 491 */ 492 493 static sal_thread_t _sal_thread_main = 0; 494 495 void 496 sal_thread_main_set(sal_thread_t thread) 497 { 498 _sal_thread_main = thread; 499 } 500 501 /* 502 * Function: 503 * sal_thread_main_get 504 * Purpose: 505 * Return which thread is the main thread 506 * Returns: 507 * Thread ID 508 * Notes: 509 * See sal_thread_main_set(). 510 */ 511 512 sal_thread_t 513 sal_thread_main_get(void) 514 { 515 return _sal_thread_main; 516 } 517 518 /* 519 * Function: 520 * sal_sleep 521 * Purpose: 522 * Suspend calling thread for a specified number of seconds. 523 * Parameters: 524 * sec - number of seconds to suspend 525 * Notes: 526 * Other tasks are free to run while the caller is suspended. 527 */ 528 529 void 530 sal_sleep(int sec) 531 { 532 struct timeval tv; 533 tv.tv_sec = (time_t) sec; 534 tv.tv_usec = 0; 535 select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv); 536 } 537 538 /* 539 * Function: 540 * sal_usleep 541 * Purpose: 542 * Suspend calling thread for a specified number of microseconds. 543 * Parameters: 544 * usec - number of microseconds to suspend 545 * Notes: 546 * The actual delay period depends on the resolution of the 547 * Unix select routine, whose precision is limited to the 548 * the period of the scheduler tick, generally 1/60 or 1/100 sec. 549 * Other tasks are free to run while the caller is suspended. 550 * 551 * A short usleep less than 20000 usec is done by doing a 'yield' 552 * within a loop, rather than a true 'sleep'. If no other tasks are 553 * using the CPU, this will effectively be a busy-wait, as the yield 554 * will immediately return. This can make it appear that the calling 555 * thread is using a lot of CPU, though this is only because no other 556 * task is in a running state. To avoid this appearance of 100% CPU 557 * load, the calling thread can increase the delay to 20000. 558 * The appearance of 100% CPU load for this thread should not have any 559 * effects on other threads. The thread that is spinning doing a 560 * sal_usleep() is continually calling an OS yield, so any other scheduled 561 * threads will run. The only time you will see this thread getting 100% 562 * CPU is if no other tasks are trying to run. 563 */ 564 565 void 566 sal_usleep(uint32 usec) 567 { 568 struct timeval tv; 569 570 if (usec < (2 * SECOND_USEC)/HZ) { 571 sal_usecs_t now; 572 sal_usecs_t earlier; 573 sal_usecs_t delta; 574 sal_usecs_t max_time = SAL_UINT32_MAX; 575 576 earlier = sal_time_usecs(); 577 do { 578 #if defined(_POSIX_PRIORITY_SCHEDULING) && (_POSIX_PRIORITY_SCHEDULING >= 200112L) 579 sched_yield(); 580 #else 581 tv.tv_sec = 0; 582 tv.tv_usec = 0; 583 select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv); 584 #endif 585 now = sal_time_usecs(); 586 if (now < earlier) { 587 delta = max_time - earlier + now; 588 } else { 589 delta = now - earlier; 590 } 591 } while (delta < usec); 592 } 593 else { 594 tv.tv_sec = (time_t) (usec / SECOND_USEC); 595 tv.tv_usec = (long) (usec % SECOND_USEC); 596 select(0, (fd_set *) 0, (fd_set *) 0, (fd_set *) 0, &tv); 597 } 598 } 599 600 #define UDELAY_USE_CLOCK_GETTIME (-1) 601 /* 602 * Function: 603 * sal_udelay 604 * Purpose: 605 * Spin wait for an approximate number of microseconds 606 * Parameters: 607 * usec - number of microseconds 608 * Notes: 609 * MUST be called once before normal use so it can self-calibrate. 610 * Code for self-calibrating delay loop is courtesy of 611 * Geoffrey Espin, the comp.os.vxworks Usenet group, and 612 * JA Borkhuis (http://www.xs4all.nl/~borkhuis). 613 * The current implementation assumes that sal_time_usecs has 614 * system tick resolution (or better). 615 */ 616 617 void 618 sal_udelay(uint32 usec) 619 { 620 static volatile int _sal_udelay_counter; 621 static int loops = 0; 622 uint32 iy; 623 int ix; 624 #ifdef CLOCK_MONOTONIC 625 int error; 626 struct timespec now, earlier; 627 long delta_usec, diff_nsec; 628 629 if (loops == 0) { 630 error = clock_getres(CLOCK_MONOTONIC, &now); 631 if (!error && !now.tv_sec && (now.tv_nsec <= 1000)) { 632 loops = UDELAY_USE_CLOCK_GETTIME; 633 } 634 } 635 636 if (loops == UDELAY_USE_CLOCK_GETTIME) { 637 error = clock_gettime(CLOCK_MONOTONIC, &earlier); 638 assert(!error); 639 do { 640 error = clock_gettime(CLOCK_MONOTONIC, &now); 641 assert(!error); 642 diff_nsec = now.tv_nsec - earlier.tv_nsec; 643 if (diff_nsec < 0) { 644 diff_nsec += 1000000000; 645 now.tv_sec--; 646 } 647 delta_usec = (now.tv_sec - earlier.tv_sec) * 1000000 + 648 (diff_nsec / 1000); 649 } while ((uint32)delta_usec < usec); 650 return; 651 } 652 #endif 653 if (loops == 0 || usec == 0) { /* Need calibration? */ 654 int max_loops; 655 int start = 0, stop = 0; 656 int mpt = (SECOND_USEC / HZ); /* usec/tick */ 657 658 for (loops = 1; loops < 0x1000 && stop == start; loops <<= 1) { 659 /* Wait for clock turn over */ 660 for (stop = start = sal_time_usecs() / mpt; 661 start == stop; 662 start = sal_time_usecs() / mpt) { 663 /* Empty */ 664 } 665 sal_udelay(mpt); /* Single recursion */ 666 stop = sal_time_usecs() / mpt; 667 } 668 669 max_loops = loops / 2; /* Loop above overshoots */ 670 671 start = stop = 0; 672 673 if (loops < 4) { 674 loops = 4; 675 } 676 677 for (loops /= 4; loops < max_loops && stop == start; loops++) { 678 /* Wait for clock turn over */ 679 for (stop = start = sal_time_usecs() / mpt; 680 start == stop; 681 start = sal_time_usecs() / mpt) { 682 /* Empty */ 683 } 684 sal_udelay(mpt); /* Single recursion */ 685 stop = sal_time_usecs() / mpt; 686 } 687 } 688 689 for (iy = 0; iy < usec; iy++) { 690 for (ix = 0; ix < loops; ix++) { 691 _sal_udelay_counter++; /* Prevent optimizations */ 692 } 693 } 694 } 695 696 #define MAX_TLS_KEY_SUPPORTED 8 697 698 typedef struct { 699 pthread_key_t key; 700 int mapped; 701 } pthread_key_map_t; 702 703 static pthread_key_map_t key_maps[MAX_TLS_KEY_SUPPORTED]; 704 static int sal_tls_inited = FALSE; 705 706 static void 707 sal_tls_init(void) 708 { 709 int i; 710 711 if (sal_tls_inited) { 712 return; 713 } 714 for (i = 0; i < MAX_TLS_KEY_SUPPORTED; i++) { 715 key_maps[i].mapped = FALSE; 716 } 717 sal_tls_inited = TRUE; 718 return; 719 } 720 721 sal_tls_key_t * 722 sal_tls_key_create(void (*destructor)(void *)) 723 { 724 int i; 725 int lvl; 726 727 lvl = sal_splhi(); 728 sal_tls_init(); 729 for (i = 0; i < MAX_TLS_KEY_SUPPORTED; i++) { 730 if (!key_maps[i].mapped) { 731 key_maps[i].mapped = TRUE; 732 break; 733 } 734 } 735 sal_spl(lvl); 736 737 if (i >= MAX_TLS_KEY_SUPPORTED) { 738 return NULL; 739 } 740 if (0 == pthread_key_create(&key_maps[i].key, destructor)) { 741 return (void *)&key_maps[i].key; 742 } else { 743 key_maps[i].mapped = FALSE; 744 return NULL; 745 } 746 } 747 748 int 749 sal_tls_key_set(sal_tls_key_t *key, void *val) 750 { 751 if (key == NULL) { 752 return FALSE; 753 } 754 755 if (!sal_tls_inited) { 756 return FALSE; 757 } 758 759 if (0 == pthread_setspecific(*(pthread_key_t *)key, val)) { 760 return TRUE; 761 } else { 762 return FALSE; 763 } 764 765 } 766 767 void * 768 sal_tls_key_get(sal_tls_key_t *key) 769 { 770 if (key == 0) { 771 return NULL; 772 } 773 if (!sal_tls_inited) { 774 return NULL; 775 } 776 return pthread_getspecific(*(pthread_key_t *)key); 777 } 778 779 int 780 sal_tls_key_delete(sal_tls_key_t *key) 781 { 782 if (key == 0) { 783 return FALSE; 784 } 785 if (!sal_tls_inited) { 786 return FALSE; 787 } 788 if (0 == pthread_key_delete(*(pthread_key_t *)key)) { 789 return TRUE; 790 } else { 791 return FALSE; 792 } 793 } 794