int sel4utils_reserve_range_no_alloc_aligned(vspace_t *vspace, sel4utils_res_t *reservation, size_t size, size_t size_bits, seL4_CapRights rights, int cacheable, void **result) { sel4utils_alloc_data_t *data = get_alloc_data(vspace); void *vaddr = find_range(data, BYTES_TO_SIZE_BITS_PAGES(size, size_bits), size_bits); if (vaddr == NULL) { return -1; } *result = vaddr; reservation->malloced = 0; perform_reservation(vspace, reservation, (uintptr_t) vaddr, size, rights, cacheable); return 0; }
static json_t * hardware_process(void *results) { hardware_results_t *raw_results = results; result_desc_t desc = { .stable = false, .name = "Nop syscall overhead", .ignored = N_IGNORED }; result_t nopnulsyscall_result = process_result(N_RUNS, raw_results->nullSyscall_overhead, desc); /* Execlude ccnt, user-level and loop overheads */ desc.overhead = nopnulsyscall_result.min; result_t result = process_result(N_RUNS, raw_results->nullSyscall_results, desc); result_set_t set = { .name = "Hardware null_syscall thread", .n_results = 1, .n_extra_cols = 0, .results = &result }; json_t *array = json_array(); json_array_append_new(array, result_set_to_json(set)); set.name = "Nop syscall overhead"; set.results = &nopnulsyscall_result; json_array_append_new(array, result_set_to_json(set)); return array; } static benchmark_t hardware_benchmark = { .name = "hardware", .enabled = config_set(CONFIG_APP_HARDWAREBENCH), .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(hardware_results_t), seL4_PageBits), .process = hardware_process, .init = blank_init }; benchmark_t * hardware_benchmark_new(void) { return &hardware_benchmark; }
static json_t * process(void *results) { irq_results_t *irq_results = (irq_results_t *) results; /* Sort and group data by tracepoints. A stable sort is used so the first N_IGNORED * results of each tracepoint can be ignored, as this keeps the data in chronological * order. */ logging_stable_sort_log(irq_results->kernel_log, irq_results->n); logging_group_log_by_key(irq_results->kernel_log, irq_results->n, sizes, offsets, CONFIG_MAX_NUM_TRACE_POINTS); /* Copy the cycle counts into a separate array to simplify further processing */ for (int i = 0; i < irq_results->n; ++i) { kernel_log_data[i] = kernel_logging_entry_get_data(&irq_results->kernel_log[i]); } /* Process log entries generated by an "empty" tracepoint, which recorded * the number of cycles between starting a tracepoint and stopping it * immediately afterwards. This will determine the overhead introduced by * using tracepoints. */ int n_overhead_data = sizes[TRACE_POINT_OVERHEAD] - N_IGNORED; if (n_overhead_data <= 0) { ZF_LOGF("Insufficient data recorded. Was the kernel built with the relevant tracepoints?\n"); } ccnt_t *overhead_data = &kernel_log_data[offsets[TRACE_POINT_OVERHEAD] + N_IGNORED]; /* The results of the IRQ path benchmark are split over multiple tracepoints. * A new buffer is allocated to store the amalgamated results. */ int n_data = sizes[TRACE_POINT_IRQ_PATH_START] - N_IGNORED; if (n_data <= 0) { ZF_LOGF("Insufficient data recorded. Was the kernel built with the relevant tracepoints?\n"); } ccnt_t *data = (ccnt_t*)malloc(sizeof(ccnt_t) * n_data); if (data == NULL) { ZF_LOGF("Failed to allocate memory\n"); } json_t *array = json_array(); result_desc_t desc = {0}; result_t result = process_result(n_overhead_data, overhead_data, desc); result_set_t set = { .name = "Tracepoint overhead", .n_results = 1, .results = &result, }; json_array_append_new(array, result_set_to_json(set)); /* Add the results from the IRQ path tracepoints to get the total IRQ path cycle counts. * The average overhead is subtracted from each cycle count (doubled as there are 2 * tracepoints) to account for overhead added to the cycle counts by use of tracepoints. */ ccnt_t *starts = &kernel_log_data[offsets[TRACE_POINT_IRQ_PATH_START] + N_IGNORED]; ccnt_t *ends = &kernel_log_data[offsets[TRACE_POINT_IRQ_PATH_END] + N_IGNORED]; for (int i = 0; i < n_data; ++i) { data[i] = starts[i] + ends[i] - (result.mean * 2); } set.name = "IRQ Path Cycle Count (accounting for overhead)"; result = process_result(n_data, data, desc); json_array_append_new(array, result_set_to_json(set)); free(data); return array; } static benchmark_t irq_benchmark = { .name = "irq", .enabled = config_set(CONFIG_APP_IRQBENCH) && CONFIG_MAX_NUM_TRACE_POINTS == 3, .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(irq_results_t), seL4_PageBits), .process = process, .init = blank_init }; benchmark_t * irq_benchmark_new(void) { return &irq_benchmark; } static json_t * irquser_process(void *r) { irquser_results_t *raw_results = r; result_desc_t desc = { .ignored = N_IGNORED, .name = "IRQ user measurement overhead" }; result_t results[3]; results[0] = process_result(N_RUNS, raw_results->overheads, desc); desc.overhead = results[0].min; results[1] = process_result(N_RUNS, raw_results->thread_results, desc); results[2] = process_result(N_RUNS, raw_results->process_results, desc); char *types[] = {"Measurement overhead", "Without context switch", "With context switch"}; column_t col = { .header = "Type", .type = JSON_STRING, .string_array = types }; result_set_t set = { .name = "IRQ path cycle count (measured from user level)", .n_results = 3, .results = results, .n_extra_cols = 1, .extra_cols = &col }; json_t *json = json_array(); json_array_append_new(json, result_set_to_json(set)); return json; } static benchmark_t irquser_benchmark = { .name = "irquser", .enabled = config_set(CONFIG_APP_IRQUSERBENCH), .results_pages = BYTES_TO_SIZE_BITS_PAGES(sizeof(irquser_results_t), seL4_PageBits), .process = irquser_process, .init = blank_init }; benchmark_t * irquser_benchmark_new(void) { return &irquser_benchmark; }