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 0 : device_set_signal(void) 35 : { 36 0 : struct sigaction sa; 37 : 38 0 : sa.sa_sigaction = sigbus_fault_sighandler; 39 0 : sigemptyset(&sa.sa_mask); 40 0 : sa.sa_flags = SA_SIGINFO; 41 0 : sigaction(SIGBUS, &sa, NULL); 42 0 : } 43 : 44 : __attribute__((destructor)) static void 45 0 : device_destroy_signal(void) 46 : { 47 : struct sigbus_handler *sigbus_handler, *tmp; 48 : 49 0 : TAILQ_FOREACH_SAFE(sigbus_handler, &g_sigbus_handler, tailq, tmp) { 50 0 : free(sigbus_handler); 51 : } 52 0 : } 53 : 54 : int 55 0 : spdk_pci_register_error_handler(spdk_pci_error_handler sighandler, void *ctx) 56 : { 57 : struct sigbus_handler *sigbus_handler; 58 : 59 0 : if (!sighandler) { 60 0 : SPDK_ERRLOG("Error handler is NULL\n"); 61 0 : return -EINVAL; 62 : } 63 : 64 0 : pthread_mutex_lock(&g_sighandler_mutex); 65 0 : 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 0 : pthread_mutex_unlock(&g_sighandler_mutex); 73 : 74 0 : sigbus_handler = calloc(1, sizeof(*sigbus_handler)); 75 0 : if (!sigbus_handler) { 76 0 : SPDK_ERRLOG("Failed to allocate sigbus handler\n"); 77 0 : return -ENOMEM; 78 : } 79 : 80 0 : sigbus_handler->func = sighandler; 81 0 : sigbus_handler->ctx = ctx; 82 : 83 0 : pthread_mutex_lock(&g_sighandler_mutex); 84 0 : TAILQ_INSERT_TAIL(&g_sigbus_handler, sigbus_handler, tailq); 85 0 : pthread_mutex_unlock(&g_sighandler_mutex); 86 : 87 0 : 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 : }