Skip to content

Commit

Permalink
feat: Add C++ Mmap Wrapper
Browse files Browse the repository at this point in the history
In preperation for CUPTI support, this commit adds a SharedMemory class
that wraps Mmap and converts the EventReader to use it.
  • Loading branch information
cvonelm committed Aug 2, 2024
1 parent 92f68a8 commit d43b469
Show file tree
Hide file tree
Showing 2 changed files with 129 additions and 9 deletions.
36 changes: 27 additions & 9 deletions include/lo2s/perf/event_reader.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#include <lo2s/log.hpp>
#include <lo2s/mmap.hpp>
#include <lo2s/platform.hpp>
#include <lo2s/shared_memory.hpp>
#include <lo2s/util.hpp>

#include <algorithm>
Expand Down Expand Up @@ -149,6 +150,22 @@ class EventReader
// struct sample_id sample_id;
};

EventReader() = default;

EventReader(EventReader<T>&) = delete;
EventReader& operator=(EventReader<T>&) = delete;

EventReader(EventReader<T>&& other)
{
std::swap(this->shmem_, other.shmem_);
}

EventReader& operator=(EventReader&& other)
{
std::swap(this->shmem_, other.shmem_);
return *this;
}

~EventReader()
{
if (lost_samples > 0)
Expand All @@ -165,16 +182,17 @@ class EventReader

mmap_pages_ = config().mmap_pages;

base = mmap(NULL, (mmap_pages_ + 1) * get_page_size(), PROT_READ | PROT_WRITE, MAP_SHARED,
fd, 0);
// Should not be necessary to check for nullptr, but we've seen it!
if (base == MAP_FAILED || base == nullptr)
try
{
shmem_ = SharedMemory(fd, (mmap_pages_ + 1) * get_page_size());
}
catch (const std::system_error& e)
{
Log::error() << "mapping memory for recording events failed. You can try "
"to decrease the buffer size with the -m flag, or try to increase "
"the amount of mappable memory by increasing /proc/sys/kernel/"
"perf_event_mlock_kb";
throw_errno();
throw;
}
}

Expand Down Expand Up @@ -305,12 +323,12 @@ class EventReader
private:
const struct perf_event_mmap_page* header() const
{
return (const struct perf_event_mmap_page*)base;
return shmem_.as<struct perf_event_mmap_page*>();
}

struct perf_event_mmap_page* header()
{
return (struct perf_event_mmap_page*)base;
return shmem_.as<struct perf_event_mmap_page*>();
}

uint64_t data_head() const
Expand Down Expand Up @@ -341,7 +359,7 @@ class EventReader
{
// workaround for old kernels
// assert(header()->data_offset == get_page_size());
return reinterpret_cast<std::byte*>(base) + get_page_size();
return shmem_.as<std::byte*>() + get_page_size();
}

public:
Expand Down Expand Up @@ -373,7 +391,7 @@ class EventReader

private:
int fd_;
void* base;
SharedMemory shmem_;
std::byte event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
};

Expand Down
102 changes: 102 additions & 0 deletions include/lo2s/shared_memory.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* This file is part of the lo2s software.
* Linux OTF2 sampling
*
* Copyright (c) 2016,
* Technische Universitaet Dresden, Germany
*
* lo2s 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 3 of the License, or
* (at your option) any later version.
*
* lo2s 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 lo2s. If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

#include <lo2s/error.hpp>

#include <utility>

extern "C"
{
#include <fcntl.h>
#include <sys/mman.h>
}

namespace lo2s
{
class SharedMemory
{
public:
SharedMemory() : addr_(nullptr), size_(0)
{
}

SharedMemory(SharedMemory&) = delete;
SharedMemory& operator=(SharedMemory&) = delete;

SharedMemory(SharedMemory&& other)
{
std::swap(addr_, other.addr_);
std::swap(size_, other.size_);
}

SharedMemory& operator=(SharedMemory&& other)
{
std::swap(addr_, other.addr_);
std::swap(size_, other.size_);
return *this;
}

SharedMemory(int fd, size_t size, size_t offset = 0, void* location = nullptr) : size_(size)
{
if (location == nullptr)
{
addr_ = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, offset);
}
else
{
addr_ =
mmap(location, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, offset);
}
if (addr_ == MAP_FAILED)
{
throw_errno();
}
}

template <typename T>
T as()
{
return reinterpret_cast<T>(addr_);
}

template <typename T>
const T as() const
{
return reinterpret_cast<const T>(addr_);
}

~SharedMemory()
{
munmap(addr_, size_);
}

size_t size()
{
return size_;
}

private:
void* addr_ = nullptr;
size_t size_;
};
} // namespace lo2s

0 comments on commit d43b469

Please sign in to comment.