File: SubprocessMemory.cpp

package info (click to toggle)
swiftlang 6.0.3-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 2,519,992 kB
  • sloc: cpp: 9,107,863; ansic: 2,040,022; asm: 1,135,751; python: 296,500; objc: 82,456; f90: 60,502; lisp: 34,951; pascal: 19,946; sh: 18,133; perl: 7,482; ml: 4,937; javascript: 4,117; makefile: 3,840; awk: 3,535; xml: 914; fortran: 619; cs: 573; ruby: 573
file content (146 lines) | stat: -rw-r--r-- 5,850 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
//===-- SubprocessMemory.cpp ------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "SubprocessMemory.h"
#include "Error.h"
#include "llvm/Support/Error.h"
#include <cerrno>

#ifdef __linux__
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#endif

namespace llvm {
namespace exegesis {

#if defined(__linux__) && !defined(__ANDROID__)

Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessID) {
  // Add the PID to the shared memory name so that if we're running multiple
  // processes at the same time, they won't interfere with each other.
  // This comes up particularly often when running the exegesis tests with
  // llvm-lit
  std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ProcessID);
  int AuxiliaryMemoryFD = shm_open(AuxiliaryMemoryName.c_str(),
                                   O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
  if (AuxiliaryMemoryFD == -1)
    return make_error<Failure>(
        "Failed to create shared memory object for auxiliary memory: " +
        Twine(strerror(errno)));
  if (ftruncate(AuxiliaryMemoryFD, AuxiliaryMemorySize) != 0) {
    return make_error<Failure>("Truncating the auxiliary memory failed: " +
                               Twine(strerror(errno)));
  }
  SharedMemoryNames.push_back(AuxiliaryMemoryName);
  return Error::success();
}

Error SubprocessMemory::addMemoryDefinition(
    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
    pid_t ProcessPID) {
  SharedMemoryNames.reserve(MemoryDefinitions.size());
  for (auto &[Name, MemVal] : MemoryDefinitions) {
    std::string SharedMemoryName = "/" + std::to_string(ProcessPID) + "memdef" +
                                   std::to_string(MemVal.Index);
    SharedMemoryNames.push_back(SharedMemoryName);
    int SharedMemoryFD =
        shm_open(SharedMemoryName.c_str(), O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
    if (ftruncate(SharedMemoryFD, MemVal.SizeBytes) != 0) {
      return make_error<Failure>("Truncating a memory definiton failed: " +
                                 Twine(strerror(errno)));
    }

    char *SharedMemoryMapping =
        (char *)mmap(NULL, MemVal.SizeBytes, PROT_READ | PROT_WRITE, MAP_SHARED,
                     SharedMemoryFD, 0);
    // fill the buffer with the specified value
    size_t CurrentByte = 0;
    const size_t ValueWidthBytes = MemVal.Value.getBitWidth() / 8;
    while (CurrentByte < MemVal.SizeBytes - ValueWidthBytes) {
      memcpy(SharedMemoryMapping + CurrentByte, MemVal.Value.getRawData(),
             ValueWidthBytes);
      CurrentByte += ValueWidthBytes;
    }
    // fill the last section
    memcpy(SharedMemoryMapping + CurrentByte, MemVal.Value.getRawData(),
           MemVal.SizeBytes - CurrentByte);
    if (munmap(SharedMemoryMapping, MemVal.SizeBytes) != 0) {
      return make_error<Failure>(
          "Unmapping a memory definition in the parent failed: " +
          Twine(strerror(errno)));
    }
  }
  return Error::success();
}

Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
    pid_t ParentPID, int CounterFileDescriptor) {
  std::string AuxiliaryMemoryName = "/auxmem" + std::to_string(ParentPID);
  int AuxiliaryMemoryFileDescriptor =
      shm_open(AuxiliaryMemoryName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
  if (AuxiliaryMemoryFileDescriptor == -1)
    return make_error<Failure>(
        "Getting file descriptor for auxiliary memory failed");
  // set up memory value file descriptors
  int *AuxiliaryMemoryMapping =
      (int *)mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED,
                  AuxiliaryMemoryFileDescriptor, 0);
  if ((intptr_t)AuxiliaryMemoryMapping == -1)
    return make_error<Failure>("Mapping auxiliary memory failed");
  AuxiliaryMemoryMapping[0] = CounterFileDescriptor;
  for (auto &[Name, MemVal] : MemoryDefinitions) {
    std::string MemoryValueName = "/" + std::to_string(ParentPID) + "memdef" +
                                  std::to_string(MemVal.Index);
    AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] =
        shm_open(MemoryValueName.c_str(), O_RDWR, S_IRUSR | S_IWUSR);
    if (AuxiliaryMemoryMapping[AuxiliaryMemoryOffset + MemVal.Index] == -1)
      return make_error<Failure>("Mapping shared memory failed");
  }
  if (munmap(AuxiliaryMemoryMapping, 4096) == -1)
    return make_error<Failure>("Unmapping auxiliary memory failed");
  return AuxiliaryMemoryFileDescriptor;
}

SubprocessMemory::~SubprocessMemory() {
  for (std::string SharedMemoryName : SharedMemoryNames) {
    if (shm_unlink(SharedMemoryName.c_str()) != 0) {
      errs() << "Failed to unlink shared memory section: " << strerror(errno)
             << "\n";
    }
  }
}

#else

Error SubprocessMemory::initializeSubprocessMemory(pid_t ProcessPID) {
  return make_error<Failure>(
      "initializeSubprocessMemory is only supported on Linux");
}

Error SubprocessMemory::addMemoryDefinition(
    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
    pid_t ProcessPID) {
  return make_error<Failure>("addMemoryDefinitions is only supported on Linux");
}

Expected<int> SubprocessMemory::setupAuxiliaryMemoryInSubprocess(
    std::unordered_map<std::string, MemoryValue> MemoryDefinitions,
    pid_t ParentPID, int CounterFileDescriptor) {
  return make_error<Failure>(
      "setupAuxiliaryMemoryInSubprocess is only supported on Linux");
}

SubprocessMemory::~SubprocessMemory() {}

#endif // defined(__linux__) && !defined(__ANDROID__)

} // namespace exegesis
} // namespace llvm