Until we make gnumach fully parallel, we need a way to execute on slave processor set on smp-enabled gnumach.
For example: $ /sbin/smp /bin/bash $ will launch a shell that executes commands only within slave pset, consisting of all processors except processor 0. We can thus test parallelism on Hurd in a controlled way. --- debian/hurd.install.in | 1 + debian/rules | 2 +- sutils/Makefile | 2 +- sutils/smp.c | 80 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 sutils/smp.c diff --git a/debian/hurd.install.in b/debian/hurd.install.in index 09993f2c5..8697488ba 100755 --- a/debian/hurd.install.in +++ b/debian/hurd.install.in @@ -60,6 +60,7 @@ sbin/reboot-hurd sbin/swapoff sbin/swapon sbin/bless +sbin/smp usr/share/msgids usr/bin/fakeroot-hurd usr/bin/gcore diff --git a/debian/rules b/debian/rules index 9e24f761f..f7c55abf1 100755 --- a/debian/rules +++ b/debian/rules @@ -59,7 +59,7 @@ endif CONFIGURE_ARGS += prefix=/ includedir=/usr/include libdir=/lib/$(DEB_HOST_MULTIARCH) libexecdir=/usr/libexec datarootdir=/usr/share sysconfdir=/etc localstatedir=/var CONFIGURE_ARGS_deb = CONFIGURE_ARGS_udeb = libdir=/lib --without-libdaemon --without-libbz2 -SUID_PROGRAMS = /bin/ids /bin/login /bin/ps-hurd /usr/bin/w-hurd +SUID_PROGRAMS = /bin/ids /bin/login /bin/ps-hurd /usr/bin/w-hurd /sbin/smp INSTALL_in := $(wildcard debian/*.install.in) INSTALL_generated := $(patsubst %.in,%,$(INSTALL_in)) diff --git a/sutils/Makefile b/sutils/Makefile index 5bb92c0bf..07d0fb998 100644 --- a/sutils/Makefile +++ b/sutils/Makefile @@ -20,7 +20,7 @@ dir := sutils makemode := utilities -progs = reboot halt fsck swapon swapoff bless +progs = reboot halt fsck swapon swapoff bless smp scripts = e2os MAKEDEV losetup targets = $(special-targets) $(progs) special-targets = $(scripts) diff --git a/sutils/smp.c b/sutils/smp.c new file mode 100644 index 000000000..f91475282 --- /dev/null +++ b/sutils/smp.c @@ -0,0 +1,80 @@ +/* Run a task on slave_pset + Copyright (C) 2024 Free Software Foundation, Inc. + + This file is part of the GNU Hurd. + + The GNU Hurd 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, or (at + your option) any later version. + + The GNU Hurd 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 this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ + +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <error.h> +#include <hurd.h> +#include <version.h> +#include <mach/mach_types.h> +#include <mach/mach_host.h> + +static void +smp (char * const argv[]) +{ + int i; + error_t err; + mach_msg_type_number_t pset_count; + mach_port_t hostpriv; + processor_set_name_array_t psets = {0}; + processor_set_t slave_pset = MACH_PORT_NULL; + + err = get_privileged_ports (&hostpriv, NULL); + if (err) + error (1, err, "Must be run as root for privileged cpu control"); + + err = host_processor_sets (hostpriv, &psets, &pset_count); + if (err) + error (1, err, "Cannot get list of host processor sets"); + + if (pset_count < 2) + error (1, ENOSYS, "gnumach does not have the expected processor sets, are you running smp kernel?"); + + err = host_processor_set_priv (hostpriv, psets[1], &slave_pset); + mach_port_deallocate (mach_task_self (), hostpriv); + for (i = 0; i < pset_count; i++) + mach_port_deallocate (mach_task_self (), psets[i]); + if (err) + error (1, err, "Cannot get access to slave processor set"); + + err = task_assign (mach_task_self (), slave_pset, FALSE); + mach_port_deallocate (mach_task_self (), slave_pset); + if (err) + error (1, err, "Cannot assign task self to slave processor set"); + + /* Drop privileges from suid binary */ + mach_port_deallocate (mach_task_self (), _hurd_host_priv); + setuid (getuid ()); + + execve (argv[1], &argv[1], environ); + + /* Fall through if not executed */ + error (1, errno, "failed to execute %s", argv[1]); +} + +int +main (int argc, char **argv) +{ + if (argc < 2) + error (1, 0, "Usage: smp /path/to/executable"); + + smp (argv); + return 0; +} -- 2.45.2