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 : static 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 2 : spdk_notify_type_register(const char *type) 31 : { 32 2 : struct spdk_notify_type *it = NULL; 33 : 34 2 : if (!type) { 35 0 : SPDK_ERRLOG("Invalid notification type %p\n", type); 36 0 : return NULL; 37 2 : } 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 2 : pthread_mutex_lock(&g_events_lock); 43 3 : TAILQ_FOREACH(it, &g_notify_types, tailq) { 44 1 : if (strcmp(type, it->name) == 0) { 45 0 : SPDK_NOTICELOG("Notification type '%s' already registered.\n", type); 46 0 : goto out; 47 : } 48 1 : } 49 : 50 2 : it = calloc(1, sizeof(*it)); 51 2 : if (it == NULL) { 52 0 : goto out; 53 : } 54 : 55 2 : snprintf(it->name, sizeof(it->name), "%s", type); 56 2 : TAILQ_INSERT_TAIL(&g_notify_types, it, tailq); 57 : 58 : out: 59 2 : pthread_mutex_unlock(&g_events_lock); 60 2 : return it; 61 2 : } 62 : 63 : const char * 64 2 : spdk_notify_type_get_name(const struct spdk_notify_type *type) 65 : { 66 2 : return type->name; 67 : } 68 : 69 : 70 : void 71 0 : spdk_notify_foreach_type(spdk_notify_foreach_type_cb cb, void *ctx) 72 : { 73 : struct spdk_notify_type *it; 74 : 75 0 : pthread_mutex_lock(&g_events_lock); 76 0 : TAILQ_FOREACH(it, &g_notify_types, tailq) { 77 0 : if (cb(it, ctx)) { 78 0 : break; 79 : } 80 0 : } 81 0 : pthread_mutex_unlock(&g_events_lock); 82 0 : } 83 : 84 : uint64_t 85 2 : spdk_notify_send(const char *type, const char *ctx) 86 : { 87 : uint64_t head; 88 : struct spdk_notify_event *ev; 89 : 90 2 : pthread_mutex_lock(&g_events_lock); 91 2 : head = g_events_head; 92 2 : g_events_head++; 93 : 94 2 : ev = &g_events[head % SPDK_NOTIFY_MAX_EVENTS]; 95 2 : spdk_strcpy_pad(ev->type, type, sizeof(ev->type), '\0'); 96 2 : spdk_strcpy_pad(ev->ctx, ctx, sizeof(ev->ctx), '\0'); 97 2 : pthread_mutex_unlock(&g_events_lock); 98 : 99 2 : return head; 100 : } 101 : 102 : uint64_t 103 3 : 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 3 : pthread_mutex_lock(&g_events_lock); 109 : 110 3 : 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 0 : } 113 : 114 5 : for (i = 0; start_idx < g_events_head && i < max; start_idx++, i++) { 115 2 : if (cb_fn(start_idx, &g_events[start_idx % SPDK_NOTIFY_MAX_EVENTS], ctx)) { 116 0 : break; 117 : } 118 2 : } 119 3 : pthread_mutex_unlock(&g_events_lock); 120 : 121 3 : return i; 122 : }