mirror of
https://github.com/scylladb/scylladb.git
synced 2026-04-24 02:20:37 +00:00
Found with clang:
[46/68] CXX build/release/core/xen/evtchn.o
FAILED: clang -MMD -MT build/release/core/xen/evtchn.o -MF
build/release/core/xen/evtchn.o.d -std=gnu++1y -Wall -Werror
-fvisibility=hidden -pthread -I. -Wno-mismatched-tags -DHAVE_XEN
-DHAVE_HWLOC -DHAVE_NUMA -O2 -I build/release/gen -c -o
build/release/core/xen/evtchn.o core/xen/evtchn.cc
core/xen/evtchn.cc:83:18: error: 'xen::userspace_evtchn::umask' hides
overloaded virtual function [-Werror,-Woverloaded-virtual]
virtual void umask(int *port, unsigned count);
^
core/xen/evtchn.hh:38:18: note: hidden overloaded virtual function
'xen::evtchn::umask' declared here: type mismatch at 2nd parameter
('int' vs 'unsigned int')
virtual void umask(int *port, int count) {};
^
1 error generated.
203 lines
4.8 KiB
C++
203 lines
4.8 KiB
C++
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <xen/xen.h>
|
|
#include <xen/event_channel.h> // kernel interface
|
|
#include <xen/sys/evtchn.h> // userspace interface
|
|
|
|
#include "core/reactor.hh"
|
|
#include "core/semaphore.hh"
|
|
#include "core/future-util.hh"
|
|
#include "evtchn.hh"
|
|
#include "osv_xen.hh"
|
|
|
|
namespace xen {
|
|
|
|
void evtchn::make_ready_port(int port) {
|
|
auto ports = _ports.equal_range(port);
|
|
for (auto i = ports.first; i != ports.second; ++i) {
|
|
i->second->_sem.signal();
|
|
}
|
|
}
|
|
|
|
void evtchn::port_moved(int prt, port* old, port* now) {
|
|
auto ports = _ports.equal_range(prt);
|
|
for (auto i = ports.first; i != ports.second; ++i) {
|
|
if (i->second == old) {
|
|
i->second = now;
|
|
}
|
|
}
|
|
}
|
|
|
|
void evtchn::port_deleted(int prt, port* obj) {
|
|
auto ports = _ports.equal_range(prt);
|
|
for (auto i = ports.first; i != ports.second; ++i) {
|
|
if (i->second == obj) {
|
|
i = _ports.erase(i);
|
|
}
|
|
}
|
|
}
|
|
|
|
port::port(int p)
|
|
: _port(p), _sem(0), _evtchn(evtchn::instance()) {
|
|
_evtchn->_ports.emplace(p, this);
|
|
}
|
|
|
|
port::port(port&& other)
|
|
: _port(other._port), _sem(std::move(other._sem)), _evtchn(other._evtchn) {
|
|
if (_port != -1) {
|
|
_evtchn->port_moved(_port, &other, this);
|
|
}
|
|
}
|
|
|
|
port::~port() {
|
|
// FIXME: unbind from Xen
|
|
if (_port != -1) {
|
|
_evtchn->port_deleted(_port, this);
|
|
}
|
|
}
|
|
|
|
port& port::operator=(port&& other) {
|
|
if (this != &other) {
|
|
this->~port();
|
|
new (this) port(std::move(other));
|
|
}
|
|
return *this;
|
|
}
|
|
|
|
future<> port::pending() {
|
|
return _sem.wait();
|
|
}
|
|
|
|
void port::notify() {
|
|
_evtchn->notify(_port);
|
|
}
|
|
|
|
void port::umask() {
|
|
_evtchn->umask(&_port, 1);
|
|
}
|
|
|
|
class userspace_evtchn: public evtchn {
|
|
pollable_fd _evtchn;
|
|
int ports[2];
|
|
protected:
|
|
virtual void umask(int *port, unsigned count) override;
|
|
public:
|
|
userspace_evtchn(unsigned otherend);
|
|
virtual port bind() override;
|
|
virtual void notify(int port) override;
|
|
};
|
|
|
|
userspace_evtchn::userspace_evtchn(unsigned otherend)
|
|
: evtchn(otherend)
|
|
, _evtchn(pollable_fd(file_desc::open("/dev/xen/evtchn", O_RDWR | O_NONBLOCK)))
|
|
{
|
|
keep_doing([this] {
|
|
return _evtchn.read_some(reinterpret_cast<char *>(&ports), sizeof(ports)).then([this] (size_t s)
|
|
{
|
|
auto count = s / sizeof(ports[0]);
|
|
for (unsigned i = 0; i < count; ++i) {
|
|
make_ready_port(ports[i]);
|
|
}
|
|
umask(ports, count);
|
|
return make_ready_future<>();
|
|
});
|
|
});
|
|
}
|
|
|
|
port userspace_evtchn::bind()
|
|
{
|
|
struct ioctl_evtchn_bind_unbound_port bind = { _otherend };
|
|
|
|
auto ret = _evtchn.get_file_desc().ioctl<struct ioctl_evtchn_bind_unbound_port>(IOCTL_EVTCHN_BIND_UNBOUND_PORT, bind);
|
|
return port(ret);
|
|
}
|
|
|
|
void userspace_evtchn::notify(int port)
|
|
{
|
|
struct ioctl_evtchn_notify notify;
|
|
notify.port = port;
|
|
|
|
_evtchn.get_file_desc().ioctl<struct ioctl_evtchn_notify>(IOCTL_EVTCHN_NOTIFY, notify);
|
|
}
|
|
|
|
void userspace_evtchn::umask(int *port, unsigned count)
|
|
{
|
|
_evtchn.get_file_desc().write(port, count * sizeof(port));
|
|
}
|
|
|
|
#ifdef HAVE_OSV
|
|
class kernel_evtchn: public evtchn {
|
|
// We need to convert extra-seastar events to intra-seastar events
|
|
// (in this case, the semaphore interface of evtchn). The interface for
|
|
// that currently is the reactor notifier.
|
|
std::unique_ptr<reactor_notifier> _notified;
|
|
static void make_ready(void *arg);
|
|
void process_interrupts(int port);
|
|
public:
|
|
kernel_evtchn(unsigned otherend)
|
|
: evtchn(otherend)
|
|
, _notified(engine.make_reactor_notifier()) {}
|
|
virtual port bind() override;
|
|
virtual void notify(int port) override;
|
|
};
|
|
|
|
void kernel_evtchn::make_ready(void *arg) {
|
|
auto notifier = reinterpret_cast<reactor_notifier *>(arg);
|
|
notifier->signal();
|
|
}
|
|
|
|
port kernel_evtchn::bind() {
|
|
|
|
unsigned int irq;
|
|
|
|
int newp;
|
|
irq = bind_listening_port_to_irq(_otherend, &newp);
|
|
|
|
port p(newp);
|
|
|
|
auto notifier = reinterpret_cast<void *>(_notified.get());
|
|
|
|
intr_add_handler("", irq, NULL, make_ready, notifier, 0, 0);
|
|
unmask_evtchn(newp);
|
|
process_interrupts(newp);
|
|
return p;
|
|
}
|
|
|
|
void kernel_evtchn::process_interrupts(int port) {
|
|
_notified->wait().then([this, port] () {
|
|
make_ready_port(port);
|
|
process_interrupts(port);
|
|
});
|
|
}
|
|
|
|
void kernel_evtchn::notify(int port) {
|
|
notify_remote_via_evtchn(port);
|
|
}
|
|
#endif
|
|
|
|
evtchn *evtchn::_instance = nullptr;
|
|
|
|
evtchn *evtchn::instance()
|
|
{
|
|
if (!_instance) {
|
|
throw std::runtime_error("Acquiring evtchn instance without specifying otherend: invalid context");
|
|
}
|
|
|
|
return _instance;
|
|
}
|
|
|
|
evtchn *evtchn::instance(bool userspace, unsigned otherend)
|
|
{
|
|
if (!_instance) {
|
|
#ifdef HAVE_OSV
|
|
if (!userspace) {
|
|
_instance = new kernel_evtchn(otherend);
|
|
} else
|
|
#endif
|
|
_instance = new userspace_evtchn(otherend);
|
|
}
|
|
return _instance;
|
|
}
|
|
|
|
}
|