| /*****************************************************************************\ | |
| * task_affinity.c - Library for task pre-launch and post_termination | |
| * functions for task affinity support | |
| ***************************************************************************** | |
| * Copyright (C) 2005-2008 Hewlett-Packard Development Company, L.P. | |
| * Modified by Hewlett-Packard for task affinity support using task_none.c | |
| * Copyright (C) 2005-2007 The Regents of the University of California | |
| * Copyright (C) 2008-2009 Lawrence Livermore National Security. | |
| * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER). | |
| * CODE-OCEC-09-009. All rights reserved. | |
| * | |
| * This file is part of Slurm, a resource management program. | |
| * For details, see <https://slurm.schedmd.com/>. | |
| * Please also read the included file: DISCLAIMER. | |
| * | |
| * Slurm is free software; you can redistribute it and/or modify it under | |
| * the terms of the GNU General Public License as published by the Free | |
| * Software Foundation; either version 2 of the License, or (at your option) | |
| * any later version. | |
| * | |
| * In addition, as a special exception, the copyright holders give permission | |
| * to link the code of portions of this program with the OpenSSL library under | |
| * certain conditions as described in each individual source file, and | |
| * distribute linked combinations including the two. You must obey the GNU | |
| * General Public License in all respects for all of the code used other than | |
| * OpenSSL. If you modify file(s) with this exception, you may extend this | |
| * exception to your version of the file(s), but you are not obligated to do | |
| * so. If you do not wish to do so, delete this exception statement from your | |
| * version. If you delete this exception statement from all source files in | |
| * the program, then also delete it here. | |
| * | |
| * Slurm is distributed in the hope that it will be useful, but WITHOUT ANY | |
| * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS | |
| * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more | |
| * details. | |
| * | |
| * You should have received a copy of the GNU General Public License along | |
| * with Slurm; if not, write to the Free Software Foundation, Inc., | |
| * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
| \*****************************************************************************/ | |
| #define _GNU_SOURCE | |
| #include "config.h" | |
| #include <ctype.h> | |
| #include <dirent.h> | |
| #include <limits.h> | |
| #include <signal.h> | |
| #include <sys/types.h> | |
| #include "affinity.h" | |
| #include "dist_tasks.h" | |
| #include "src/interfaces/task.h" | |
| /* Required Slurm plugin symbols: */ | |
| const char plugin_name[] = "task affinity plugin"; | |
| const char plugin_type[] = "task/affinity"; | |
| const uint32_t plugin_version = SLURM_VERSION_NUMBER; | |
| extern int init(void) | |
| { | |
| char *mstr = NULL; | |
| xcpuset_t *cur_mask = xgetaffinity(0); | |
| mstr = task_cpuset_to_str(cur_mask); | |
| verbose("%s loaded with CPU mask 0x%s", plugin_name, mstr); | |
| xfree(mstr); | |
| xfree(cur_mask); | |
| return SLURM_SUCCESS; | |
| } | |
| extern void fini(void) | |
| { | |
| debug("%s unloaded", plugin_name); | |
| } | |
| /* | |
| * task_p_slurmd_batch_request() | |
| */ | |
| extern int task_p_slurmd_batch_request (batch_job_launch_msg_t *req) | |
| { | |
| info("%s: %pI", __func__, &req->step_id); | |
| batch_bind(req); | |
| return SLURM_SUCCESS; | |
| } | |
| /* | |
| * task_p_slurmd_launch_request() | |
| */ | |
| extern int task_p_slurmd_launch_request (launch_tasks_request_msg_t *req, | |
| uint32_t node_id, char **err_msg) | |
| { | |
| char buf_type[100]; | |
| bool have_debug_flag = slurm_conf.debug_flags & DEBUG_FLAG_CPU_BIND; | |
| int rc; | |
| if (have_debug_flag) { | |
| slurm_sprint_cpu_bind_type(buf_type, req->cpu_bind_type); | |
| log_flag(CPU_BIND, "task affinity : before lllp distribution cpu bind method is '%s' (%s)", | |
| buf_type, req->cpu_bind); | |
| } | |
| rc = lllp_distribution(req, node_id, err_msg); | |
| if (have_debug_flag) { | |
| slurm_sprint_cpu_bind_type(buf_type, req->cpu_bind_type); | |
| log_flag(CPU_BIND, "task affinity : after lllp distribution cpu bind method is '%s' (%s)", | |
| buf_type, req->cpu_bind); | |
| } | |
| return rc; | |
| } | |
| static void _calc_cpu_affinity(stepd_step_rec_t *step) | |
| { | |
| if (!step->cpu_bind_type) | |
| return; | |
| for (int i = 0; i < step->node_tasks; i++) { | |
| step->task[i]->cpu_set = get_cpuset(step, i); | |
| } | |
| } | |
| /* | |
| * task_p_pre_setuid() is called before setting the UID for the | |
| * user to launch his jobs. | |
| */ | |
| extern int task_p_pre_setuid (stepd_step_rec_t *step) | |
| { | |
| int rc = SLURM_SUCCESS; | |
| _calc_cpu_affinity(step); | |
| cpu_freq_cpuset_validate(step); | |
| return rc; | |
| } | |
| #ifdef HAVE_NUMA | |
| static void _numa_set_preferred(nodemask_t *new_mask) | |
| { | |
| int i; | |
| for (i = 0; i < NUMA_NUM_NODES; i++) { | |
| if (nodemask_isset(new_mask, i)) { | |
| numa_set_preferred(i); | |
| break; | |
| } | |
| } | |
| } | |
| #endif | |
| /* | |
| * task_p_pre_launch() is called prior to exec of application task. | |
| * It is followed by TaskProlog program (from slurm.conf) and | |
| * --task-prolog (from srun command line). | |
| */ | |
| extern int task_p_pre_launch (stepd_step_rec_t *step) | |
| { | |
| int rc = SLURM_SUCCESS; | |
| char tmp_str[128]; | |
| if (get_log_level() >= LOG_LEVEL_DEBUG) { | |
| slurm_sprint_cpu_bind_type(tmp_str, step->cpu_bind_type); | |
| debug("affinity %ps, task:%u bind:%s", | |
| &step->step_id, step->envtp->procid, tmp_str); | |
| } | |
| #ifdef HAVE_NUMA | |
| if (step->mem_bind_type && (numa_available() >= 0)) { | |
| nodemask_t new_mask, cur_mask; | |
| cur_mask = numa_get_membind(); | |
| if ((step->mem_bind_type & MEM_BIND_NONE) || | |
| (step->mem_bind_type == MEM_BIND_VERBOSE)) { | |
| /* Do nothing */ | |
| } else if (get_memset(&new_mask, step)) { | |
| if (step->mem_bind_type & MEM_BIND_PREFER) | |
| _numa_set_preferred(&new_mask); | |
| else | |
| numa_set_membind(&new_mask); | |
| cur_mask = new_mask; | |
| } else | |
| rc = SLURM_ERROR; | |
| slurm_chk_memset(&cur_mask, step); | |
| } | |
| #endif | |
| return rc; | |
| } | |
| /* | |
| * task_p_pre_launch_priv() is called prior to exec of application task. | |
| * Runs in privileged mode. | |
| */ | |
| extern int task_p_pre_launch_priv(stepd_step_rec_t *step, uint32_t node_tid, | |
| uint32_t global_tid) | |
| { | |
| int rc = SLURM_SUCCESS; | |
| xcpuset_t *new_mask = step->task[node_tid]->cpu_set; | |
| pid_t mypid = step->task[node_tid]->pid; | |
| if (new_mask) | |
| rc = xsetaffinity(mypid, new_mask); | |
| /* Log affinity status to stderr */ | |
| if (!new_mask || (rc != SLURM_SUCCESS)) { | |
| xcpuset_t *current = xgetaffinity(mypid); | |
| task_slurm_chkaffinity(current, step, rc, node_tid); | |
| xfree(current); | |
| } else { | |
| task_slurm_chkaffinity(new_mask, step, rc, node_tid); | |
| } | |
| return rc; | |
| } | |
| /* | |
| * task_term() is called after termination of application task. | |
| * It is preceded by --task-epilog (from srun command line) | |
| * followed by TaskEpilog program (from slurm.conf). | |
| */ | |
| extern int task_p_post_term (stepd_step_rec_t *step, | |
| stepd_step_task_info_t *task) | |
| { | |
| debug("affinity %ps, task %d", &step->step_id, task->id); | |
| return SLURM_SUCCESS; | |
| } | |
| /* | |
| * task_p_post_step() is called after termination of the step | |
| * (all the task) | |
| */ | |
| extern int task_p_post_step (stepd_step_rec_t *step) | |
| { | |
| return SLURM_SUCCESS; | |
| } | |
| /* | |
| * Keep track a of a pid. | |
| */ | |
| extern int task_p_add_pid (pid_t pid) | |
| { | |
| return SLURM_SUCCESS; | |
| } | |
| extern int task_p_update_mem_limit(stepd_step_rec_t *step, uint64_t new_job_mem, | |
| uint64_t new_step_mem) | |
| { | |
| return SLURM_SUCCESS; | |
| } |