23 #include <sys/types.h> 26 #include <netinet/in.h> 73 if ((fd = open (
"/proc/self/maps", 0)) < 0)
79 if (
unformat (&input,
"%llx-%llx", &start, &end))
88 if (bits >= 36 && bits <= 48)
95 return 0x130000000ULL;
101 pthread_mutex_lock (&rp->
mutex);
124 for (i =
nheld - 1; i >= 0; i--)
128 for (j = i; j <
MAXLOCK - 1; j++)
138 pthread_mutex_unlock (&rp->
mutex);
152 s =
format (s,
"NODATA ");
164 if (size >= (1 << 20))
166 s =
format (s,
"(%d mb)", size >> 20);
168 else if (size >= (1 << 10))
170 s =
format (s,
"(%d kb)", size >> 10);
174 s =
format (s,
"(%d bytes)", size);
183 int verbose = va_arg (*args,
int);
187 s =
format (s,
"%s: base va 0x%x size 0x%x %U\n",
190 s =
format (s,
" user_ctx 0x%x, bitmap_size %d\n",
198 " region_heap 0x%x data_base 0x%x data_heap 0x%x\n",
213 s =
format (s,
" VM in use: ");
233 s =
format (s,
" 0x%x - 0x%x (%dk)\n", lo, hi,
239 #if USE_DLMALLOC == 0 293 if (fstat (fd, &statb) < 0)
300 if (statb.st_mode & S_IFREG)
302 if (statb.st_size == 0)
304 if (lseek (fd, map_size, SEEK_SET) == (off_t) - 1)
310 if (write (fd, &junk, 1) != 1)
327 ASSERT (map_size <= rp->virtual_size -
330 if (mmap (rp->
data_base, map_size, PROT_READ | PROT_WRITE,
331 MAP_SHARED | MAP_FIXED, fd, 0) == MAP_FAILED)
344 #if USE_DLMALLOC == 0 385 if (fstat (fd, &statb) < 0)
392 if (statb.st_mode & S_IFREG)
394 if (statb.st_size == 0)
396 if (lseek (fd, map_size, SEEK_SET) == (off_t) - 1)
402 if (write (fd, &junk, 1) != 1)
419 ASSERT (map_size <= rp->virtual_size
424 if (mmap (rp->
data_base, map_size, PROT_READ | PROT_WRITE,
425 MAP_SHARED | MAP_FIXED, fd, 0) == MAP_FAILED)
443 int root_path_offset = 0;
455 path =
format (0,
"/dev/shm/%s%c", &a->
root_path[root_path_offset], 0);
456 split_point = path + 1;
461 while (*split_point && *split_point !=
'/')
469 mkdir_arg[
vec_len (mkdir_arg) - 1] =
'-';
475 if (a->
name[0] ==
'/')
479 &a->
name[name_offset], 0);
489 pthread_mutexattr_t attr;
490 pthread_condattr_t cattr;
491 int nbits, words, bit;
500 if (pthread_mutexattr_init (&attr))
503 if (pthread_mutexattr_setpshared (&attr, PTHREAD_PROCESS_SHARED))
506 if (pthread_mutex_init (&rp->
mutex, &attr))
509 if (pthread_mutexattr_destroy (&attr))
512 if (pthread_condattr_init (&cattr))
515 if (pthread_condattr_setpshared (&cattr, PTHREAD_PROCESS_SHARED))
518 if (pthread_cond_init (&rp->
condvar, &cattr))
521 if (pthread_condattr_destroy (&cattr))
529 #if USE_DLMALLOC == 0 573 while (overhead_space > 0);
609 int pid_holding_region_lock;
611 int dead_region_recovery = 0;
614 struct timespec ts, tsrem;
623 getpid (), a->
name, shm_name);
625 svm_fd = shm_open ((
char *) shm_name, O_RDWR | O_CREAT | O_EXCL, 0777);
629 if (fchmod (svm_fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP) < 0)
632 if (fchown (svm_fd, a->
uid, a->
gid) < 0)
637 if (lseek (svm_fd, a->
size, SEEK_SET) == (off_t) - 1)
643 if (write (svm_fd, &junk, 1) != 1)
651 PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, svm_fd, 0);
663 return ((
void *) rp);
667 svm_fd = shm_open ((
char *) shm_name, O_RDWR, 0777);
673 perror (
"svm_region_map(mmap open)");
678 if (fchown (svm_fd, a->
uid, a->
gid) < 0)
684 if (0 != fstat (svm_fd, &stat))
690 if (stat.st_size > 0)
696 clib_warning (
"waiting for resize of shm file timed out");
701 ts.tv_nsec = 100000000;
702 while (nanosleep (&ts, &tsrem) < 0)
708 PROT_READ | PROT_WRITE, MAP_SHARED, svm_fd, 0);
720 while (rp->
version == 0 && deadman++ < 5)
732 munmap (rp, a->
size);
741 PROT_READ | PROT_WRITE,
742 MAP_SHARED | MAP_FIXED, svm_fd, 0);
762 if (pid_holding_region_lock && kill (pid_holding_region_lock, 0) < 0)
765 (
"region %s mutex held by dead pid %d, tag %d, force unlock",
768 rp->
mutex.__data.__owner = 0;
769 rp->
mutex.__data.__lock = 0;
770 dead_region_recovery = 1;
773 if (dead_region_recovery)
780 if (dead_region_recovery)
789 if (dead_region_recovery)
796 return ((
void *) rp);
806 for (i = 0; i <
nheld; i++)
817 uword randomize_baseva;
833 a->
baseva += randomize_baseva;
978 for (i = 0; i < (need_nbits - 1); i++)
991 while (index < root_rp->bitmap_size);
996 clib_warning (
"region %s: not enough VM to allocate 0x%llx (%lld)",
1007 clib_warning (
"set %d bits at index %d", need_nbits, index);
1010 for (i = 0; i < need_nbits; i++)
1051 clib_warning (
"[%d] shm_unlink (%s)", getpid (), shm_name);
1052 shm_unlink ((
const char *) shm_name);
1067 int i, mypid = getpid ();
1070 uword virtual_base, virtual_size;
1113 if (nclients_left == 0)
1115 int index, nbits,
i;
1134 clib_warning (
"clear %d bits at index %d", nbits, index);
1137 for (i = 0; i < nbits; i++)
1171 munmap ((
void *) virtual_base, virtual_size);
1180 munmap ((
void *) virtual_base, virtual_size);
1202 int i, mypid = getpid ();
1203 uword virtual_base, virtual_size;
1239 if (!is_client && vec_len (root_rp->
client_pids) == 0)
1246 munmap ((
void *) virtual_base, virtual_size);
1265 int mypid = getpid ();
1301 int mypid = getpid ();
1309 pthread_mutex_lock (&root_rp->
mutex);
1335 name = vec_dup (subp->subregion_name);
1336 vec_add1(svm_names, name);
1340 pthread_mutex_unlock (&root_rp->
mutex);
1342 for (i = 0; i <
vec_len (svm_names); i++)
1346 a->
name = (
char *) svm_names[i];
1350 pthread_mutex_lock (&rp->
mutex);
1354 pthread_mutex_unlock (&rp->
mutex);
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
void svm_region_init_chroot_uid_gid(const char *root_path, int uid, int gid)
svm_region_t * svm_get_root_rp(void)
#define SVM_GLOBAL_REGION_NAME
static void svm_pop_heap(void *oldheap)
#define vec_c_string_is_terminated(V)
Test whether a vector is a NULL terminated c-string.
#define SVM_FLAGS_NEED_DATA_INIT
void * svm_map_region(svm_map_region_args_t *a)
#define count_leading_zeros(x)
Optimized string handling code, including c11-compliant "safe C library" variants.
Fixed length block allocator.
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
static u64 clib_cpu_time_now(void)
void svm_client_scan(const char *root_path)
#define SVM_PVT_MHEAP_SIZE
static mheap_t * mheap_header(u8 *v)
void svm_region_unmap_client(void *rp_arg)
#define hash_set_mem(h, key, value)
clib_memset(h->entries, 0, sizeof(h->entries[0])*entries)
void svm_region_exit_client(void)
#define MHEAP_FLAG_THREAD_SAFE
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
static u8 * format_svm_size(u8 *s, va_list *args)
static uword clib_bitmap_get_no_check(uword *ai, uword i)
Gets the ith bit value from a bitmap Does not sanity-check the bit position.
#define clib_unix_error(format, args...)
static uword clib_bitmap_set_no_check(uword *a, uword i, uword new_value)
Sets the ith bit of a bitmap to new_value.
DLMALLOC_EXPORT mspace create_mspace_with_base(void *base, size_t capacity, int locked)
void svm_region_exit(void)
void svm_region_init(void)
#define pool_foreach(VAR, POOL, BODY)
Iterate through pool.
#define MHEAP_FLAG_DISABLE_VM
void * svm_region_find_or_create(svm_map_region_args_t *a)
static u64 rnd_pagesize(u64 size)
u8 * format_svm_region(u8 *s, va_list *args)
#define hash_create_string(elts, value_bytes)
u8 * format_mheap(u8 *s, va_list *va)
static int svm_region_init_internal(svm_map_region_args_t *a)
#define hash_unset_mem(h, key)
DLMALLOC_EXPORT void mspace_disable_expand(mspace msp)
#define pool_put(P, E)
Free an object E in pool P.
#define vec_dup(V)
Return copy of vector (no header, no alignment)
svm_subregion_t * subregions
void svm_region_init_args(svm_map_region_args_t *a)
#define SVM_GLOBAL_REGION_SIZE
void svm_region_init_mapped_region(svm_map_region_args_t *a, svm_region_t *rp)
static void * svm_push_pvt_heap(svm_region_t *rp)
static int root_rp_refcount
#define vec_free(V)
Free vector's memory (no header).
#define clib_warning(format, args...)
static pthread_mutex_t * mutexes_held[MAXLOCK]
u8 * shm_name_from_svm_map_region_args(svm_map_region_args_t *a)
static int svm_data_region_map(svm_map_region_args_t *a, svm_region_t *rp)
void * mheap_alloc_with_flags(void *memory, uword memory_size, uword flags)
#define uword_to_pointer(u, type)
#define vec_delete(V, N, M)
Delete N elements starting at element M.
static void region_lock(svm_region_t *rp, int tag)
u64 svm_get_global_region_base_va()
Bitmaps built as vectors of machine words.
static void region_unlock(svm_region_t *rp)
void svm_region_unmap_internal(void *rp_arg, u8 is_client)
static heap_header_t * heap_header(void *v)
void svm_region_unlink(svm_region_t *rp)
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define clib_unix_warning(format, args...)
void svm_region_unmap(void *rp_arg)
void svm_client_scan_this_region_nolock(svm_region_t *rp)
#define hash_get_mem(h, key)
#define CLIB_MEMORY_BARRIER()
static int svm_data_region_create(svm_map_region_args_t *a, svm_region_t *rp)
static u8 * format_svm_flags(u8 *s, va_list *args)
static void svm_mutex_cleanup(void)
CLIB vectors are ubiquitous dynamically resized arrays with by user defined "headers".
static svm_region_t * root_rp
int svm_region_init_chroot(const char *root_path)
static void svm_region_exit_internal(u8 is_client)