static void vl_unmap_shmem_internal (u8 is_client) { svm_region_t *rp; int i; api_main_t *am = &api_main; if (!svm_get_root_rp ()) return; for (i = 0; i < vec_len (am->mapped_shmem_regions); i++) { rp = am->mapped_shmem_regions[i]; is_client ? svm_region_unmap_client (rp) : svm_region_unmap (rp); } vec_free (am->mapped_shmem_regions); am->shmem_hdr = 0; is_client ? svm_region_exit_client () : svm_region_exit (); /* $$$ more careful cleanup, valgrind run... */ vec_free (am->msg_handlers); vec_free (am->msg_endian_handlers); vec_free (am->msg_print_handlers); }
void svmdb_unmap (svmdb_client_t * client) { ASSERT (client); if (!svm_get_root_rp ()) return; svm_region_unmap ((void *) client->db_rp); svm_region_exit (); vec_free (client); }
int vl_map_shmem (const char *region_name, int is_vlib) { svm_map_region_args_t _a, *a = &_a; svm_region_t *vlib_rp, *root_rp; api_main_t *am = &api_main; int i; struct timespec ts, tsrem; char *vpe_api_region_suffix = "-vpe-api"; clib_memset (a, 0, sizeof (*a)); if (strstr (region_name, vpe_api_region_suffix)) { u8 *root_path = format (0, "%s", region_name); _vec_len (root_path) = (vec_len (root_path) - strlen (vpe_api_region_suffix)); vec_terminate_c_string (root_path); a->root_path = (const char *) root_path; am->root_path = (const char *) root_path; } if (is_vlib == 0) { int tfd; u8 *api_name; /* * Clients wait for vpp to set up the root / API regioins */ if (am->root_path) api_name = format (0, "/dev/shm/%s-%s%c", am->root_path, region_name + 1, 0); else api_name = format (0, "/dev/shm%s%c", region_name, 0); /* Wait up to 100 seconds... */ for (i = 0; i < 10000; i++) { ts.tv_sec = 0; ts.tv_nsec = 10000 * 1000; /* 10 ms */ while (nanosleep (&ts, &tsrem) < 0) ts = tsrem; tfd = open ((char *) api_name, O_RDWR); if (tfd >= 0) break; } vec_free (api_name); if (tfd < 0) { clib_warning ("region init fail"); return -2; } close (tfd); svm_region_init_chroot_uid_gid (am->root_path, getuid (), getgid ()); } if (a->root_path != NULL) { a->name = "/vpe-api"; } else a->name = region_name; a->size = am->api_size ? am->api_size : (16 << 20); a->flags = SVM_FLAGS_MHEAP; a->uid = am->api_uid; a->gid = am->api_gid; a->pvt_heap_size = am->api_pvt_heap_size; vlib_rp = svm_region_find_or_create (a); if (vlib_rp == 0) return (-2); pthread_mutex_lock (&vlib_rp->mutex); /* Has someone else set up the shared-memory variable table? */ if (vlib_rp->user_ctx) { am->shmem_hdr = (void *) vlib_rp->user_ctx; am->our_pid = getpid (); if (is_vlib) { svm_queue_t *q; uword old_msg; /* * application restart. Reset cached pids, API message * rings, list of clients; otherwise, various things * fail. (e.g. queue non-empty notification) */ /* ghosts keep the region from disappearing properly */ svm_client_scan_this_region_nolock (vlib_rp); am->shmem_hdr->application_restarts++; q = am->shmem_hdr->vl_input_queue; am->shmem_hdr->vl_pid = getpid (); q->consumer_pid = am->shmem_hdr->vl_pid; /* Drain the input queue, freeing msgs */ for (i = 0; i < 10; i++) { if (pthread_mutex_trylock (&q->mutex) == 0) { pthread_mutex_unlock (&q->mutex); goto mutex_ok; } ts.tv_sec = 0; ts.tv_nsec = 10000 * 1000; /* 10 ms */ while (nanosleep (&ts, &tsrem) < 0) ts = tsrem; } /* Mutex buggered, "fix" it */ clib_memset (&q->mutex, 0, sizeof (q->mutex)); clib_warning ("forcibly release main input queue mutex"); mutex_ok: am->vlib_rp = vlib_rp; while (svm_queue_sub (q, (u8 *) & old_msg, SVM_Q_NOWAIT, 0) != -2 /* queue underflow */ ) { vl_msg_api_free_nolock ((void *) old_msg); am->shmem_hdr->restart_reclaims++; } pthread_mutex_unlock (&vlib_rp->mutex); root_rp = svm_get_root_rp (); ASSERT (root_rp); /* Clean up the root region client list */ pthread_mutex_lock (&root_rp->mutex); svm_client_scan_this_region_nolock (root_rp); pthread_mutex_unlock (&root_rp->mutex); } else { pthread_mutex_unlock (&vlib_rp->mutex); } am->vlib_rp = vlib_rp; vec_add1 (am->mapped_shmem_regions, vlib_rp); return 0; } /* Clients simply have to wait... */ if (!is_vlib) { pthread_mutex_unlock (&vlib_rp->mutex); /* Wait up to 100 seconds... */ for (i = 0; i < 10000; i++) { ts.tv_sec = 0; ts.tv_nsec = 10000 * 1000; /* 10 ms */ while (nanosleep (&ts, &tsrem) < 0) ts = tsrem; if (vlib_rp->user_ctx) goto ready; } /* Clean up and leave... */ svm_region_unmap (vlib_rp); clib_warning ("region init fail"); return (-2); ready: am->shmem_hdr = (void *) vlib_rp->user_ctx; am->our_pid = getpid (); am->vlib_rp = vlib_rp; vec_add1 (am->mapped_shmem_regions, vlib_rp); return 0; } /* Nope, it's our problem... */ vl_init_shmem (vlib_rp, 0 /* default config */ , 1 /* is vlib */ , 0 /* is_private_region */ ); vec_add1 (am->mapped_shmem_regions, vlib_rp); return 0; }
int ssvm_master_init_shm (ssvm_private_t * ssvm) { int ssvm_fd; #if USE_DLMALLOC == 0 int mh_flags = MHEAP_FLAG_DISABLE_VM | MHEAP_FLAG_THREAD_SAFE; #endif clib_mem_vm_map_t mapa = { 0 }; u8 junk = 0, *ssvm_filename; ssvm_shared_header_t *sh; uword page_size, requested_va = 0; void *oldheap; if (ssvm->ssvm_size == 0) return SSVM_API_ERROR_NO_SIZE; if (CLIB_DEBUG > 1) clib_warning ("[%d] creating segment '%s'", getpid (), ssvm->name); ASSERT (vec_c_string_is_terminated (ssvm->name)); ssvm_filename = format (0, "/dev/shm/%s%c", ssvm->name, 0); unlink ((char *) ssvm_filename); vec_free (ssvm_filename); ssvm_fd = shm_open ((char *) ssvm->name, O_RDWR | O_CREAT | O_EXCL, 0777); if (ssvm_fd < 0) { clib_unix_warning ("create segment '%s'", ssvm->name); return SSVM_API_ERROR_CREATE_FAILURE; } if (fchmod (ssvm_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0) clib_unix_warning ("ssvm segment chmod"); if (svm_get_root_rp ()) { /* TODO: is this really needed? */ svm_main_region_t *smr = svm_get_root_rp ()->data_base; if (fchown (ssvm_fd, smr->uid, smr->gid) < 0) clib_unix_warning ("ssvm segment chown"); } if (lseek (ssvm_fd, ssvm->ssvm_size, SEEK_SET) < 0) { clib_unix_warning ("lseek"); close (ssvm_fd); return SSVM_API_ERROR_SET_SIZE; } if (write (ssvm_fd, &junk, 1) != 1) { clib_unix_warning ("set ssvm size"); close (ssvm_fd); return SSVM_API_ERROR_SET_SIZE; } page_size = clib_mem_get_fd_page_size (ssvm_fd); if (ssvm->requested_va) { requested_va = ssvm->requested_va; clib_mem_vm_randomize_va (&requested_va, min_log2 (page_size)); } mapa.requested_va = requested_va; mapa.size = ssvm->ssvm_size; mapa.fd = ssvm_fd; if (clib_mem_vm_ext_map (&mapa)) { clib_unix_warning ("mmap"); close (ssvm_fd); return SSVM_API_ERROR_MMAP; } close (ssvm_fd); sh = mapa.addr; sh->master_pid = ssvm->my_pid; sh->ssvm_size = ssvm->ssvm_size; sh->ssvm_va = pointer_to_uword (sh); sh->type = SSVM_SEGMENT_SHM; #if USE_DLMALLOC == 0 sh->heap = mheap_alloc_with_flags (((u8 *) sh) + page_size, ssvm->ssvm_size - page_size, mh_flags); #else sh->heap = create_mspace_with_base (((u8 *) sh) + page_size, ssvm->ssvm_size - page_size, 1 /* locked */ ); mspace_disable_expand (sh->heap); #endif oldheap = ssvm_push_heap (sh); sh->name = format (0, "%s", ssvm->name, 0); ssvm_pop_heap (oldheap); ssvm->sh = sh; ssvm->my_pid = getpid (); ssvm->i_am_master = 1; /* The application has to set set sh->ready... */ return 0; }