X-Git-Url: https://gerrit.fd.io/r/gitweb?a=blobdiff_plain;f=src%2Fvppinfra%2Flinux%2Fmem.c;h=3b752cf43cf57cc21a089f915923b3351cdc1f19;hb=6eb0f84e3;hp=8edae74f9cd5e023fca219b146b39719f5f70102;hpb=567e61d09cd00174203eff85f63a598420476951;p=vpp.git diff --git a/src/vppinfra/linux/mem.c b/src/vppinfra/linux/mem.c index 8edae74f9cd..3b752cf43cf 100644 --- a/src/vppinfra/linux/mem.c +++ b/src/vppinfra/linux/mem.c @@ -26,10 +26,10 @@ #include #include +#include #include #include #include -#include #include #ifndef F_LINUX_SPECIFIC_BASE @@ -46,42 +46,105 @@ #define F_SEAL_WRITE 0x0008 /* prevent writes */ #endif +#ifndef MFD_HUGETLB +#define MFD_HUGETLB 0x0004U +#endif -uword -clib_mem_get_page_size (void) +#ifndef MAP_HUGE_SHIFT +#define MAP_HUGE_SHIFT 26 +#endif + +#ifndef MFD_HUGE_SHIFT +#define MFD_HUGE_SHIFT 26 +#endif + +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE 0x100000 +#endif + +static void +map_lock () { - return getpagesize (); + while (clib_atomic_test_and_set (&clib_mem_main.map_lock)) + CLIB_PAUSE (); } -uword -clib_mem_get_default_hugepage_size (void) +static void +map_unlock () +{ + clib_atomic_release (&clib_mem_main.map_lock); +} + +static clib_mem_page_sz_t +legacy_get_log2_default_hugepage_size (void) +{ + clib_mem_page_sz_t log2_page_size = CLIB_MEM_PAGE_SZ_UNKNOWN; + FILE *fp; + char tmp[33] = { }; + + if ((fp = fopen ("/proc/meminfo", "r")) == NULL) + return CLIB_MEM_PAGE_SZ_UNKNOWN; + + while (fscanf (fp, "%32s", tmp) > 0) + if (strncmp ("Hugepagesize:", tmp, 13) == 0) + { + u32 size; + if (fscanf (fp, "%u", &size) > 0) + log2_page_size = 10 + min_log2 (size); + break; + } + + fclose (fp); + return log2_page_size; +} + +void +clib_mem_main_init () { - unformat_input_t input; - static u32 size = 0; + clib_mem_main_t *mm = &clib_mem_main; + uword page_size; + void *va; int fd; - if (size) - goto done; + if (mm->log2_page_sz != CLIB_MEM_PAGE_SZ_UNKNOWN) + return; - if ((fd = open ("/proc/meminfo", 0)) == -1) - return 0; + /* system page size */ + page_size = sysconf (_SC_PAGESIZE); + mm->log2_page_sz = min_log2 (page_size); + + /* default system hugeppage size */ + if ((fd = syscall (__NR_memfd_create, "test", MFD_HUGETLB)) != -1) + { + mm->log2_default_hugepage_sz = clib_mem_get_fd_log2_page_size (fd); + close (fd); + } + else /* likely kernel older than 4.14 */ + mm->log2_default_hugepage_sz = legacy_get_log2_default_hugepage_size (); - unformat_init_clib_file (&input, fd); + mm->log2_sys_default_hugepage_sz = mm->log2_default_hugepage_sz; - while (unformat_check_input (&input) != UNFORMAT_END_OF_INPUT) + /* numa nodes */ + va = mmap (0, page_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | + MAP_ANONYMOUS, -1, 0); + if (va == MAP_FAILED) + return; + + if (mlock (va, page_size)) + goto done; + + for (int i = 0; i < CLIB_MAX_NUMAS; i++) { - if (unformat (&input, "Hugepagesize:%_%u kB", &size)) - ; - else - unformat_skip_line (&input); + int status; + if (syscall (__NR_move_pages, 0, 1, &va, &i, &status, 0) == 0) + mm->numa_node_bitmap |= 1ULL << i; } - unformat_free (&input); - close (fd); + done: - return 1024ULL * size; + munmap (va, page_size); } -u64 +__clib_export u64 clib_mem_get_fd_page_size (int fd) { struct stat st = { 0 }; @@ -90,14 +153,16 @@ clib_mem_get_fd_page_size (int fd) return st.st_blksize; } -int +__clib_export clib_mem_page_sz_t clib_mem_get_fd_log2_page_size (int fd) { - return min_log2 (clib_mem_get_fd_page_size (fd)); + uword page_size = clib_mem_get_fd_page_size (fd); + return page_size ? min_log2 (page_size) : CLIB_MEM_PAGE_SZ_UNKNOWN; } -void -clib_mem_vm_randomize_va (uword * requested_va, u32 log2_page_size) +__clib_export void +clib_mem_vm_randomize_va (uword * requested_va, + clib_mem_page_sz_t log2_page_size) { u8 bit_mask = 15; @@ -112,239 +177,402 @@ clib_mem_vm_randomize_va (uword * requested_va, u32 log2_page_size) (clib_cpu_time_now () & bit_mask) * (1ull << log2_page_size); } -#ifndef MFD_HUGETLB -#define MFD_HUGETLB 0x0004U -#endif - -clib_error_t * -clib_mem_create_fd (char *name, int *fdp) +static int +legacy_memfd_create (u8 * name) { - int fd; + clib_mem_main_t *mm = &clib_mem_main; + int fd = -1; + char *mount_dir; + u8 *temp; + u8 *filename; + + /* + * Since mkdtemp will modify template string "/tmp/hugepage_mount.XXXXXX", + * it must not be a string constant, but should be declared as + * a character array. + */ + temp = format (0, "/tmp/hugepage_mount.XXXXXX%c", 0); - ASSERT (name); + /* create mount directory */ + if ((mount_dir = mkdtemp ((char *) temp)) == 0) + { + vec_free (temp); + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, "mkdtemp"); + return CLIB_MEM_ERROR; + } + + if (mount ("none", mount_dir, "hugetlbfs", 0, NULL)) + { + vec_free (temp); + rmdir ((char *) mount_dir); + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, "mount"); + return CLIB_MEM_ERROR; + } - if ((fd = memfd_create (name, MFD_ALLOW_SEALING)) == -1) - return clib_error_return_unix (0, "memfd_create"); + filename = format (0, "%s/%s%c", mount_dir, name, 0); - if ((fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1) + if ((fd = open ((char *) filename, O_CREAT | O_RDWR, 0755)) == -1) { - close (fd); - return clib_error_return_unix (0, "fcntl (F_ADD_SEALS)"); + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, "mkdtemp"); } - *fdp = fd; - return 0; + umount2 ((char *) mount_dir, MNT_DETACH); + rmdir ((char *) mount_dir); + vec_free (filename); + vec_free (temp); + + return fd; } -clib_error_t * -clib_mem_create_hugetlb_fd (char *name, int *fdp) +__clib_export int +clib_mem_vm_create_fd (clib_mem_page_sz_t log2_page_size, char *fmt, ...) { - clib_error_t *err = 0; - int fd = -1; - static int memfd_hugetlb_supported = 1; - char *mount_dir; - char template[] = "/tmp/hugepage_mount.XXXXXX"; - u8 *filename; + clib_mem_main_t *mm = &clib_mem_main; + int fd; + unsigned int memfd_flags; + va_list va; + u8 *s = 0; - ASSERT (name); + if (log2_page_size == mm->log2_page_sz) + log2_page_size = CLIB_MEM_PAGE_SZ_DEFAULT; + else if (log2_page_size == mm->log2_sys_default_hugepage_sz) + log2_page_size = CLIB_MEM_PAGE_SZ_DEFAULT_HUGE; - if (memfd_hugetlb_supported) + switch (log2_page_size) { - if ((fd = memfd_create (name, MFD_HUGETLB)) != -1) - goto done; - - /* avoid further tries if memfd MFD_HUGETLB is not supported */ - if (errno == EINVAL && strnlen (name, 256) <= 249) - memfd_hugetlb_supported = 0; + case CLIB_MEM_PAGE_SZ_UNKNOWN: + return CLIB_MEM_ERROR; + case CLIB_MEM_PAGE_SZ_DEFAULT: + memfd_flags = MFD_ALLOW_SEALING; + break; + case CLIB_MEM_PAGE_SZ_DEFAULT_HUGE: + memfd_flags = MFD_HUGETLB; + break; + default: + memfd_flags = MFD_HUGETLB | log2_page_size << MFD_HUGE_SHIFT; } - mount_dir = mkdtemp (template); - if (mount_dir == 0) - return clib_error_return_unix (0, "mkdtemp \'%s\'", template); + va_start (va, fmt); + s = va_format (0, fmt, &va); + va_end (va); + + /* memfd_create maximum string size is 249 chars without trailing zero */ + if (vec_len (s) > 249) + _vec_len (s) = 249; + vec_add1 (s, 0); + + /* memfd_create introduced in kernel 3.17, we don't support older kernels */ + fd = syscall (__NR_memfd_create, (char *) s, memfd_flags); - if (mount ("none", (char *) mount_dir, "hugetlbfs", 0, NULL)) + /* kernel versions < 4.14 does not support memfd_create for huge pages */ + if (fd == -1 && errno == EINVAL && + log2_page_size == CLIB_MEM_PAGE_SZ_DEFAULT_HUGE) { - rmdir ((char *) mount_dir); - err = clib_error_return_unix (0, "mount hugetlb directory '%s'", - mount_dir); + fd = legacy_memfd_create (s); + } + else if (fd == -1) + { + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, "memfd_create"); + vec_free (s); + return CLIB_MEM_ERROR; } - filename = format (0, "%s/%s%c", mount_dir, name, 0); - fd = open ((char *) filename, O_CREAT | O_RDWR, 0755); - umount2 ((char *) mount_dir, MNT_DETACH); - rmdir ((char *) mount_dir); + vec_free (s); - if (fd == -1) - err = clib_error_return_unix (0, "open"); + if ((memfd_flags & MFD_ALLOW_SEALING) && + ((fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK)) == -1)) + { + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, "fcntl (F_ADD_SEALS)"); + close (fd); + return CLIB_MEM_ERROR; + } -done: - if (fd != -1) - fdp[0] = fd; - return err; + return fd; } -clib_error_t * -clib_mem_vm_ext_alloc (clib_mem_vm_alloc_t * a) +uword +clib_mem_vm_reserve (uword start, uword size, clib_mem_page_sz_t log2_page_sz) { - int fd = -1; - clib_error_t *err = 0; - void *addr = 0; - u8 *filename = 0; - int mmap_flags = 0; - int log2_page_size; - int n_pages; - int old_mpol = -1; - long unsigned int old_mask[16] = { 0 }; - - /* save old numa mem policy if needed */ - if (a->flags & (CLIB_MEM_VM_F_NUMA_PREFER | CLIB_MEM_VM_F_NUMA_FORCE)) - { - int rv; - rv = get_mempolicy (&old_mpol, old_mask, sizeof (old_mask) * 8 + 1, - 0, 0); + clib_mem_main_t *mm = &clib_mem_main; + uword pagesize = 1ULL << log2_page_sz; + uword sys_page_sz = 1ULL << mm->log2_page_sz; + uword n_bytes; + void *base = 0, *p; - if (rv == -1) - { - if (a->numa_node != 0 && (a->flags & CLIB_MEM_VM_F_NUMA_FORCE) != 0) - { - err = clib_error_return_unix (0, "get_mempolicy"); - goto error; - } - else - old_mpol = -1; - } + size = round_pow2 (size, pagesize); + + /* in adition of requested reservation, we also rserve one system page + * (typically 4K) adjacent to the start off reservation */ + + if (start) + { + /* start address is provided, so we just need to make sure we are not + * replacing existing map */ + if (start & pow2_mask (log2_page_sz)) + return ~0; + + base = (void *) start - sys_page_sz; + base = mmap (base, size + sys_page_sz, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED_NOREPLACE, -1, 0); + return (base == MAP_FAILED) ? ~0 : start; } - if (a->flags & CLIB_MEM_VM_F_LOCKED) - mmap_flags |= MAP_LOCKED; + /* to make sure that we get reservation aligned to page_size we need to + * request one additional page as mmap will return us address which is + * aligned only to system page size */ + base = mmap (0, size + pagesize, PROT_NONE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - /* if we are creating shared segment, we need file descriptor */ - if (a->flags & CLIB_MEM_VM_F_SHARED) + if (base == MAP_FAILED) + return ~0; + + /* return additional space at the end of allocation */ + p = base + size + pagesize; + n_bytes = (uword) p & pow2_mask (log2_page_sz); + if (n_bytes) { - mmap_flags |= MAP_SHARED; - /* if hugepages are needed we need to create mount point */ - if (a->flags & CLIB_MEM_VM_F_HUGETLB) - { - if ((err = clib_mem_create_hugetlb_fd (a->name, &fd))) - goto error; + p -= n_bytes; + munmap (p, n_bytes); + } - mmap_flags |= MAP_LOCKED; - } - else - { - if ((err = clib_mem_create_fd (a->name, &fd))) - goto error; - } + /* return additional space at the start of allocation */ + n_bytes = pagesize - sys_page_sz - n_bytes; + if (n_bytes) + { + munmap (base, n_bytes); + base += n_bytes; + } - log2_page_size = clib_mem_get_fd_log2_page_size (fd); - if (log2_page_size == 0) - { - err = clib_error_return_unix (0, "cannot determine page size"); - goto error; - } + return (uword) base + sys_page_sz; +} - if (a->requested_va) - { - clib_mem_vm_randomize_va (&a->requested_va, log2_page_size); - mmap_flags |= MAP_FIXED; - } +__clib_export clib_mem_vm_map_hdr_t * +clib_mem_vm_get_next_map_hdr (clib_mem_vm_map_hdr_t * hdr) +{ + clib_mem_main_t *mm = &clib_mem_main; + uword sys_page_sz = 1ULL << mm->log2_page_sz; + clib_mem_vm_map_hdr_t *next; + if (hdr == 0) + { + hdr = mm->first_map; + if (hdr) + mprotect (hdr, sys_page_sz, PROT_READ); + return hdr; } - else /* not CLIB_MEM_VM_F_SHARED */ + next = hdr->next; + mprotect (hdr, sys_page_sz, PROT_NONE); + if (next) + mprotect (next, sys_page_sz, PROT_READ); + return next; +} + +void * +clib_mem_vm_map_internal (void *base, clib_mem_page_sz_t log2_page_sz, + uword size, int fd, uword offset, char *name) +{ + clib_mem_main_t *mm = &clib_mem_main; + clib_mem_vm_map_hdr_t *hdr; + uword sys_page_sz = 1ULL << mm->log2_page_sz; + int mmap_flags = MAP_FIXED, is_huge = 0; + + if (fd != -1) + { + mmap_flags |= MAP_SHARED; + log2_page_sz = clib_mem_get_fd_log2_page_size (fd); + if (log2_page_sz > mm->log2_page_sz) + is_huge = 1; + } + else { mmap_flags |= MAP_PRIVATE | MAP_ANONYMOUS; - if (a->flags & CLIB_MEM_VM_F_HUGETLB) + + if (log2_page_sz == mm->log2_page_sz) + log2_page_sz = CLIB_MEM_PAGE_SZ_DEFAULT; + + switch (log2_page_sz) { + case CLIB_MEM_PAGE_SZ_UNKNOWN: + /* will fail later */ + break; + case CLIB_MEM_PAGE_SZ_DEFAULT: + log2_page_sz = mm->log2_page_sz; + break; + case CLIB_MEM_PAGE_SZ_DEFAULT_HUGE: mmap_flags |= MAP_HUGETLB; - log2_page_size = 21; - } - else - { - log2_page_size = min_log2 (sysconf (_SC_PAGESIZE)); + log2_page_sz = mm->log2_default_hugepage_sz; + is_huge = 1; + break; + default: + mmap_flags |= MAP_HUGETLB; + mmap_flags |= log2_page_sz << MAP_HUGE_SHIFT; + is_huge = 1; } } - n_pages = ((a->size - 1) >> log2_page_size) + 1; + if (log2_page_sz == CLIB_MEM_PAGE_SZ_UNKNOWN) + return CLIB_MEM_VM_MAP_FAILED; + + size = round_pow2 (size, 1ULL << log2_page_sz); + + base = (void *) clib_mem_vm_reserve ((uword) base, size, log2_page_sz); - if (a->flags & CLIB_MEM_VM_F_HUGETLB_PREALLOC) + if (base == (void *) ~0) + return CLIB_MEM_VM_MAP_FAILED; + + base = mmap (base, size, PROT_READ | PROT_WRITE, mmap_flags, fd, offset); + + if (base == MAP_FAILED) + return CLIB_MEM_VM_MAP_FAILED; + + if (is_huge && (mlock (base, size) != 0)) { - err = clib_sysfs_prealloc_hugepages (a->numa_node, log2_page_size, - n_pages); - if (err) - goto error; + munmap (base, size); + return CLIB_MEM_VM_MAP_FAILED; + } + + hdr = mmap (base - sys_page_sz, sys_page_sz, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0); + if (hdr != base - sys_page_sz) + { + munmap (base, size); + return CLIB_MEM_VM_MAP_FAILED; } - if (fd != -1) - if ((ftruncate (fd, (u64) n_pages * (1 << log2_page_size))) == -1) - { - err = clib_error_return_unix (0, "ftruncate"); - goto error; - } + map_lock (); - if (old_mpol != -1) + if (mm->last_map) { - int rv; - long unsigned int mask[16] = { 0 }; - mask[0] = 1 << a->numa_node; - rv = set_mempolicy (MPOL_BIND, mask, sizeof (mask) * 8 + 1); - if (rv == -1 && a->numa_node != 0 && - (a->flags & CLIB_MEM_VM_F_NUMA_FORCE) != 0) - { - err = clib_error_return_unix (0, "set_mempolicy"); - goto error; - } + mprotect (mm->last_map, sys_page_sz, PROT_READ | PROT_WRITE); + mm->last_map->next = hdr; + mprotect (mm->last_map, sys_page_sz, PROT_NONE); } + else + mm->first_map = hdr; + + CLIB_MEM_UNPOISON (hdr, sys_page_sz); + hdr->next = 0; + hdr->prev = mm->last_map; + snprintf (hdr->name, CLIB_VM_MAP_HDR_NAME_MAX_LEN - 1, "%s", (char *) name); + mm->last_map = hdr; + + map_unlock (); - addr = mmap (uword_to_pointer (a->requested_va, void *), a->size, - (PROT_READ | PROT_WRITE), mmap_flags, fd, 0); - if (addr == MAP_FAILED) + hdr->base_addr = (uword) base; + hdr->log2_page_sz = log2_page_sz; + hdr->num_pages = size >> log2_page_sz; + hdr->fd = fd; + hdr->name[CLIB_VM_MAP_HDR_NAME_MAX_LEN - 1] = 0; + mprotect (hdr, sys_page_sz, PROT_NONE); + + CLIB_MEM_UNPOISON (base, size); + return base; +} + +__clib_export int +clib_mem_vm_unmap (void *base) +{ + clib_mem_main_t *mm = &clib_mem_main; + uword size, sys_page_sz = 1ULL << mm->log2_page_sz; + clib_mem_vm_map_hdr_t *hdr = base - sys_page_sz;; + + map_lock (); + if (mprotect (hdr, sys_page_sz, PROT_READ | PROT_WRITE) != 0) + goto out; + + size = hdr->num_pages << hdr->log2_page_sz; + if (munmap ((void *) hdr->base_addr, size) != 0) + goto out; + + if (hdr->next) { - err = clib_error_return_unix (0, "mmap"); - goto error; + mprotect (hdr->next, sys_page_sz, PROT_READ | PROT_WRITE); + hdr->next->prev = hdr->prev; + mprotect (hdr->next, sys_page_sz, PROT_NONE); } + else + mm->last_map = hdr->prev; - /* re-apply old numa memory policy */ - if (old_mpol != -1 && - set_mempolicy (old_mpol, old_mask, sizeof (old_mask) * 8 + 1) == -1) + if (hdr->prev) { - err = clib_error_return_unix (0, "set_mempolicy"); - goto error; + mprotect (hdr->prev, sys_page_sz, PROT_READ | PROT_WRITE); + hdr->prev->next = hdr->next; + mprotect (hdr->prev, sys_page_sz, PROT_NONE); } + else + mm->first_map = hdr->next; - a->log2_page_size = log2_page_size; - a->n_pages = n_pages; - a->addr = addr; - a->fd = fd; - goto done; + map_unlock (); -error: - if (fd != -1) - close (fd); + if (munmap (hdr, sys_page_sz) != 0) + return CLIB_MEM_ERROR; -done: - vec_free (filename); - return err; + return 0; +out: + map_unlock (); + return CLIB_MEM_ERROR; } -void -clib_mem_vm_ext_free (clib_mem_vm_alloc_t * a) +__clib_export void +clib_mem_get_page_stats (void *start, clib_mem_page_sz_t log2_page_size, + uword n_pages, clib_mem_page_stats_t * stats) { - if (a != 0) + int i, *status = 0; + void **ptr = 0; + + log2_page_size = clib_mem_log2_page_size_validate (log2_page_size); + + vec_validate (status, n_pages - 1); + vec_validate (ptr, n_pages - 1); + + for (i = 0; i < n_pages; i++) + ptr[i] = start + (i << log2_page_size); + + clib_memset (stats, 0, sizeof (clib_mem_page_stats_t)); + stats->total = n_pages; + stats->log2_page_sz = log2_page_size; + + if (syscall (__NR_move_pages, 0, n_pages, ptr, 0, status, 0) != 0) + { + stats->unknown = n_pages; + goto done; + } + + for (i = 0; i < n_pages; i++) { - clib_mem_vm_free (a->addr, 1ull << a->log2_page_size); - if (a->fd != -1) - close (a->fd); + if (status[i] >= 0 && status[i] < CLIB_MAX_NUMAS) + { + stats->mapped++; + stats->per_numa[status[i]]++; + } + else if (status[i] == -EFAULT) + stats->not_mapped++; + else + stats->unknown++; } + +done: + vec_free (status); + vec_free (ptr); } -u64 * -clib_mem_vm_get_paddr (void *mem, int log2_page_size, int n_pages) + +__clib_export u64 * +clib_mem_vm_get_paddr (void *mem, clib_mem_page_sz_t log2_page_size, + int n_pages) { int pagesize = sysconf (_SC_PAGESIZE); int fd; int i; u64 *r = 0; + log2_page_size = clib_mem_log2_page_size_validate (log2_page_size); + if ((fd = open ((char *) "/proc/self/pagemap", O_RDONLY)) == -1) return 0; @@ -376,22 +604,53 @@ done: return r; } -clib_error_t * -clib_mem_vm_ext_map (clib_mem_vm_map_t * a) +__clib_export int +clib_mem_set_numa_affinity (u8 numa_node, int force) { - int mmap_flags = MAP_SHARED; - void *addr; + clib_mem_main_t *mm = &clib_mem_main; + long unsigned int mask[16] = { 0 }; + int mask_len = sizeof (mask) * 8 + 1; + + /* no numa support */ + if (mm->numa_node_bitmap == 0) + { + if (numa_node) + { + vec_reset_length (mm->error); + mm->error = clib_error_return (mm->error, "%s: numa not supported", + (char *) __func__); + return CLIB_MEM_ERROR; + } + else + return 0; + } - if (a->requested_va) - mmap_flags |= MAP_FIXED; + mask[0] = 1 << numa_node; - addr = (void *) mmap (uword_to_pointer (a->requested_va, void *), a->size, - PROT_READ | PROT_WRITE, mmap_flags, a->fd, 0); + if (syscall (__NR_set_mempolicy, force ? MPOL_BIND : MPOL_PREFERRED, mask, + mask_len)) + goto error; - if (addr == MAP_FAILED) - return clib_error_return_unix (0, "mmap"); + vec_reset_length (mm->error); + return 0; - a->addr = addr; +error: + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, (char *) __func__); + return CLIB_MEM_ERROR; +} + +__clib_export int +clib_mem_set_default_numa_affinity () +{ + clib_mem_main_t *mm = &clib_mem_main; + + if (syscall (__NR_set_mempolicy, MPOL_DEFAULT, 0, 0)) + { + vec_reset_length (mm->error); + mm->error = clib_error_return_unix (mm->error, (char *) __func__); + return CLIB_MEM_ERROR; + } return 0; }