+static ct_segment_t *
+ct_alloc_segment (ct_main_t *cm, app_worker_t *server_wrk, u64 table_handle,
+ segment_manager_t *sm, u32 client_wrk_index)
+{
+ u32 seg_ctx_index = ~0, sm_index, pair_bytes;
+ segment_manager_props_t *props;
+ const u32 margin = 16 << 10;
+ ct_segments_ctx_t *seg_ctx;
+ app_worker_t *client_wrk;
+ u64 seg_size, seg_handle;
+ application_t *server;
+ ct_segment_t *ct_seg;
+ uword *spp;
+ int fs_index;
+
+ server = application_get (server_wrk->app_index);
+ props = application_segment_manager_properties (server);
+ sm_index = segment_manager_index (sm);
+ pair_bytes = props->rx_fifo_size + props->tx_fifo_size + margin;
+
+ /*
+ * Make sure another thread did not alloc a segment while acquiring the lock
+ */
+
+ spp = hash_get (cm->app_segs_ctxs_table, table_handle);
+ if (spp)
+ {
+ seg_ctx_index = *spp;
+ ct_seg = ct_lookup_free_segment (cm, sm, seg_ctx_index);
+ if (ct_seg)
+ return ct_seg;
+ }
+
+ /*
+ * No segment, try to alloc one and notify the server and the client.
+ * Make sure the segment is not used for other fifos
+ */
+ seg_size = clib_max (props->segment_size, 128 << 20);
+ fs_index =
+ segment_manager_add_segment2 (sm, seg_size, FIFO_SEGMENT_F_CUSTOM_USE);
+ if (fs_index < 0)
+ return 0;
+
+ if (seg_ctx_index == ~0)
+ {
+ pool_get_zero (cm->app_seg_ctxs, seg_ctx);
+ seg_ctx_index = seg_ctx - cm->app_seg_ctxs;
+ hash_set (cm->app_segs_ctxs_table, table_handle, seg_ctx_index);
+ seg_ctx->server_wrk = server_wrk->wrk_index;
+ seg_ctx->client_wrk = client_wrk_index;
+ seg_ctx->sm_index = sm_index;
+ seg_ctx->fifo_pair_bytes = pair_bytes;
+ }
+ else
+ {
+ seg_ctx = pool_elt_at_index (cm->app_seg_ctxs, seg_ctx_index);
+ }
+
+ pool_get_zero (seg_ctx->segments, ct_seg);
+ ct_seg->segment_index = fs_index;
+ ct_seg->server_n_sessions = 0;
+ ct_seg->client_n_sessions = 0;
+ ct_seg->ct_seg_index = ct_seg - seg_ctx->segments;
+ ct_seg->seg_ctx_index = seg_ctx_index;
+
+ /* New segment, notify the server and client */
+ seg_handle = segment_manager_make_segment_handle (sm_index, fs_index);
+ if (app_worker_add_segment_notify (server_wrk, seg_handle))
+ goto error;
+
+ client_wrk = app_worker_get (client_wrk_index);
+ if (app_worker_add_segment_notify (client_wrk, seg_handle))
+ {
+ app_worker_del_segment_notify (server_wrk, seg_handle);
+ goto error;
+ }
+
+ return ct_seg;
+
+error:
+
+ segment_manager_lock_and_del_segment (sm, fs_index);
+ pool_put_index (seg_ctx->segments, ct_seg->seg_ctx_index);
+ return 0;
+}
+