]> git.proxmox.com Git - mirror_kronosnet.git/blame - libknet/threads_common.c
[PMTUd] create common/shared code to trigger PMTUd rerun
[mirror_kronosnet.git] / libknet / threads_common.c
CommitLineData
3adbb389 1/*
a1bbd0e1 2 * Copyright (C) 2016-2019 Red Hat, Inc. All rights reserved.
3adbb389
FDN
3 *
4 * Authors: Fabio M. Di Nitto <fabbione@kronosnet.org>
5 * Federico Simoncelli <fsimon@kronosnet.org>
6 *
7 * This software licensed under GPL-2.0+, LGPL-2.0+
8 */
9
10#include "config.h"
11
12#include <pthread.h>
13#include <errno.h>
14#include <string.h>
15
16#include "internals.h"
17#include "logging.h"
18#include "threads_common.h"
19
20int shutdown_in_progress(knet_handle_t knet_h)
21{
22 int savederrno = 0;
23 int ret;
24
25 savederrno = pthread_rwlock_rdlock(&knet_h->global_rwlock);
26 if (savederrno) {
27 log_err(knet_h, KNET_SUB_COMMON, "Unable to get read lock: %s",
28 strerror(savederrno));
29 errno = savederrno;
30 return -1;
31 }
32
33 ret = knet_h->fini_in_progress;
34
35 pthread_rwlock_unlock(&knet_h->global_rwlock);
36
37 return ret;
38}
1dfc8220
FDN
39
40static int pmtud_reschedule(knet_handle_t knet_h)
41{
42 if (pthread_mutex_lock(&knet_h->pmtud_mutex) != 0) {
43 log_debug(knet_h, KNET_SUB_PMTUD, "Unable to get mutex lock");
44 return -1;
45 }
46
d2a6344f
FDN
47 if (knet_h->pmtud_running) {
48 knet_h->pmtud_abort = 1;
1dfc8220 49
d2a6344f
FDN
50 if (knet_h->pmtud_waiting) {
51 pthread_cond_signal(&knet_h->pmtud_cond);
52 }
1dfc8220
FDN
53 }
54
55 pthread_mutex_unlock(&knet_h->pmtud_mutex);
56 return 0;
57}
58
59int get_global_wrlock(knet_handle_t knet_h)
60{
61 if (pmtud_reschedule(knet_h) < 0) {
62 log_info(knet_h, KNET_SUB_PMTUD, "Unable to notify PMTUd to reschedule. Expect delays in executing API calls");
63 }
64 return pthread_rwlock_wrlock(&knet_h->global_rwlock);
65}
aed6b5db 66
6394d892 67static struct pretty_names thread_names[KNET_THREAD_MAX] =
3c77b62f
FDN
68{
69 { "TX", KNET_THREAD_TX },
70 { "RX", KNET_THREAD_RX },
71 { "HB", KNET_THREAD_HB },
72 { "PMTUD", KNET_THREAD_PMTUD },
73#ifdef HAVE_NETINET_SCTP_H
74 { "SCTP_LISTEN", KNET_THREAD_SCTP_LISTEN },
75 { "SCTP_CONN", KNET_THREAD_SCTP_CONN },
76#endif
77 { "DST_LINK", KNET_THREAD_DST_LINK }
78};
79
80static struct pretty_names thread_status[] =
81{
6394d892
FDN
82 { "unregistered", KNET_THREAD_UNREGISTERED },
83 { "registered", KNET_THREAD_REGISTERED },
84 { "started", KNET_THREAD_STARTED },
85 { "stopped", KNET_THREAD_STOPPED }
3c77b62f
FDN
86};
87
3c77b62f
FDN
88static const char *get_thread_status_name(uint8_t status)
89{
90 unsigned int i;
91
92 for (i = 0; i < KNET_THREAD_STATUS_MAX; i++) {
93 if (thread_status[i].val == status) {
94 return thread_status[i].name;
95 }
96 }
97 return "unknown";
98}
99
100static const char *get_thread_name(uint8_t thread_id)
101{
102 unsigned int i;
103
104 for (i = 0; i < KNET_THREAD_MAX; i++) {
105 if (thread_names[i].val == thread_id) {
106 return thread_names[i].name;
107 }
108 }
109 return "unknown";
110}
111
aed6b5db
FDN
112int set_thread_status(knet_handle_t knet_h, uint8_t thread_id, uint8_t status)
113{
114 if (pthread_mutex_lock(&knet_h->threads_status_mutex) != 0) {
115 log_debug(knet_h, KNET_SUB_HANDLE, "Unable to get mutex lock");
116 return -1;
117 }
118
119 knet_h->threads_status[thread_id] = status;
120
3c77b62f
FDN
121 log_debug(knet_h, KNET_SUB_HANDLE, "Updated status for thread %s to %s",
122 get_thread_name(thread_id), get_thread_status_name(status));
aed6b5db
FDN
123
124 pthread_mutex_unlock(&knet_h->threads_status_mutex);
125 return 0;
126}
127
128int wait_all_threads_status(knet_handle_t knet_h, uint8_t status)
129{
130 uint8_t i = 0, found = 0;
131
132 while (!found) {
133 usleep(KNET_THREADS_TIMERES);
134
135 if (pthread_mutex_lock(&knet_h->threads_status_mutex) != 0) {
136 continue;
137 }
138
139 found = 1;
140
141 for (i = 0; i < KNET_THREAD_MAX; i++) {
6394d892
FDN
142 if (knet_h->threads_status[i] == KNET_THREAD_UNREGISTERED) {
143 continue;
144 }
3c77b62f
FDN
145 log_debug(knet_h, KNET_SUB_HANDLE, "Checking thread: %s status: %s req: %s",
146 get_thread_name(i),
147 get_thread_status_name(knet_h->threads_status[i]),
148 get_thread_status_name(status));
aed6b5db
FDN
149 if (knet_h->threads_status[i] != status) {
150 found = 0;
151 }
152 }
153
154 pthread_mutex_unlock(&knet_h->threads_status_mutex);
155 }
156
157 return 0;
158}
5b02bef1
FDN
159
160void force_pmtud_run(knet_handle_t knet_h, uint8_t subsystem)
161{
162 /*
163 * we can only try to take a lock here. This part of the code
164 * can be invoked by any thread, including PMTUd that is already
165 * holding a lock at that stage.
166 * If PMTUd is holding the lock, most likely it is already running
167 * and we don't need to notify it back.
168 */
169 if (!pthread_mutex_trylock(&knet_h->pmtud_mutex)) {
170 if (!knet_h->pmtud_running) {
171 if (!knet_h->pmtud_forcerun) {
172 log_debug(knet_h, subsystem, "Notifying PMTUd to rerun");
173 knet_h->pmtud_forcerun = 1;
174 }
175 }
176 pthread_mutex_unlock(&knet_h->pmtud_mutex);
177 }
178}