/* * Validate the cpus and select the frequency to set * Called from task cpuset code with task launch request containing * a pointer to a hex map string of the cpus to be used by this step */ void cpu_freq_cpuset_validate(stepd_step_rec_t *job) { int cpuidx, cpu_num; bitstr_t *cpus_to_set; bitstr_t *cpu_map; char *cpu_bind; char *cpu_str; char *savestr = NULL; debug2("cpu_freq_cpuset_validate: request = %12d %8x", job->cpu_freq, job->cpu_freq); debug2(" jobid=%u, stepid=%u, tasks=%u cpu/task=%u, cpus=%u", job->jobid, job->stepid, job->node_tasks, job->cpus_per_task,job->cpus); debug2(" cpu_bind_type=%4x, cpu_bind map=%s", job->cpu_bind_type, job->cpu_bind); if (!cpu_freq_count) return; if (job->cpu_bind == NULL) { error("cpu_freq_cpuset_validate: cpu_bind string is null"); return; } cpu_bind = xstrdup(job->cpu_bind); if ( (cpu_str = strtok_r(cpu_bind, ",", &savestr) ) == NULL) { error("cpu_freq_cpuset_validate: cpu_bind string invalid"); xfree(cpu_bind); return; } cpu_map = (bitstr_t *) bit_alloc(cpu_freq_count); cpus_to_set = (bitstr_t *) bit_alloc(cpu_freq_count); do { debug3(" cpu_str = %s", cpu_str); if ((job->cpu_bind_type & CPU_BIND_MAP) == CPU_BIND_MAP) { cpu_num = atoi(cpu_str); if (cpu_num >= cpu_freq_count) { error("cpu_freq_cpuset_validate: invalid cpu " "number %d", cpu_num); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; } bit_set(cpu_map, (bitoff_t)cpu_num); } else { if (bit_unfmt_hexmask(cpu_map, cpu_str) == -1) { error("cpu_freq_cpuset_validate: invalid cpu " "mask %s", cpu_bind); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; } } bit_or(cpus_to_set, cpu_map); } while ( (cpu_str = strtok_r(NULL, ",", &savestr) ) != NULL); for (cpuidx=0; cpuidx < cpu_freq_count; cpuidx++) { if (bit_test(cpus_to_set, cpuidx)) { _cpu_freq_find_valid(job->cpu_freq, cpuidx); } } cpu_freq_set(job); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; }
/* * Validate the cpus and select the frequency to set * Called from task cpuset code with task launch request containing * a pointer to a hex map string of the cpus to be used by this step */ extern void cpu_freq_cpuset_validate(stepd_step_rec_t *job) { int cpuidx, cpu_num; bitstr_t *cpus_to_set; bitstr_t *cpu_map; char *cpu_bind; char *cpu_str; char *savestr = NULL; debug_flags = slurm_get_debug_flags(); /* init for slurmstepd */ if (debug_flags & DEBUG_FLAG_CPU_FREQ) { info("cpu_freq_cpuset_validate: request: min=(%12d %8x) " "max=(%12d %8x) governor=%8x", job->cpu_freq_min, job->cpu_freq_min, job->cpu_freq_max, job->cpu_freq_max, job->cpu_freq_gov); info(" jobid=%u, stepid=%u, tasks=%u cpu/task=%u, cpus=%u", job->jobid, job->stepid, job->node_tasks, job->cpus_per_task, job->cpus); info(" cpu_bind_type=%4x, cpu_bind map=%s", job->cpu_bind_type, job->cpu_bind); } if (!cpu_freq_count) return; if (job->cpu_bind == NULL) { error("cpu_freq_cpuset_validate: cpu_bind string is null"); return; } cpu_bind = xstrdup(job->cpu_bind); if ( (cpu_str = strtok_r(cpu_bind, ",", &savestr) ) == NULL) { error("cpu_freq_cpuset_validate: cpu_bind string invalid"); xfree(cpu_bind); return; } cpu_map = (bitstr_t *) bit_alloc(cpu_freq_count); cpus_to_set = (bitstr_t *) bit_alloc(cpu_freq_count); do { debug3(" cpu_str = %s", cpu_str); if ((job->cpu_bind_type & CPU_BIND_MAP) == CPU_BIND_MAP) { cpu_num = atoi(cpu_str); if (cpu_num >= cpu_freq_count) { error("cpu_freq_cpuset_validate: invalid cpu " "number %d", cpu_num); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; } bit_set(cpu_map, (bitoff_t)cpu_num); } else { if (bit_unfmt_hexmask(cpu_map, cpu_str) == -1) { error("cpu_freq_cpuset_validate: invalid cpu " "mask %s", cpu_bind); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; } } bit_or(cpus_to_set, cpu_map); } while ( (cpu_str = strtok_r(NULL, ",", &savestr) ) != NULL); for (cpuidx = 0; cpuidx < cpu_freq_count; cpuidx++) { _cpu_freq_init_data(cpuidx); if (bit_test(cpus_to_set, cpuidx)) { _cpu_freq_setup_data(job, cpuidx); } } cpu_freq_set(job); bit_free(cpu_map); bit_free(cpus_to_set); xfree(cpu_bind); return; }
/* Translate bitmap representation from hex to decimal format, replacing * array_task_str. */ static void _xlate_task_str(slurmdb_job_rec_t *job_ptr) { static int bitstr_len = -1; int buf_size, len; int i, i_first, i_last, i_prev, i_step = 0; bitstr_t *task_bitmap; char *in_buf = job_ptr->array_task_str; char *out_buf = NULL; if (!in_buf) return; if (strlen(in_buf) < 3 || in_buf[1] != 'x') return; i = strlen(in_buf); task_bitmap = bit_alloc(i * 4); bit_unfmt_hexmask(task_bitmap, in_buf); /* Check first for a step function */ i_first = bit_ffs(task_bitmap); i_last = bit_fls(task_bitmap); if (((i_last - i_first) > 10) && !bit_test(task_bitmap, i_first + 1)) { bool is_step = true; i_prev = i_first; for (i = i_first + 1; i <= i_last; i++) { if (!bit_test(task_bitmap, i)) continue; if (i_step == 0) { i_step = i - i_prev; } else if ((i - i_prev) != i_step) { is_step = false; break; } i_prev = i; } if (is_step) { xstrfmtcat(out_buf, "%d-%d:%d", i_first, i_last, i_step); } } if (bitstr_len > 0) { /* Print the first bitstr_len bytes of the bitmap string */ buf_size = bitstr_len; out_buf = xmalloc(buf_size); bit_fmt(out_buf, buf_size, task_bitmap); len = strlen(out_buf); if (len > (buf_size - 3)) for (i = 0; i < 3; i++) out_buf[buf_size - 2 - i] = '.'; } else { /* Print the full bitmap's string representation. * For huge bitmaps this can take roughly one minute, * so let the client do the work */ buf_size = bit_size(task_bitmap) * 8; while (1) { out_buf = xmalloc(buf_size); bit_fmt(out_buf, buf_size, task_bitmap); len = strlen(out_buf); if ((len > 0) && (len < (buf_size - 32))) break; xfree(out_buf); buf_size *= 2; } } if (job_ptr->array_max_tasks) xstrfmtcat(out_buf, "%c%u", '%', job_ptr->array_max_tasks); xfree(job_ptr->array_task_str); job_ptr->array_task_str = out_buf; }