Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright (C) 2020 Intel Corporation. 3 : : * All rights reserved. 4 : : */ 5 : : 6 : : #include "spdk/stdinc.h" 7 : : #include "spdk/env.h" 8 : : #include "spdk/log.h" 9 : : 10 : : struct sigbus_handler { 11 : : spdk_pci_error_handler func; 12 : : void *ctx; 13 : : 14 : : TAILQ_ENTRY(sigbus_handler) tailq; 15 : : }; 16 : : 17 : : static pthread_mutex_t g_sighandler_mutex = PTHREAD_MUTEX_INITIALIZER; 18 : : static TAILQ_HEAD(, sigbus_handler) g_sigbus_handler = 19 : : TAILQ_HEAD_INITIALIZER(g_sigbus_handler); 20 : : 21 : : static void 22 : 0 : sigbus_fault_sighandler(int signum, siginfo_t *info, void *ctx) 23 : : { 24 : : struct sigbus_handler *sigbus_handler; 25 : : 26 [ # # ]: 0 : pthread_mutex_lock(&g_sighandler_mutex); 27 [ # # ]: 0 : TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) { 28 : 0 : sigbus_handler->func(info->si_addr, sigbus_handler->ctx); 29 : : } 30 [ # # ]: 0 : pthread_mutex_unlock(&g_sighandler_mutex); 31 : 0 : } 32 : : 33 : : __attribute__((constructor)) static void 34 : 3180 : device_set_signal(void) 35 : : { 36 : 1334 : struct sigaction sa; 37 : : 38 : 3180 : sa.sa_sigaction = sigbus_fault_sighandler; 39 [ - + ]: 3180 : sigemptyset(&sa.sa_mask); 40 : 3180 : sa.sa_flags = SA_SIGINFO; 41 : 3180 : sigaction(SIGBUS, &sa, NULL); 42 : 3180 : } 43 : : 44 : : __attribute__((destructor)) static void 45 : 3182 : device_destroy_signal(void) 46 : : { 47 : : struct sigbus_handler *sigbus_handler, *tmp; 48 : : 49 [ + + ]: 3663 : TAILQ_FOREACH_SAFE(sigbus_handler, &g_sigbus_handler, tailq, tmp) { 50 : 481 : free(sigbus_handler); 51 : : } 52 : 3182 : } 53 : : 54 : : int 55 : 481 : spdk_pci_register_error_handler(spdk_pci_error_handler sighandler, void *ctx) 56 : : { 57 : : struct sigbus_handler *sigbus_handler; 58 : : 59 [ - + ]: 481 : if (!sighandler) { 60 : 0 : SPDK_ERRLOG("Error handler is NULL\n"); 61 : 0 : return -EINVAL; 62 : : } 63 : : 64 [ - + ]: 481 : pthread_mutex_lock(&g_sighandler_mutex); 65 [ - + ]: 481 : TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) { 66 [ # # ]: 0 : if (sigbus_handler->func == sighandler) { 67 [ # # ]: 0 : pthread_mutex_unlock(&g_sighandler_mutex); 68 : 0 : SPDK_ERRLOG("Error handler has been registered\n"); 69 : 0 : return -EINVAL; 70 : : } 71 : : } 72 [ - + ]: 481 : pthread_mutex_unlock(&g_sighandler_mutex); 73 : : 74 : 481 : sigbus_handler = calloc(1, sizeof(*sigbus_handler)); 75 [ - + ]: 481 : if (!sigbus_handler) { 76 : 0 : SPDK_ERRLOG("Failed to allocate sigbus handler\n"); 77 : 0 : return -ENOMEM; 78 : : } 79 : : 80 : 481 : sigbus_handler->func = sighandler; 81 : 481 : sigbus_handler->ctx = ctx; 82 : : 83 [ - + ]: 481 : pthread_mutex_lock(&g_sighandler_mutex); 84 : 481 : TAILQ_INSERT_TAIL(&g_sigbus_handler, sigbus_handler, tailq); 85 [ - + ]: 481 : pthread_mutex_unlock(&g_sighandler_mutex); 86 : : 87 : 481 : return 0; 88 : : } 89 : : 90 : : void 91 : 0 : spdk_pci_unregister_error_handler(spdk_pci_error_handler sighandler) 92 : : { 93 : : struct sigbus_handler *sigbus_handler; 94 : : 95 [ # # ]: 0 : if (!sighandler) { 96 : 0 : return; 97 : : } 98 : : 99 [ # # ]: 0 : pthread_mutex_lock(&g_sighandler_mutex); 100 [ # # ]: 0 : TAILQ_FOREACH(sigbus_handler, &g_sigbus_handler, tailq) { 101 [ # # ]: 0 : if (sigbus_handler->func == sighandler) { 102 [ # # ]: 0 : TAILQ_REMOVE(&g_sigbus_handler, sigbus_handler, tailq); 103 : 0 : free(sigbus_handler); 104 [ # # ]: 0 : pthread_mutex_unlock(&g_sighandler_mutex); 105 : 0 : return; 106 : : } 107 : : } 108 [ # # ]: 0 : pthread_mutex_unlock(&g_sighandler_mutex); 109 : : }