Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (c) 2017 Cisco and/or its affiliates. |
| 3 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 | * you may not use this file except in compliance with the License. |
| 5 | * You may obtain a copy of the License at: |
| 6 | * |
| 7 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 8 | * |
| 9 | * Unless required by applicable law or agreed to in writing, software |
| 10 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 | * See the License for the specific language governing permissions and |
| 13 | * limitations under the License. |
| 14 | */ |
| 15 | |
| 16 | #include <vnet/session/segment_manager.h> |
| 17 | #include <vnet/session/session.h> |
| 18 | #include <vnet/session/application.h> |
| 19 | |
| 20 | /** |
| 21 | * Counter used to build segment names |
| 22 | */ |
| 23 | u32 segment_name_counter = 0; |
| 24 | |
| 25 | /** |
| 26 | * Pool of segment managers |
| 27 | */ |
| 28 | segment_manager_t *segment_managers = 0; |
| 29 | |
| 30 | /** |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 31 | * Process private segment index |
| 32 | */ |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 33 | u32 *private_segment_indices; |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 34 | |
| 35 | /** |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 36 | * Default fifo and segment size. TODO config. |
| 37 | */ |
| 38 | u32 default_fifo_size = 1 << 16; |
| 39 | u32 default_segment_size = 1 << 20; |
| 40 | |
| 41 | void |
| 42 | segment_manager_get_segment_info (u32 index, u8 ** name, u32 * size) |
| 43 | { |
| 44 | svm_fifo_segment_private_t *s; |
| 45 | s = svm_fifo_get_segment (index); |
| 46 | *name = s->h->segment_name; |
| 47 | *size = s->ssvm.ssvm_size; |
| 48 | } |
| 49 | |
| 50 | always_inline int |
| 51 | session_manager_add_segment_i (segment_manager_t * sm, u32 segment_size, |
| 52 | u8 * segment_name) |
| 53 | { |
| 54 | svm_fifo_segment_create_args_t _ca, *ca = &_ca; |
| 55 | int rv; |
| 56 | |
| 57 | memset (ca, 0, sizeof (*ca)); |
| 58 | |
| 59 | ca->segment_name = (char *) segment_name; |
| 60 | ca->segment_size = segment_size; |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 61 | ca->rx_fifo_size = sm->properties->rx_fifo_size; |
| 62 | ca->tx_fifo_size = sm->properties->tx_fifo_size; |
| 63 | ca->preallocated_fifo_pairs = sm->properties->preallocated_fifo_pairs; |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 64 | |
| 65 | rv = svm_fifo_segment_create (ca); |
| 66 | if (rv) |
| 67 | { |
| 68 | clib_warning ("svm_fifo_segment_create ('%s', %d) failed", |
| 69 | ca->segment_name, ca->segment_size); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 70 | return VNET_API_ERROR_SVM_SEGMENT_CREATE_FAIL; |
| 71 | } |
| 72 | |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 73 | vec_append (sm->segment_indices, ca->new_segment_indices); |
| 74 | vec_free (ca->new_segment_indices); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 75 | |
| 76 | return 0; |
| 77 | } |
| 78 | |
| 79 | int |
| 80 | session_manager_add_segment (segment_manager_t * sm) |
| 81 | { |
| 82 | u8 *segment_name; |
| 83 | svm_fifo_segment_create_args_t _ca, *ca = &_ca; |
| 84 | u32 add_segment_size; |
| 85 | int rv; |
| 86 | |
| 87 | memset (ca, 0, sizeof (*ca)); |
| 88 | segment_name = format (0, "%d-%d%c", getpid (), segment_name_counter++, 0); |
| 89 | add_segment_size = sm->properties->add_segment_size ? |
| 90 | sm->properties->add_segment_size : default_segment_size; |
| 91 | |
| 92 | rv = session_manager_add_segment_i (sm, add_segment_size, segment_name); |
| 93 | vec_free (segment_name); |
| 94 | return rv; |
| 95 | } |
| 96 | |
| 97 | int |
| 98 | session_manager_add_first_segment (segment_manager_t * sm, u32 segment_size) |
| 99 | { |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 100 | u8 *segment_name; |
| 101 | int rv; |
| 102 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 103 | segment_name = format (0, "%d-%d%c", getpid (), segment_name_counter++, 0); |
| 104 | rv = session_manager_add_segment_i (sm, segment_size, segment_name); |
| 105 | vec_free (segment_name); |
| 106 | return rv; |
| 107 | } |
| 108 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 109 | static void |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 110 | segment_manager_alloc_process_private_segment |
| 111 | (segment_manager_properties_t * props) |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 112 | { |
| 113 | svm_fifo_segment_create_args_t _a, *a = &_a; |
| 114 | |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 115 | if (private_segment_indices) |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 116 | return; |
| 117 | |
| 118 | memset (a, 0, sizeof (*a)); |
| 119 | a->segment_name = "process-private-segment"; |
| 120 | a->segment_size = ~0; |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 121 | a->rx_fifo_size = props->rx_fifo_size; |
| 122 | a->tx_fifo_size = props->tx_fifo_size; |
| 123 | a->preallocated_fifo_pairs = props->preallocated_fifo_pairs; |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 124 | a->private_segment_count = props->private_segment_count; |
| 125 | a->private_segment_size = props->private_segment_size; |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 126 | |
| 127 | if (svm_fifo_segment_create_process_private (a)) |
| 128 | clib_warning ("Failed to create process private segment"); |
| 129 | |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 130 | private_segment_indices = a->new_segment_indices; |
| 131 | ASSERT (vec_len (private_segment_indices)); |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 132 | } |
| 133 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 134 | /** |
| 135 | * Initializes segment manager based on options provided. |
| 136 | * Returns error if svm segment allocation fails. |
| 137 | */ |
| 138 | int |
| 139 | segment_manager_init (segment_manager_t * sm, |
| 140 | segment_manager_properties_t * properties, |
| 141 | u32 first_seg_size) |
| 142 | { |
| 143 | int rv; |
| 144 | |
| 145 | /* app allocates these */ |
| 146 | sm->properties = properties; |
| 147 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 148 | first_seg_size = first_seg_size > 0 ? first_seg_size : default_segment_size; |
| 149 | |
| 150 | if (sm->properties->use_private_segment == 0) |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 151 | { |
| 152 | rv = session_manager_add_first_segment (sm, first_seg_size); |
| 153 | if (rv) |
| 154 | { |
| 155 | clib_warning ("Failed to allocate segment"); |
| 156 | return rv; |
| 157 | } |
| 158 | } |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 159 | else |
| 160 | { |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 161 | if (vec_len (private_segment_indices) == 0) |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 162 | segment_manager_alloc_process_private_segment (properties); |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 163 | ASSERT (vec_len (private_segment_indices)); |
| 164 | vec_append (sm->segment_indices, private_segment_indices); |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 165 | } |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 166 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 167 | clib_spinlock_init (&sm->lockp); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 168 | return 0; |
| 169 | } |
| 170 | |
Dave Wallace | 7b749fe | 2017-07-05 14:30:46 -0400 | [diff] [blame] | 171 | void |
| 172 | segment_manager_first_segment_maybe_del (segment_manager_t * sm) |
| 173 | { |
| 174 | svm_fifo_segment_private_t *fifo_segment; |
| 175 | |
| 176 | /* If the first semgment has no fifos, then delete the 1st segment |
| 177 | */ |
| 178 | fifo_segment = svm_fifo_get_segment (sm->segment_indices[0]); |
| 179 | if (!svm_fifo_segment_has_fifos (fifo_segment)) |
| 180 | { |
| 181 | clib_spinlock_lock (&sm->lockp); |
| 182 | svm_fifo_segment_delete (fifo_segment); |
| 183 | vec_del1 (sm->segment_indices, 0); |
| 184 | clib_spinlock_unlock (&sm->lockp); |
| 185 | } |
| 186 | } |
| 187 | |
| 188 | /** |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 189 | * Removes segment manager. |
| 190 | * |
| 191 | * Since the fifos allocated in the segment keep backpointers to the sessions |
| 192 | * prior to removing the segment, we call session disconnect. This |
| 193 | * subsequently propages into transport. |
| 194 | */ |
| 195 | void |
| 196 | segment_manager_del (segment_manager_t * sm) |
| 197 | { |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 198 | int j; |
Dave Wallace | 7b749fe | 2017-07-05 14:30:46 -0400 | [diff] [blame] | 199 | svm_fifo_segment_private_t *fifo_segment; |
| 200 | ASSERT (vec_len (sm->segment_indices)); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 201 | |
| 202 | /* Across all fifo segments used by the server */ |
| 203 | for (j = 0; j < vec_len (sm->segment_indices); j++) |
| 204 | { |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 205 | svm_fifo_t *fifo; |
| 206 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 207 | /* Vector of fifos allocated in the segment */ |
| 208 | fifo_segment = svm_fifo_get_segment (sm->segment_indices[j]); |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 209 | fifo = svm_fifo_segment_get_fifo_list (fifo_segment); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 210 | |
| 211 | /* |
| 212 | * Remove any residual sessions from the session lookup table |
| 213 | * Don't bother deleting the individual fifos, we're going to |
| 214 | * throw away the fifo segment in a minute. |
| 215 | */ |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 216 | while (fifo) |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 217 | { |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 218 | u32 session_index, thread_index; |
| 219 | stream_session_t *session; |
| 220 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 221 | session_index = fifo->master_session_index; |
| 222 | thread_index = fifo->master_thread_index; |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 223 | |
| 224 | session = stream_session_get (session_index, thread_index); |
| 225 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 226 | /* Instead of directly removing the session call disconnect */ |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 227 | session_send_session_evt_to_thread (stream_session_handle (session), |
| 228 | FIFO_EVENT_DISCONNECT, |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 229 | thread_index); |
| 230 | fifo = fifo->next; |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 231 | } |
| 232 | |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 233 | /* Instead of removing the segment, test when cleaning up disconnected |
| 234 | * sessions if the segment can be removed. |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 235 | */ |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 236 | } |
| 237 | |
Dave Wallace | 7b749fe | 2017-07-05 14:30:46 -0400 | [diff] [blame] | 238 | segment_manager_first_segment_maybe_del (sm); |
| 239 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 240 | clib_spinlock_free (&sm->lockp); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 241 | pool_put (segment_managers, sm); |
| 242 | } |
| 243 | |
| 244 | static int |
| 245 | segment_manager_notify_app_seg_add (segment_manager_t * sm, |
| 246 | u32 fifo_segment_index) |
| 247 | { |
| 248 | application_t *app = application_get (sm->app_index); |
| 249 | u32 seg_size = 0; |
| 250 | u8 *seg_name; |
| 251 | |
| 252 | /* Send an API message to the external app, to map new segment */ |
| 253 | ASSERT (app->cb_fns.add_segment_callback); |
| 254 | |
| 255 | segment_manager_get_segment_info (fifo_segment_index, &seg_name, &seg_size); |
| 256 | return app->cb_fns.add_segment_callback (app->api_client_index, seg_name, |
| 257 | seg_size); |
| 258 | } |
| 259 | |
| 260 | int |
| 261 | segment_manager_alloc_session_fifos (segment_manager_t * sm, |
| 262 | svm_fifo_t ** server_rx_fifo, |
| 263 | svm_fifo_t ** server_tx_fifo, |
| 264 | u32 * fifo_segment_index) |
| 265 | { |
| 266 | svm_fifo_segment_private_t *fifo_segment; |
| 267 | u32 fifo_size, sm_index; |
| 268 | u8 added_a_segment = 0; |
| 269 | int i; |
| 270 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 271 | ASSERT (vec_len (sm->segment_indices)); |
| 272 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 273 | /* Make sure we don't have multiple threads trying to allocate segments |
| 274 | * at the same time. */ |
| 275 | clib_spinlock_lock (&sm->lockp); |
| 276 | |
| 277 | /* Allocate svm fifos */ |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 278 | again: |
| 279 | for (i = 0; i < vec_len (sm->segment_indices); i++) |
| 280 | { |
| 281 | *fifo_segment_index = sm->segment_indices[i]; |
| 282 | fifo_segment = svm_fifo_get_segment (*fifo_segment_index); |
| 283 | |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 284 | /* FC: cleanup, make sure sm->properties->xxx_fifo_size always set */ |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 285 | fifo_size = sm->properties->rx_fifo_size; |
| 286 | fifo_size = (fifo_size == 0) ? default_fifo_size : fifo_size; |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 287 | *server_rx_fifo = |
| 288 | svm_fifo_segment_alloc_fifo (fifo_segment, fifo_size, |
| 289 | FIFO_SEGMENT_RX_FREELIST); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 290 | |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 291 | /* FC: cleanup, make sure sm->properties->xxx_fifo_size always set */ |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 292 | fifo_size = sm->properties->tx_fifo_size; |
| 293 | fifo_size = (fifo_size == 0) ? default_fifo_size : fifo_size; |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 294 | *server_tx_fifo = |
| 295 | svm_fifo_segment_alloc_fifo (fifo_segment, fifo_size, |
| 296 | FIFO_SEGMENT_TX_FREELIST); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 297 | |
| 298 | if (*server_rx_fifo == 0) |
| 299 | { |
| 300 | /* This would be very odd, but handle it... */ |
| 301 | if (*server_tx_fifo != 0) |
| 302 | { |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 303 | svm_fifo_segment_free_fifo (fifo_segment, *server_tx_fifo, |
| 304 | FIFO_SEGMENT_TX_FREELIST); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 305 | *server_tx_fifo = 0; |
| 306 | } |
| 307 | continue; |
| 308 | } |
| 309 | if (*server_tx_fifo == 0) |
| 310 | { |
| 311 | if (*server_rx_fifo != 0) |
| 312 | { |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 313 | svm_fifo_segment_free_fifo (fifo_segment, *server_rx_fifo, |
| 314 | FIFO_SEGMENT_RX_FREELIST); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 315 | *server_rx_fifo = 0; |
| 316 | } |
| 317 | continue; |
| 318 | } |
| 319 | break; |
| 320 | } |
| 321 | |
| 322 | /* See if we're supposed to create another segment */ |
| 323 | if (*server_rx_fifo == 0) |
| 324 | { |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 325 | if (sm->properties->add_segment && !sm->properties->use_private_segment) |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 326 | { |
| 327 | if (added_a_segment) |
| 328 | { |
| 329 | clib_warning ("added a segment, still cant allocate a fifo"); |
Florin Coras | f03a59a | 2017-06-09 21:07:32 -0700 | [diff] [blame] | 330 | clib_spinlock_unlock (&sm->lockp); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 331 | return SESSION_ERROR_NEW_SEG_NO_SPACE; |
| 332 | } |
| 333 | |
| 334 | if (session_manager_add_segment (sm)) |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 335 | { |
Florin Coras | f03a59a | 2017-06-09 21:07:32 -0700 | [diff] [blame] | 336 | clib_spinlock_unlock (&sm->lockp); |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 337 | return VNET_API_ERROR_URI_FIFO_CREATE_FAILED; |
| 338 | } |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 339 | |
| 340 | added_a_segment = 1; |
| 341 | goto again; |
| 342 | } |
| 343 | else |
| 344 | { |
| 345 | clib_warning ("No space to allocate fifos!"); |
Florin Coras | f03a59a | 2017-06-09 21:07:32 -0700 | [diff] [blame] | 346 | clib_spinlock_unlock (&sm->lockp); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 347 | return SESSION_ERROR_NO_SPACE; |
| 348 | } |
| 349 | } |
| 350 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 351 | /* Backpointers to segment manager */ |
| 352 | sm_index = segment_manager_index (sm); |
| 353 | (*server_tx_fifo)->segment_manager = sm_index; |
| 354 | (*server_rx_fifo)->segment_manager = sm_index; |
| 355 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 356 | clib_spinlock_unlock (&sm->lockp); |
| 357 | |
| 358 | if (added_a_segment) |
| 359 | return segment_manager_notify_app_seg_add (sm, *fifo_segment_index); |
| 360 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 361 | return 0; |
| 362 | } |
| 363 | |
| 364 | void |
| 365 | segment_manager_dealloc_fifos (u32 svm_segment_index, svm_fifo_t * rx_fifo, |
| 366 | svm_fifo_t * tx_fifo) |
| 367 | { |
| 368 | segment_manager_t *sm; |
| 369 | svm_fifo_segment_private_t *fifo_segment; |
| 370 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 371 | sm = segment_manager_get_if_valid (rx_fifo->segment_manager); |
| 372 | |
| 373 | /* It's possible to have no segment manager if the session was removed |
| 374 | * as result of a detach */ |
| 375 | if (!sm) |
| 376 | return; |
| 377 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 378 | fifo_segment = svm_fifo_get_segment (svm_segment_index); |
Dave Barach | 10d8cc6 | 2017-05-30 09:30:07 -0400 | [diff] [blame] | 379 | svm_fifo_segment_free_fifo (fifo_segment, rx_fifo, |
| 380 | FIFO_SEGMENT_RX_FREELIST); |
| 381 | svm_fifo_segment_free_fifo (fifo_segment, tx_fifo, |
| 382 | FIFO_SEGMENT_TX_FREELIST); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 383 | |
Dave Barach | 2c25a62 | 2017-06-26 11:35:07 -0400 | [diff] [blame] | 384 | /* Don't try to delete process-private segments */ |
| 385 | if (sm->properties->private_segment_count > 0) |
| 386 | return; |
| 387 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 388 | /* Remove segment only if it holds no fifos and not the first */ |
| 389 | if (sm->segment_indices[0] != svm_segment_index |
| 390 | && !svm_fifo_segment_has_fifos (fifo_segment)) |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 391 | { |
Florin Coras | f03a59a | 2017-06-09 21:07:32 -0700 | [diff] [blame] | 392 | clib_spinlock_lock (&sm->lockp); |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 393 | svm_fifo_segment_delete (fifo_segment); |
| 394 | vec_del1 (sm->segment_indices, svm_segment_index); |
Florin Coras | f03a59a | 2017-06-09 21:07:32 -0700 | [diff] [blame] | 395 | clib_spinlock_unlock (&sm->lockp); |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 396 | } |
| 397 | } |
| 398 | |
Florin Coras | a546481 | 2017-04-19 13:00:05 -0700 | [diff] [blame] | 399 | /** |
| 400 | * Allocates shm queue in the first segment |
| 401 | */ |
| 402 | unix_shared_memory_queue_t * |
| 403 | segment_manager_alloc_queue (segment_manager_t * sm, u32 queue_size) |
| 404 | { |
| 405 | ssvm_shared_header_t *sh; |
| 406 | svm_fifo_segment_private_t *segment; |
| 407 | unix_shared_memory_queue_t *q; |
| 408 | void *oldheap; |
| 409 | |
| 410 | ASSERT (sm->segment_indices != 0); |
| 411 | |
| 412 | segment = svm_fifo_get_segment (sm->segment_indices[0]); |
| 413 | sh = segment->ssvm.sh; |
| 414 | |
| 415 | oldheap = ssvm_push_heap (sh); |
| 416 | q = |
| 417 | unix_shared_memory_queue_init (queue_size, sizeof (session_fifo_event_t), |
| 418 | 0 /* consumer pid */ , 0 |
| 419 | /* signal when queue non-empty */ ); |
| 420 | ssvm_pop_heap (oldheap); |
| 421 | return q; |
| 422 | } |
| 423 | |
| 424 | /** |
| 425 | * Frees shm queue allocated in the first segment |
| 426 | */ |
| 427 | void |
| 428 | segment_manager_dealloc_queue (segment_manager_t * sm, |
| 429 | unix_shared_memory_queue_t * q) |
| 430 | { |
| 431 | ssvm_shared_header_t *sh; |
| 432 | svm_fifo_segment_private_t *segment; |
| 433 | void *oldheap; |
| 434 | |
| 435 | ASSERT (sm->segment_indices != 0); |
| 436 | |
| 437 | segment = svm_fifo_get_segment (sm->segment_indices[0]); |
| 438 | sh = segment->ssvm.sh; |
| 439 | |
| 440 | oldheap = ssvm_push_heap (sh); |
| 441 | unix_shared_memory_queue_free (q); |
| 442 | ssvm_pop_heap (oldheap); |
| 443 | } |
| 444 | |
Florin Coras | 6cf30ad | 2017-04-04 23:08:23 -0700 | [diff] [blame] | 445 | /* |
| 446 | * fd.io coding-style-patch-verification: ON |
| 447 | * |
| 448 | * Local Variables: |
| 449 | * eval: (c-set-style "gnu") |
| 450 | * End: |
| 451 | */ |