Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause 2 : : * Copyright (C) 2018 Intel Corporation. 3 : : * All rights reserved. 4 : : */ 5 : : 6 : : #include <sys/queue.h> 7 : : 8 : : #include "spdk/stdinc.h" 9 : : #include "spdk/util.h" 10 : : #include "spdk/queue.h" 11 : : #include "spdk/string.h" 12 : : #include "spdk/log.h" 13 : : 14 : : #include "spdk/notify.h" 15 : : 16 : : #define SPDK_NOTIFY_MAX_EVENTS 1024 17 : : 18 : : struct spdk_notify_type { 19 : : char name[SPDK_NOTIFY_MAX_NAME_SIZE]; 20 : : TAILQ_ENTRY(spdk_notify_type) tailq; 21 : : }; 22 : : 23 : : pthread_mutex_t g_events_lock = PTHREAD_MUTEX_INITIALIZER; 24 : : static struct spdk_notify_event g_events[SPDK_NOTIFY_MAX_EVENTS]; 25 : : static uint64_t g_events_head; 26 : : 27 : : static TAILQ_HEAD(, spdk_notify_type) g_notify_types = TAILQ_HEAD_INITIALIZER(g_notify_types); 28 : : 29 : : struct spdk_notify_type * 30 : 906 : spdk_notify_type_register(const char *type) 31 : : { 32 : 906 : struct spdk_notify_type *it = NULL; 33 : : 34 [ - + ]: 906 : if (!type) { 35 : 0 : SPDK_ERRLOG("Invalid notification type %p\n", type); 36 : 0 : return NULL; 37 [ + - - + ]: 906 : } else if (!type[0] || strlen(type) >= SPDK_NOTIFY_MAX_NAME_SIZE) { 38 : 0 : SPDK_ERRLOG("Notification type '%s' too short or too long\n", type); 39 : 0 : return NULL; 40 : : } 41 : : 42 : 906 : pthread_mutex_lock(&g_events_lock); 43 [ + + ]: 1359 : TAILQ_FOREACH(it, &g_notify_types, tailq) { 44 [ + + ]: 471 : if (strcmp(type, it->name) == 0) { 45 : 18 : SPDK_NOTICELOG("Notification type '%s' already registered.\n", type); 46 : 18 : goto out; 47 : : } 48 : : } 49 : : 50 : 888 : it = calloc(1, sizeof(*it)); 51 [ - + ]: 888 : if (it == NULL) { 52 : 0 : goto out; 53 : : } 54 : : 55 : 888 : snprintf(it->name, sizeof(it->name), "%s", type); 56 : 888 : TAILQ_INSERT_TAIL(&g_notify_types, it, tailq); 57 : : 58 : 906 : out: 59 : 906 : pthread_mutex_unlock(&g_events_lock); 60 : 906 : return it; 61 : : } 62 : : 63 : : const char * 64 : 8 : spdk_notify_type_get_name(const struct spdk_notify_type *type) 65 : : { 66 : 8 : return type->name; 67 : : } 68 : : 69 : : 70 : : void 71 : 2 : spdk_notify_foreach_type(spdk_notify_foreach_type_cb cb, void *ctx) 72 : : { 73 : : struct spdk_notify_type *it; 74 : : 75 : 2 : pthread_mutex_lock(&g_events_lock); 76 [ + + ]: 6 : TAILQ_FOREACH(it, &g_notify_types, tailq) { 77 [ - + ]: 4 : if (cb(it, ctx)) { 78 : 0 : break; 79 : : } 80 : : } 81 : 2 : pthread_mutex_unlock(&g_events_lock); 82 : 2 : } 83 : : 84 : : uint64_t 85 : 3850 : spdk_notify_send(const char *type, const char *ctx) 86 : : { 87 : : uint64_t head; 88 : : struct spdk_notify_event *ev; 89 : : 90 : 3850 : pthread_mutex_lock(&g_events_lock); 91 : 3850 : head = g_events_head; 92 : 3850 : g_events_head++; 93 : : 94 : 3850 : ev = &g_events[head % SPDK_NOTIFY_MAX_EVENTS]; 95 : 3850 : spdk_strcpy_pad(ev->type, type, sizeof(ev->type), '\0'); 96 : 3850 : spdk_strcpy_pad(ev->ctx, ctx, sizeof(ev->ctx), '\0'); 97 : 3850 : pthread_mutex_unlock(&g_events_lock); 98 : : 99 : 3850 : return head; 100 : : } 101 : : 102 : : uint64_t 103 : 10 : spdk_notify_foreach_event(uint64_t start_idx, uint64_t max, 104 : : spdk_notify_foreach_event_cb cb_fn, void *ctx) 105 : : { 106 : : uint64_t i; 107 : : 108 : 10 : pthread_mutex_lock(&g_events_lock); 109 : : 110 [ - + - - ]: 10 : if (g_events_head > SPDK_NOTIFY_MAX_EVENTS && start_idx < g_events_head - SPDK_NOTIFY_MAX_EVENTS) { 111 : 0 : start_idx = g_events_head - SPDK_NOTIFY_MAX_EVENTS; 112 : : } 113 : : 114 [ + + + + ]: 48 : for (i = 0; start_idx < g_events_head && i < max; start_idx++, i++) { 115 [ - + ]: 38 : if (cb_fn(start_idx, &g_events[start_idx % SPDK_NOTIFY_MAX_EVENTS], ctx)) { 116 : 0 : break; 117 : : } 118 : : } 119 : 10 : pthread_mutex_unlock(&g_events_lock); 120 : : 121 : 10 : return i; 122 : : }