summaryrefslogtreecommitdiff
path: root/sysdeps/unix/sysv/linux/tst-affinity-pid.c
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/unix/sysv/linux/tst-affinity-pid.c')
-rw-r--r--sysdeps/unix/sysv/linux/tst-affinity-pid.c201
1 files changed, 201 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/tst-affinity-pid.c b/sysdeps/unix/sysv/linux/tst-affinity-pid.c
new file mode 100644
index 0000000000..67402bf7ff
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/tst-affinity-pid.c
@@ -0,0 +1,201 @@
+/* Test for sched_getaffinity and sched_setaffinity, PID version.
+ Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <http://www.gnu.org/licenses/>. */
+
+/* Function definitions for the benefit of tst-skeleton-affinity.c.
+ This variant forks a child process which then invokes
+ sched_getaffinity and sched_setaffinity on the parent PID. */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <unistd.h>
+
+static int
+write_fully (int fd, const void *buffer, size_t length)
+{
+ const void *end = buffer + length;
+ while (buffer < end)
+ {
+ ssize_t bytes_written = TEMP_FAILURE_RETRY
+ (write (fd, buffer, end - buffer));
+ if (bytes_written < 0)
+ return -1;
+ if (bytes_written == 0)
+ {
+ errno = ENOSPC;
+ return -1;
+ }
+ buffer += bytes_written;
+ }
+ return 0;
+}
+
+static ssize_t
+read_fully (int fd, void *buffer, size_t length)
+{
+ const void *start = buffer;
+ const void *end = buffer + length;
+ while (buffer < end)
+ {
+ ssize_t bytes_read = TEMP_FAILURE_RETRY
+ (read (fd, buffer, end - buffer));
+ if (bytes_read < 0)
+ return -1;
+ if (bytes_read == 0)
+ return buffer - start;
+ buffer += bytes_read;
+ }
+ return length;
+}
+
+static int
+process_child_response (int *pipes, pid_t child,
+ cpu_set_t *set, size_t size)
+{
+ close (pipes[1]);
+
+ int value_from_child;
+ ssize_t bytes_read = read_fully
+ (pipes[0], &value_from_child, sizeof (value_from_child));
+ if (bytes_read < 0)
+ {
+ printf ("error: read from child: %m\n");
+ exit (1);
+ }
+ if (bytes_read != sizeof (value_from_child))
+ {
+ printf ("error: not enough bytes from child: %zd\n", bytes_read);
+ exit (1);
+ }
+ if (value_from_child == 0)
+ {
+ bytes_read = read_fully (pipes[0], set, size);
+ if (bytes_read < 0)
+ {
+ printf ("error: read: %m\n");
+ exit (1);
+ }
+ if (bytes_read != size)
+ {
+ printf ("error: not enough bytes from child: %zd\n", bytes_read);
+ exit (1);
+ }
+ }
+
+ int status;
+ if (waitpid (child, &status, 0) < 0)
+ {
+ printf ("error: waitpid: %m\n");
+ exit (1);
+ }
+ if (!(WIFEXITED (status) && WEXITSTATUS (status) == 0))
+ {
+ printf ("error: invalid status from : %m\n");
+ exit (1);
+ }
+
+ close (pipes[0]);
+
+ if (value_from_child != 0)
+ {
+ errno = value_from_child;
+ return -1;
+ }
+ return 0;
+}
+
+static int
+getaffinity (size_t size, cpu_set_t *set)
+{
+ int pipes[2];
+ if (pipe (pipes) < 0)
+ {
+ printf ("error: pipe: %m\n");
+ exit (1);
+ }
+
+ int ret = fork ();
+ if (ret < 0)
+ {
+ printf ("error: fork: %m\n");
+ exit (1);
+ }
+ if (ret == 0)
+ {
+ /* Child. */
+ int ret = sched_getaffinity (getppid (), size, set);
+ if (ret < 0)
+ ret = errno;
+ if (write_fully (pipes[1], &ret, sizeof (ret)) < 0
+ || write_fully (pipes[1], set, size) < 0
+ || (ret == 0 && write_fully (pipes[1], set, size) < 0))
+ {
+ printf ("error: write: %m\n");
+ _exit (1);
+ }
+ _exit (0);
+ }
+
+ /* Parent. */
+ return process_child_response (pipes, ret, set, size);
+}
+
+static int
+setaffinity (size_t size, const cpu_set_t *set)
+{
+ int pipes[2];
+ if (pipe (pipes) < 0)
+ {
+ printf ("error: pipe: %m\n");
+ exit (1);
+ }
+
+ int ret = fork ();
+ if (ret < 0)
+ {
+ printf ("error: fork: %m\n");
+ exit (1);
+ }
+ if (ret == 0)
+ {
+ /* Child. */
+ int ret = sched_setaffinity (getppid (), size, set);
+ if (write_fully (pipes[1], &ret, sizeof (ret)) < 0)
+ {
+ printf ("error: write: %m\n");
+ _exit (1);
+ }
+ _exit (0);
+ }
+
+ /* Parent. There is no affinity mask to read from the child, so the
+ size is 0. */
+ return process_child_response (pipes, ret, NULL, 0);
+}
+
+struct conf;
+static bool early_test (struct conf *unused)
+{
+ return true;
+}
+
+#include "tst-skeleton-affinity.c"