+ props = segment_manager_properties_get (sm);
+
+ /* Not configured for addition of new segments and not first */
+ if (!props->add_segment && !segment_size)
+ {
+ clib_warning ("cannot allocate new segment");
+ return VNET_API_ERROR_INVALID_VALUE;
+ }
+
+ /*
+ * Allocate fifo segment and lock if needed
+ */
+ if (vlib_num_workers ())
+ {
+ clib_rwlock_writer_lock (&sm->segments_rwlock);
+ pool_get (sm->segments, seg);
+ }
+ else
+ {
+ pool_get (sm->segments, seg);
+ }
+ memset (seg, 0, sizeof (*seg));
+
+ /*
+ * Initialize ssvm segment and svm fifo private header
+ */
+ segment_size = segment_size ? segment_size : props->add_segment_size;
+ page_size = clib_mem_get_page_size ();
+ segment_size = (segment_size + page_size - 1) & ~(page_size - 1);
+ if (props->segment_type != SSVM_SEGMENT_PRIVATE)
+ {
+ seg_name = format (0, "%d-%d%c", getpid (), segment_name_counter++, 0);
+ alloc_size = segment_size + rnd_margin;
+ baseva = clib_valloc_alloc (&smm->va_allocator, alloc_size, 0);
+ if (!baseva)
+ {
+ clib_warning ("out of space for segments");
+ return -1;
+ }
+ }
+ else
+ seg_name = format (0, "%s%c", "process-private-segment", 0);
+
+ seg->ssvm.ssvm_size = segment_size;
+ seg->ssvm.name = seg_name;
+ seg->ssvm.requested_va = baseva;
+
+ if ((rv = ssvm_master_init (&seg->ssvm, props->segment_type)))
+ {
+ clib_warning ("svm_master_init ('%v', %u) failed", seg_name,
+ segment_size);
+
+ if (props->segment_type != SSVM_SEGMENT_PRIVATE)
+ clib_valloc_free (&smm->va_allocator, baseva);
+ pool_put (sm->segments, seg);
+ return (rv);
+ }
+
+ svm_fifo_segment_init (seg);
+
+ /*
+ * Save segment index before dropping lock, if any held
+ */
+ seg_index = seg - sm->segments;
+
+ if (vlib_num_workers ())
+ clib_rwlock_writer_unlock (&sm->segments_rwlock);
+
+ return seg_index;
+}
+
+segment_manager_t *
+segment_manager_new ()
+{
+ segment_manager_main_t *smm = &segment_manager_main;
+ segment_manager_t *sm;
+ pool_get (smm->segment_managers, sm);
+ memset (sm, 0, sizeof (*sm));
+ clib_rwlock_init (&sm->segments_rwlock);
+ return sm;