static int metal_add_page_size(const char *path, int shift, int mmap_flags) { int index = _metal.num_page_sizes; unsigned long size = 1UL << shift; if (index >= MAX_PAGE_SIZES) { metal_log(METAL_LOG_WARNING, "skipped page size %ld - overflow\n", size); return -EOVERFLOW; } if (!path || shift <= 0) { metal_log(METAL_LOG_WARNING, "skipped page size %ld - invalid args\n", size); return -EINVAL; } _metal.page_sizes[index].page_shift = shift; _metal.page_sizes[index].page_size = size; _metal.page_sizes[index].mmap_flags = mmap_flags; strncpy(_metal.page_sizes[index].path, path, PATH_MAX); _metal.num_page_sizes ++; metal_log(METAL_LOG_DEBUG, "added page size %ld @%s\n", size, path); return 0; }
int metal_sys_init(const struct metal_init_params *params) { static char sysfs_path[SYSFS_PATH_MAX]; const char *tmp_path; unsigned int seed; FILE* urandom; int result; /* Determine sysfs mount point. */ result = sysfs_get_mnt_path(sysfs_path, sizeof(sysfs_path)); if (result) { metal_log(METAL_LOG_ERROR, "failed to get sysfs path (%s)\n", strerror(-result)); return result; } _metal.sysfs_path = sysfs_path; /* Find the temporary directory location. */ tmp_path = getenv("TMPDIR"); if (!tmp_path) tmp_path = "/tmp"; _metal.tmp_path = tmp_path; /* Initialize the pseudo-random number generator. */ urandom = fopen("/dev/urandom", "r"); if (!urandom) { metal_log(METAL_LOG_ERROR, "failed to open /dev/urandom (%s)\n", strerror(errno)); return -errno; } if (sizeof(int) != fread(&seed, sizeof(int), 1, urandom)) { metal_log(METAL_LOG_DEBUG, "Failed fread /dev/urandom\n"); } fclose(urandom); srand(seed); result = metal_init_page_sizes(); if (result < 0) return result; result = metal_linux_bus_init(); if (result < 0) return result; result = open("/proc/self/pagemap", O_RDONLY | O_CLOEXEC); if (result < 0) { metal_log(METAL_LOG_DEBUG, "Failed pagemap open - %s\n", strerror(errno)); } _metal.pagemap_fd = result; metal_unused(params); /* Initialize IRQ handling */ metal_linux_irq_init(); return 0; }
void metal_finish_threads(int threads, void *tids) { int i; pthread_t *tid_p = (pthread_t *)tids; if (!tids) { metal_log(METAL_LOG_ERROR, "invalid argument, tids is NULL.\n"); return; } for (i = 0; i < threads; i++) (void)pthread_join(tid_p[i], NULL); }
static int metal_init_page_sizes(void) { const int max_sizes = MAX_PAGE_SIZES - 1; long sizes[max_sizes]; /* Determine system page size. */ sizes[0] = getpagesize(); if (sizes[0] <= 0) { metal_log(METAL_LOG_ERROR, "failed to get page size\n"); return -ENOSYS; } _metal.page_size = sizes[0]; _metal.page_shift = metal_log2(sizes[0]); metal_add_page_size(_metal.tmp_path, _metal.page_shift, 0); #ifdef HAVE_HUGETLBFS_H #ifndef MAP_HUGE_SHIFT /* System does not support multiple huge page sizes. */ sizes[0] = gethugepagesize(); if (sizes[0] > 0) { metal_add_page_size(hugetlbfs_find_path(), metal_log2(sizes[0]), MAP_HUGETLB); } #else if (gethugepagesize() >= 0) { int i, count; /* System supports multiple huge page sizes. */ count = gethugepagesizes(sizes, max_sizes); for (i = 0; i < count; i++) { int shift = metal_log2(sizes[i]); if ((shift & MAP_HUGE_MASK) != shift) continue; metal_add_page_size( hugetlbfs_find_path_for_size(sizes[i]), shift, (MAP_HUGETLB | (shift << MAP_HUGE_SHIFT))); } } #endif #endif /* Finally sort the resulting array by size. */ qsort(_metal.page_sizes, _metal.num_page_sizes, sizeof(struct metal_page_size), metal_pagesize_compare); return 0; }
int metal_run_noblock(int threads, metal_thread_t child, void *arg, void *tids, int *threads_out) { int i; TaskHandle_t *tid_p = (TaskHandle_t *)tids; BaseType_t stat = pdPASS; char tn[15]; thread_wrap_arg_t *wrap_p; if (!tids) { metal_log(METAL_LOG_ERROR, "invalid argument, tids is NULL.\n"); return -EINVAL; } for (i = 0; i < threads; i++) { snprintf(tn, metal_dim(tn), "%d", i); wrap_p = pvPortMalloc(sizeof(thread_wrap_arg_t)); if (!wrap_p) { metal_log(METAL_LOG_ERROR, "failed to allocate wrapper %d\n", i); break; } wrap_p->thread_func = child; wrap_p->arg = arg; stat = xTaskCreate(thread_wrapper, tn, TEST_THREAD_STACK_SIZE, wrap_p, 2, &tid_p[i]); if (stat != pdPASS) { metal_log(METAL_LOG_ERROR, "failed to create thread %d\n", i); vPortFree(wrap_p); break; } } *threads_out = i; return pdPASS == stat ? 0 : -ENOMEM; }
int metal_run_noblock(int threads, metal_thread_t child, void *arg, void *tids, int *threads_out) { int error, i; pthread_t *tid_p = (pthread_t *)tids; if (!tids) { metal_log(METAL_LOG_ERROR, "invalid arguement, tids is NULL.\n"); return -EINVAL; } error = 0; for (i = 0; i < threads; i++) { error = -pthread_create(&tid_p[i], NULL, child, arg); if (error) { metal_log(METAL_LOG_ERROR, "failed to create thread - %s\n", strerror(error)); break; } } *threads_out = i; return error; }
void metal_finish_threads(int threads, void *tids) { int i; TaskHandle_t *tid_p = (TaskHandle_t *)tids; if (!tids) { metal_log(METAL_LOG_ERROR, "invalid argument, tids is NULL.\n"); return; } for (i = 0; i < threads; i++) { eTaskState ts; do { taskYIELD(); ts=eTaskGetState(tid_p[i]); } while (ts != eDeleted); } }
static int atomic(void) { atomic_int counter = ATOMIC_VAR_INIT(0); int value, error=0, i; for (i = 0; i < atomic_test_count; i++) { atomic_fetch_add(&counter, 1); } value = atomic_load(&counter); value -= atomic_test_count; if (value) { metal_log(METAL_LOG_DEBUG, "counter mismatch, delta = %d\n", value); error = -1; } return error; }
static void *alloc_thread(void *arg) { int i; void *ptr; void *rv = 0; (void)arg; for (i = 0; i < test_count; i++) { /* expecting the implementation to be thread safe */ ptr = metal_allocate_memory(256 /*10*i*/); if (!ptr) { metal_log(METAL_LOG_DEBUG, "failed to allocate memmory\n"); rv = (void *)-ENOMEM; break; } metal_free_memory(ptr); } return rv; }