diff --git a/NEWS b/NEWS index 2558a95e1c52b0bc33e9261f290f1a0a839e3e1e..512cf9c8f05241ecb9d0dfff5c2210ea6883446d 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,7 @@ documents those changes that are of interest to users and administrators. -- Prevent job stuck in configuring state if slurmctld daemon restarted while PrologSlurmctld is running. Also re-issue burst_buffer/pre-load operation as needed. + -- Correct task affinity support for FreeBSD. * Changes in Slurm 16.05.0 ========================== diff --git a/doc/man/man5/slurm.conf.5 b/doc/man/man5/slurm.conf.5 index d2b10983525173ee26cf09bf73075f9c0b788563..9179e308cb408c62a64ffd60947aa09f539550dd 100644 --- a/doc/man/man5/slurm.conf.5 +++ b/doc/man/man5/slurm.conf.5 @@ -1,4 +1,4 @@ -.TH "slurm.conf" "5" "Slurm Configuration File" "April 2016" "Slurm Configuration File" +.TH "slurm.conf" "5" "Slurm Configuration File" "June 2016" "Slurm Configuration File" .SH "NAME" slurm.conf \- Slurm configuration file @@ -3355,6 +3355,8 @@ exclusive and since they decrease scheduling flexibility are not generally recommended (select no more than one of them). \fBCpusets\fR and \fBSched\fR are mutually exclusive (select only one of them). +All TaskPluginParam options are supported on FreeBSD except \fBCpusets\fR. +The \fBSched\fR option uses cpuset_setaffinity() on FreeBSD, not sched_setaffinity(). .RS .TP 10 diff --git a/src/plugins/task/affinity/affinity.c b/src/plugins/task/affinity/affinity.c index d4f4a558c0d958fd09bcb07cb64918a3f286dc34..e1190a93f34d72c0d09c1d1004e7627081958109 100644 --- a/src/plugins/task/affinity/affinity.c +++ b/src/plugins/task/affinity/affinity.c @@ -290,12 +290,34 @@ int get_cpuset(cpu_set_t *mask, stepd_step_rec_t *job) return false; } +/* For sysctl() functions */ +#if defined(__FreeBSD__) || defined(__NetBSD__) +#include <sys/types.h> +#include <sys/sysctl.h> +#endif + +#define BUFFLEN 127 + /* Return true if Power7 processor */ static bool _is_power_cpu(void) { if (is_power == -1) { +#if defined(__FreeBSD__) || defined(__NetBSD__) + + char buffer[BUFFLEN+1]; + size_t len = BUFFLEN; + + if ( sysctlbyname("hw.model", buffer, &len, NULL, 0) == 0 ) + is_power = ( strstr(buffer, "POWER7") != NULL ); + else { + error("_get_is_power: sysctl could not retrieve hw.model"); + return false; + } + +#elif defined(__linux__) + FILE *cpu_info_file; - char buffer[128]; + char buffer[BUFFLEN+1]; char* _cpuinfo_path = "/proc/cpuinfo"; cpu_info_file = fopen(_cpuinfo_path, "r"); if (cpu_info_file == NULL) { @@ -312,6 +334,14 @@ static bool _is_power_cpu(void) } } fclose(cpu_info_file); + +#else + +/* Assuming other platforms don't support sysctlbyname() or /proc/cpuinfo */ +#warning "Power7 check not implemented for this platform." + is_power = 0; + +#endif } if (is_power == 1) @@ -335,7 +365,11 @@ void reset_cpuset(cpu_set_t *new_mask, cpu_set_t *cur_mask) if (slurm_getaffinity(1, sizeof(full_mask), &full_mask)) { /* Try to get full CPU mask from process init */ CPU_ZERO(&full_mask); +#ifdef __FreeBSD__ + CPU_OR(&full_mask, cur_mask); +#else CPU_OR(&full_mask, &full_mask, cur_mask); +#endif } CPU_ZERO(&newer_mask); for (cur_offset = 0; cur_offset < CPU_SETSIZE; cur_offset++) { @@ -360,7 +394,10 @@ int slurm_setaffinity(pid_t pid, size_t size, const cpu_set_t *mask) int rval; char mstr[1 + CPU_SETSIZE / 4]; -#ifdef SCHED_GETAFFINITY_THREE_ARGS +#ifdef __FreeBSD__ + rval = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, + pid, size, mask); +#elif defined(SCHED_GETAFFINITY_THREE_ARGS) rval = sched_setaffinity(pid, size, mask); #else rval = sched_setaffinity(pid, mask); @@ -378,7 +415,19 @@ int slurm_getaffinity(pid_t pid, size_t size, cpu_set_t *mask) char mstr[1 + CPU_SETSIZE / 4]; CPU_ZERO(mask); -#ifdef SCHED_GETAFFINITY_THREE_ARGS + + /* + * The FreeBSD cpuset API is a superset of the Linux API. + * In addition to PIDs, it supports threads, interrupts, + * jails, and potentially other objects. The first two arguments + * to cpuset_*etaffinity() below indicate that the third argument + * is a PID. -1 indicates the PID of the calling process. + * Linux sched_*etaffinity() uses 0 for this. + */ +#ifdef __FreeBSD__ + rval = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, + pid, size, mask); +#elif SCHED_GETAFFINITY_THREE_ARGS rval = sched_getaffinity(pid, size, mask); #else rval = sched_getaffinity(pid, mask); diff --git a/src/plugins/task/affinity/affinity.h b/src/plugins/task/affinity/affinity.h index 2c05ffd7422b1d2e73ab56a570c445b350a24337..afd2ce627c9fac8845b6380fa3177038fc83b5ad 100644 --- a/src/plugins/task/affinity/affinity.h +++ b/src/plugins/task/affinity/affinity.h @@ -33,7 +33,9 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. \*****************************************************************************/ -#include "config.h" +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif #ifndef _GNU_SOURCE # define _GNU_SOURCE @@ -47,6 +49,17 @@ # include <numa.h> #endif +/* + * FreeBSD and Linux affinity functions have a slightly different interface + * and are defined in different headers. See platform-dependencies in + * affinity.c. + */ +#ifdef __FreeBSD__ +# include <sys/param.h> +# include <sys/cpuset.h> + typedef cpuset_t cpu_set_t; +#endif + #ifdef HAVE_SYS_PRCTL_H # include <sys/prctl.h> #endif