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