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

Quelle  mmap.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0-only
#define _GNU_SOURCE

#include <dirent.h>
#include <sched.h>
#include <stdbool.h>
#include <stdio.h>
#include <unistd.h>

#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/types.h>

#include <linux/perf_event.h>

#include "../kselftest_harness.h"

#define RB_SIZE  0x3000
#define AUX_SIZE 0x10000
#define AUX_OFFS 0x4000

#define HOLE_SIZE 0x1000

/* Reserve space for rb, aux with space for shrink-beyond-vma testing. */
#define REGION_SIZE (2 * RB_SIZE + 2 * AUX_SIZE)
#define REGION_AUX_OFFS (2 * RB_SIZE)

#define MAP_BASE 1
#define MAP_AUX  2

#define EVENT_SRC_DIR "/sys/bus/event_source/devices"

FIXTURE(perf_mmap)
{
 int  fd;
 void  *ptr;
 void  *region;
};

FIXTURE_VARIANT(perf_mmap)
{
 bool  aux;
 unsigned long ptr_size;
};

FIXTURE_VARIANT_ADD(perf_mmap, rb)
{
 .aux = false,
 .ptr_size = RB_SIZE,
};

FIXTURE_VARIANT_ADD(perf_mmap, aux)
{
 .aux = true,
 .ptr_size = AUX_SIZE,
};

static bool read_event_type(struct dirent *dent, __u32 *type)
{
 char typefn[512];
 FILE *fp;
 int res;

 snprintf(typefn, sizeof(typefn), "%s/%s/type", EVENT_SRC_DIR, dent->d_name);
 fp = fopen(typefn, "r");
 if (!fp)
  return false;

 res = fscanf(fp, "%u", type);
 fclose(fp);
 return res > 0;
}

FIXTURE_SETUP(perf_mmap)
{
 struct perf_event_attr attr = {
  .size  = sizeof(attr),
  .disabled = 1,
  .exclude_kernel = 1,
  .exclude_hv = 1,
 };
 struct perf_event_attr attr_ok = {};
 unsigned int eacces = 0, map = 0;
 struct perf_event_mmap_page *rb;
 struct dirent *dent;
 void *aux, *region;
 DIR *dir;

 self->ptr = NULL;

 dir = opendir(EVENT_SRC_DIR);
 if (!dir)
  SKIP(return"perf not available.");

 region = mmap(NULL, REGION_SIZE, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
 ASSERT_NE(region, MAP_FAILED);
 self->region = region;

 // Try to find a suitable event on this system
 while ((dent = readdir(dir))) {
  int fd;

  if (!read_event_type(dent, &attr.type))
   continue;

  fd = syscall(SYS_perf_event_open, &attr, 0, -1, -1, 0);
  if (fd < 0) {
   if (errno == EACCES)
    eacces++;
   continue;
  }

  // Check whether the event supports mmap()
  rb = mmap(region, RB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, 0);
  if (rb == MAP_FAILED) {
   close(fd);
   continue;
  }

  if (!map) {
   // Save the event in case that no AUX capable event is found
   attr_ok = attr;
   map = MAP_BASE;
  }

  if (!variant->aux)
   continue;

  rb->aux_offset = AUX_OFFS;
  rb->aux_size = AUX_SIZE;

  // Check whether it supports a AUX buffer
  aux = mmap(region + REGION_AUX_OFFS, AUX_SIZE, PROT_READ | PROT_WRITE,
      MAP_SHARED | MAP_FIXED, fd, AUX_OFFS);
  if (aux == MAP_FAILED) {
   munmap(rb, RB_SIZE);
   close(fd);
   continue;
  }

  attr_ok = attr;
  map = MAP_AUX;
  munmap(aux, AUX_SIZE);
  munmap(rb, RB_SIZE);
  close(fd);
  break;
 }
 closedir(dir);

 if (!map) {
  if (!eacces)
   SKIP(return"No mappable perf event found.");
  else
   SKIP(return"No permissions for perf_event_open()");
 }

 self->fd = syscall(SYS_perf_event_open, &attr_ok, 0, -1, -1, 0);
 ASSERT_NE(self->fd, -1);

 rb = mmap(region, RB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, self->fd, 0);
 ASSERT_NE(rb, MAP_FAILED);

 if (!variant->aux) {
  self->ptr = rb;
  return;
 }

 if (map != MAP_AUX)
  SKIP(return"No AUX event found.");

 rb->aux_offset = AUX_OFFS;
 rb->aux_size = AUX_SIZE;
 aux = mmap(region + REGION_AUX_OFFS, AUX_SIZE, PROT_READ | PROT_WRITE,
     MAP_SHARED | MAP_FIXED, self->fd, AUX_OFFS);
 ASSERT_NE(aux, MAP_FAILED);
 self->ptr = aux;
}

FIXTURE_TEARDOWN(perf_mmap)
{
 ASSERT_EQ(munmap(self->region, REGION_SIZE), 0);
 if (self->fd != -1)
  ASSERT_EQ(close(self->fd), 0);
}

TEST_F(perf_mmap, remap)
{
 void *tmp, *ptr = self->ptr;
 unsigned long size = variant->ptr_size;

 // Test the invalid remaps
 ASSERT_EQ(mremap(ptr, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED);
 ASSERT_EQ(mremap(ptr + HOLE_SIZE, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED);
 ASSERT_EQ(mremap(ptr + size - HOLE_SIZE, HOLE_SIZE, size, MREMAP_MAYMOVE), MAP_FAILED);
 // Shrink the end of the mapping such that we only unmap past end of the VMA,
 // which should succeed and poke a hole into the PROT_NONE region
 ASSERT_NE(mremap(ptr + size - HOLE_SIZE, size, HOLE_SIZE, MREMAP_MAYMOVE), MAP_FAILED);

 // Remap the whole buffer to a new address
 tmp = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
 ASSERT_NE(tmp, MAP_FAILED);

 // Try splitting offset 1 hole size into VMA, this should fail
 ASSERT_EQ(mremap(ptr + HOLE_SIZE, size - HOLE_SIZE, size - HOLE_SIZE,
    MREMAP_MAYMOVE | MREMAP_FIXED, tmp), MAP_FAILED);
 // Remapping the whole thing should succeed fine
 ptr = mremap(ptr, size, size, MREMAP_MAYMOVE | MREMAP_FIXED, tmp);
 ASSERT_EQ(ptr, tmp);
 ASSERT_EQ(munmap(tmp, size), 0);
}

TEST_F(perf_mmap, unmap)
{
 unsigned long size = variant->ptr_size;

 // Try to poke holes into the mappings
 ASSERT_NE(munmap(self->ptr, HOLE_SIZE), 0);
 ASSERT_NE(munmap(self->ptr + HOLE_SIZE, HOLE_SIZE), 0);
 ASSERT_NE(munmap(self->ptr + size - HOLE_SIZE, HOLE_SIZE), 0);
}

TEST_F(perf_mmap, map)
{
 unsigned long size = variant->ptr_size;

 // Try to poke holes into the mappings by mapping anonymous memory over it
 ASSERT_EQ(mmap(self->ptr, HOLE_SIZE, PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0), MAP_FAILED);
 ASSERT_EQ(mmap(self->ptr + HOLE_SIZE, HOLE_SIZE, PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0), MAP_FAILED);
 ASSERT_EQ(mmap(self->ptr + size - HOLE_SIZE, HOLE_SIZE, PROT_READ | PROT_WRITE,
         MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0), MAP_FAILED);
}

TEST_HARNESS_MAIN

Messung V0.5
C=95 H=97 G=95

¤ Dauer der Verarbeitung: 0.10 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.