static uint64_t get_default_hp_size(void) { const char proc_meminfo[] = "/proc/meminfo"; const char str_hugepagesz[] = "Hugepagesize:"; unsigned int hugepagesz_len = sizeof(str_hugepagesz) - 1; char buffer[256]; unsigned long long size = 0; FILE *fd = fopen(proc_meminfo, "r"); if (!fd) ODP_PRINT("Cannot open %s\n", proc_meminfo); while (fgets(buffer, sizeof(buffer), fd)) if (strncmp(buffer, str_hugepagesz, hugepagesz_len) == 0) { size = odp_str_to_size(&buffer[hugepagesz_len]); break; } fclose(fd); if (size == 0) ODP_PRINT("Cannot get default hugepage " "size from %s\n", proc_meminfo); return size; }
/* create the ring */ struct odp_ring *odp_ring_create(const char *name, unsigned count, int socket_id, unsigned flags) { char mz_name[ODP_MEMZONE_NAMESIZE]; struct odp_ring *r; struct odp_tailq_entry *te; const struct odp_mm_district *mz; ssize_t ring_size; int mz_flags = 0; struct odp_ring_list *ring_list = NULL; ring_list = ODP_TAILQ_CAST(odp_ring_tailq.head, odp_ring_list); ring_size = odp_ring_get_memsize(count); if (ring_size < 0) { odp_err = ring_size; return NULL; } te = malloc(sizeof(*te)); if (te == NULL) { ODP_PRINT("Cannot reserve memory for tailq\n"); odp_err = ENOMEM; return NULL; } snprintf(mz_name, sizeof(mz_name), "%s%s", ODP_RING_MZ_PREFIX, name); odp_rwlock_write_lock(ODP_TAILQ_RWLOCK); /* reserve a memory zone for this ring. If we can't get odp_config or * we are secondary process, the mm_district_reserve function will set * odp_err for us appropriately-hence no check in this this function */ mz = odp_mm_district_reserve(mz_name, mz_name, ring_size, socket_id, mz_flags); if (mz != NULL) { r = mz->addr; /* no need to check return value here, we already checked the * arguments above */ odp_ring_init(r, name, count, flags); te->data = (void *)r; TAILQ_INSERT_TAIL(ring_list, te, next); } else { r = NULL; ODP_PRINT("Cannot reserve memory\n"); free(te); } odp_rwlock_write_unlock(ODP_TAILQ_RWLOCK); return r; }
void odp_shm_print_all(void) { int i; ODP_PRINT("\nShared memory\n"); ODP_PRINT("--------------\n"); ODP_PRINT(" page size: %" PRIu64 " kB\n", odp_sys_page_size() / 1024); ODP_PRINT(" huge page size: %" PRIu64 " kB\n", odp_sys_huge_page_size() / 1024); ODP_PRINT("\n"); ODP_PRINT(" id name kB align huge addr\n"); for (i = 0; i < ODP_CONFIG_SHM_BLOCKS; i++) { odp_shm_block_t *block; block = &odp_shm_tbl->block[i]; if (block->addr) ODP_PRINT(" %2i %-24s %4" PRIu64 " %4" PRIu64 " %2c %p\n", i, block->name, block->size / 1024, block->align, (block->huge ? '*' : ' '), block->addr); } ODP_PRINT("\n"); }
int odp_buffer_snprint(char *str, uint32_t n, odp_buffer_t buf) { odp_buffer_hdr_t *hdr; int len = 0; if (!odp_buffer_is_valid(buf)) { ODP_PRINT("Buffer is not valid.\n"); return len; } hdr = odp_buf_to_hdr(buf); len += snprintf(&str[len], n-len, "Buffer\n"); len += snprintf(&str[len], n-len, " pool %" PRIu64 "\n", odp_pool_to_u64(hdr->pool_hdl)); len += snprintf(&str[len], n-len, " addr %p\n", hdr->addr); len += snprintf(&str[len], n-len, " size %" PRIu32 "\n", hdr->size); len += snprintf(&str[len], n-len, " ref_count %" PRIu32 "\n", odp_atomic_load_u32(&hdr->ref_count)); len += snprintf(&str[len], n-len, " type %i\n", hdr->type); return len; }
static int get_num_hugepages(const char *subdir) { char path[ODP_PATH_MAX]; unsigned long resv_pages, num_pages = 0; const char *nr_hp_file; /* first, check how many reserved pages kernel reports */ snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, "resv_hugepages"); resv_pages = odp_parse_sysfs_value(path); if (resv_pages < 0) return 0; /* if secondary process, just look at the number of hugepages, * otherwise look at number of free hugepages */ if (local_config.process_type == ODP_PROC_SECONDARY) nr_hp_file = "nr_hugepages"; else nr_hp_file = "free_hugepages"; snprintf(path, sizeof(path), "%s/%s/%s", sys_dir_path, subdir, nr_hp_file); num_pages = odp_parse_sysfs_value(path); if (num_pages < 0) return 0; if (num_pages == 0) ODP_PRINT("No free hugepages repohodpd in %s\n", subdir); /* adjust num_pages in case of primary process */ if ((num_pages > 0) && (local_config.process_type == ODP_PROC_PRIMARY)) num_pages -= resv_pages; return (int)num_pages; }
void odp_buffer_print(odp_buffer_t buf) { int max_len = 512; char str[max_len]; int len; len = odp_buffer_snprint(str, max_len-1, buf); str[len] = 0; ODP_PRINT("\n%s\n", str); }
/* return the size of memory occupied by a ring */ ssize_t odp_ring_get_memsize(unsigned count) { ssize_t sz; /* count must be a power of 2 */ if ((!POWEROF2(count)) || (count > ODP_RING_SZ_MASK)) { ODP_PRINT("Requested size is invalid, must be power of 2, and " "do not exceed the size limit %u\n", ODP_RING_SZ_MASK); return -EINVAL; } sz = sizeof(struct odp_ring) + count * sizeof(void *); sz = ODP_ALIGN(sz, ODP_CACHE_LINE_SIZE); return sz; }
int odp_hugepage_info_init(void) { unsigned i, num_sizes = 0; struct dirent *dirent = NULL; DIR *dir = NULL; struct odp_hugepage_type *hpt = NULL; dir = opendir(sys_dir_path); if (!dir) ODP_PRINT("Cannot open directory %s to " "read system hugepage info\n", sys_dir_path); dirent = readdir(dir); /* loop get different kinds of hugepages in * the system hugepage directory */ while (dirent) { if (strncmp(dirent->d_name, "hugepages-", ODP_SYS_HGPG_STR_LEN) == 0) { hpt = &local_config.odp_hugepage_type[num_sizes]; hpt->hugepage_sz = odp_str_to_size(&dirent->d_name[ ODP_SYS_HGPG_STR_LEN]); hpt->hugedir = get_hugepage_dir(hpt->hugepage_sz); /* first, check if we have a mountpoint */ if (!hpt->hugedir) { int32_t num_pages; num_pages = get_num_hugepages(dirent->d_name); if (num_pages > 0) { ODP_PRINT("%d hugepages of" " size %lu reserved, ", num_pages, hpt->hugepage_sz); ODP_PRINT("but no mounted hugetlbfs" " found for that size\n"); } } else { /* try to obtain a writelock */ hpt->lock_descriptor = open(hpt->hugedir, O_RDONLY); /* if blocking lock failed */ if (flock(hpt->lock_descriptor, LOCK_EX) == -1) { ODP_ERR("Failed to lock hugepage" " directory!\n"); closedir(dir); return -1; } /* clear out the hugepages * dir from unused pages */ if (clear_hugedir(hpt->hugedir) == -1) { closedir(dir); return -1; } /* for now, put all pages into socket 0, * later they will be sohodpd */ hpt->num_pages[0] = get_num_hugepages(dirent->d_name); hpt->num_pages[0] = ODP_MIN(hpt->num_pages[0], ODP_PAGE_MEMORY_MAX / hpt->hugepage_sz); num_sizes++; } } dirent = readdir(dir); } closedir(dir); local_config.num_hugepage_types = num_sizes; /* sort the page directory entries by size, largest to smallest */ for (i = 0; i < num_sizes; i++) { unsigned int j; for (j = i + 1; j < num_sizes; j++) if (local_config.odp_hugepage_type[j - 1].hugepage_sz < local_config.odp_hugepage_type[j].hugepage_sz) swap_hpt( &local_config.odp_hugepage_type[j - 1], &local_config.odp_hugepage_type[j]); } /* now we have all info, check we have at least one valid size */ for (i = 0; i < num_sizes; i++) if (local_config.odp_hugepage_type[i].hugedir && (local_config.odp_hugepage_type[i].num_pages[0] > 0)) return 0; /* no valid hugepage mounts available, return error */ return -1; }
/* * Clear the hugepage directory of whatever hugepage files * there are. Checks if the file is locked (i.e. * if it's in use by another ODP process). */ static int clear_hugedir(const char *hugedir) { DIR *dir; struct dirent *dirent; int dir_fd, fd, lck_result; const char filter[] = "*map_*"; /* matches hugepage files */ /* open directory */ dir = opendir(hugedir); if (!dir) { ODP_PRINT("Unable to open hugepage directory %s\n", hugedir); goto error; } dir_fd = dirfd(dir); dirent = readdir(dir); if (!dirent) { ODP_PRINT("Unable to read hugepage directory %s\n", hugedir); goto error; } while (dirent) { /* skip files that don't match the hugepage pattern */ if (fnmatch(filter, dirent->d_name, 0) > 0) { dirent = readdir(dir); continue; } /* try and lock the file */ fd = openat(dir_fd, dirent->d_name, O_RDONLY); /* skip to next file */ if (fd == -1) { dirent = readdir(dir); continue; } /* non-blocking lock */ lck_result = flock(fd, LOCK_EX | LOCK_NB); /* if lock succeeds, unlock and remove the file */ if (lck_result != -1) { flock(fd, LOCK_UN); unlinkat(dir_fd, dirent->d_name, 0); } close(fd); dirent = readdir(dir); } closedir(dir); return 0; error: if (dir) closedir(dir); ODP_PRINT("Error while clearing hugepage dir: %s\n", strerror(errno)); return -1; }
static const char *get_hugepage_dir(uint64_t hugepage_sz) { enum proc_mount_fieldnames { DEVICE = 0, MOUNTPT, FSTYPE, OPTIONS, _FIELDNAME_MAX }; static uint64_t default_size; const char split_tok = ' '; char *splitstr[_FIELDNAME_MAX]; char buf[ODP_BUFF_SIZE]; char *retval = NULL; FILE *fd = fopen("/proc/mounts", "r"); if (!fd) ODP_PRINT("Cannot open proc_mount\n"); if (default_size == 0) default_size = get_default_hp_size(); while (fgets(buf, sizeof(buf), fd)) { if (odp_strsplit(buf, sizeof(buf), splitstr, _FIELDNAME_MAX, split_tok) != _FIELDNAME_MAX) { ODP_PRINT("Error parsing proc_mount\n"); break; /* return NULL */ } if (strncmp(splitstr[FSTYPE], HUGETLBFS_DESC, HGTLB_DSC_LEN) == 0) { const char *pagesz_str = strstr(splitstr[OPTIONS], HUGEPAGE_SIZE_DESC); /* if no explicit page size, the * default page size is compared */ if (!pagesz_str) { if (hugepage_sz == default_size) { retval = strdup(splitstr[MOUNTPT]); break; } } /* there is an explicit page size, so check it */ else { uint64_t pagesz = odp_str_to_size( &pagesz_str[HP_DESC_LEN]); if (pagesz == hugepage_sz) { retval = strdup(splitstr[MOUNTPT]); break; } } } /* end if strncmp hugetlbfs */ } /* end while fgets */ fclose(fd); return retval; }