Quellcodebibliothek Statistik Leitseite products/sources/formale Sprachen/C/Linux/tools/testing/selftests/mm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 4 kB image not shown  

Quelle  mrelease_test.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright 2022 Google LLC
 */

#define _GNU_SOURCE
#include <errno.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/syscall.h>
#include <sys/wait.h>
#include <unistd.h>
#include <asm-generic/unistd.h>
#include "vm_util.h"
#include "../kselftest.h"

#define MB(x) (x << 20)
#define MAX_SIZE_MB 1024

static int alloc_noexit(unsigned long nr_pages, int pipefd)
{
 int ppid = getppid();
 int timeout = 10; /* 10sec timeout to get killed */
 unsigned long i;
 char *buf;

 buf = (char *)mmap(NULL, nr_pages * psize(), PROT_READ | PROT_WRITE,
      MAP_PRIVATE | MAP_ANON, 0, 0);
 if (buf == MAP_FAILED)
  ksft_exit_fail_msg("mmap failed, halting the test: %s\n", strerror(errno));

 for (i = 0; i < nr_pages; i++)
  *((unsigned long *)(buf + (i * psize()))) = i;

 /* Signal the parent that the child is ready */
 if (write(pipefd, "", 1) < 0)
  ksft_exit_fail_msg("write: %s\n", strerror(errno));

 /* Wait to be killed (when reparenting happens) */
 while (getppid() == ppid && timeout > 0) {
  sleep(1);
  timeout--;
 }

 munmap(buf, nr_pages * psize());

 return (timeout > 0) ? KSFT_PASS : KSFT_FAIL;
}

/* The process_mrelease calls in this test are expected to fail */
static void run_negative_tests(int pidfd)
{
 /* Test invalid flags. Expect to fail with EINVAL error code. */
 if (!syscall(__NR_process_mrelease, pidfd, (unsigned int)-1) ||
   errno != EINVAL) {
  ksft_exit_fail_msg("process_mrelease with wrong flags: %s\n", strerror(errno));
 }
 /*
 * Test reaping while process is alive with no pending SIGKILL.
 * Expect to fail with EINVAL error code.
 */

 if (!syscall(__NR_process_mrelease, pidfd, 0) || errno != EINVAL)
  ksft_exit_fail_msg("process_mrelease on a live process: %s\n", strerror(errno));
}

static int child_main(int pipefd[], size_t size)
{
 int res;

 /* Allocate and fault-in memory and wait to be killed */
 close(pipefd[0]);
 res = alloc_noexit(MB(size) / psize(), pipefd[1]);
 close(pipefd[1]);
 return res;
}

int main(void)
{
 int pipefd[2], pidfd;
 bool success, retry;
 size_t size;
 pid_t pid;
 char byte;
 int res;

 ksft_print_header();
 ksft_set_plan(1);

 /* Test a wrong pidfd */
 if (!syscall(__NR_process_mrelease, -1, 0) || errno != EBADF) {
  if (errno == ENOSYS) {
   ksft_test_result_skip("process_mrelease not implemented\n");
   ksft_finished();
  } else {
   ksft_exit_fail_msg("process_mrelease with wrong pidfd: %s",
        strerror(errno));
  }
 }

 /* Start the test with 1MB child memory allocation */
 size = 1;
retry:
 /*
 * Pipe for the child to signal when it's done allocating
 * memory
 */

 if (pipe(pipefd))
  ksft_exit_fail_msg("pipe: %s\n", strerror(errno));

 pid = fork();
 if (pid < 0) {
  close(pipefd[0]);
  close(pipefd[1]);
  ksft_exit_fail_msg("fork: %s\n", strerror(errno));
 }

 if (pid == 0) {
  /* Child main routine */
  res = child_main(pipefd, size);
  exit(res);
 }

 /*
 * Parent main routine:
 * Wait for the child to finish allocations, then kill and reap
 */

 close(pipefd[1]);
 /* Block until the child is ready */
 res = read(pipefd[0], &byte, 1);
 close(pipefd[0]);
 if (res < 0) {
  if (!kill(pid, SIGKILL))
   waitpid(pid, NULL, 0);
  ksft_exit_fail_msg("read: %s\n", strerror(errno));
 }

 pidfd = syscall(__NR_pidfd_open, pid, 0);
 if (pidfd < 0) {
  if (!kill(pid, SIGKILL))
   waitpid(pid, NULL, 0);
  ksft_exit_fail_msg("pidfd_open: %s\n", strerror(errno));
 }

 /* Run negative tests which require a live child */
 run_negative_tests(pidfd);

 if (kill(pid, SIGKILL))
  ksft_exit_fail_msg("kill: %s\n", strerror(errno));

 success = (syscall(__NR_process_mrelease, pidfd, 0) == 0);
 if (!success) {
  /*
 * If we failed to reap because the child exited too soon,
 * before we could call process_mrelease. Double child's memory
 * which causes it to spend more time on cleanup and increases
 * our chances of reaping its memory before it exits.
 * Retry until we succeed or reach MAX_SIZE_MB.
 */

  if (errno == ESRCH) {
   retry = (size <= MAX_SIZE_MB);
  } else {
   waitpid(pid, NULL, 0);
   ksft_exit_fail_msg("process_mrelease: %s\n", strerror(errno));
  }
 }

 /* Cleanup to prevent zombies */
 if (waitpid(pid, NULL, 0) < 0)
  ksft_exit_fail_msg("waitpid: %s\n", strerror(errno));

 close(pidfd);

 if (!success) {
  if (retry) {
   size *= 2;
   goto retry;
  }
  ksft_exit_fail_msg("All process_mrelease attempts failed!\n");
 }

 ksft_test_result_pass("Success reaping a child with %zuMB of memory allocations\n",
         size);
 ksft_finished();
}

Messung V0.5
C=97 H=93 G=94

¤ Dauer der Verarbeitung: 0.13 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.