RTXI  3.0.0
The Real-Time eXperiment Interface Reference Manual
fifo_xenomai.cpp
Go to the documentation of this file.
1 /*
2  The Real-Time eXperiment Interface (RTXI)
3  Copyright (C) 2011 Georgia Institute of Technology, University of Utah,
4  Weill Cornell Medical College
5 
6  This program is free software: you can redistribute it and/or modify
7  it under the terms of the GNU General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  This program is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  GNU General Public License for more details.
15 
16  You should have received a copy of the GNU General Public License
17  along with this program. If not, see <http://www.gnu.org/licenses/>.
18 
19 */
20 
21 #include <filesystem>
22 
23 #include "fifo.hpp"
24 
25 #include <alchemy/pipe.h>
26 #include <fcntl.h>
27 #include <poll.h>
28 #include <sys/eventfd.h>
29 #include <unistd.h>
30 
31 #include "debug.hpp"
32 
33 int FIFO_COUNT = 0;
34 constexpr std::string_view pipe_filesystem_prefix =
35  "/proc/xenomai/registry/rtipc/xddp/";
36 
37 // Generic xenomai fifo based on pipes
38 namespace RT::OS
39 {
40 class xenomaiFifo : public Fifo
41 {
42 public:
43  explicit xenomaiFifo(size_t size);
44  xenomaiFifo(const xenomaiFifo& fifo) = delete;
45  xenomaiFifo& operator=(const xenomaiFifo& fifo) = delete;
46  xenomaiFifo(xenomaiFifo&&) = default;
48  ~xenomaiFifo() override;
49 
50  int64_t read(void* buf, size_t buf_size) override;
51  int64_t write(void* buf, size_t buf_size) override;
52  int64_t readRT(void* buf, size_t buf_size) override;
53  int64_t writeRT(void* buf, size_t buf_size) override;
54  void poll() override;
55  void close() override;
56  int buffer_fd() const;
57  size_t getCapacity() override;
58 
59 private:
60  bool closed = false;
61  std::string pipe_name;
62  int fd; // file descriptor for non-realtime reading and writing
63  int close_event_fd;
64  int pipe_number;
65  RT_PIPE pipe_handle {};
66  size_t fifo_capacity;
67  std::array<struct pollfd, 2> xbuf_poll_fd {};
68 };
69 } // namespace RT::OS
70 
72  : pipe_name(std::string("RTXI-pipe-") + std::to_string(FIFO_COUNT++))
73  , fifo_capacity(size)
74 {
75  pipe_number = rt_pipe_create(
76  &this->pipe_handle, pipe_name.c_str(), P_MINOR_AUTO, fifo_capacity);
77  if (pipe_number < 0) {
78  ERROR_MSG("Unable to open real-time X pipe");
79  }
80  const std::string filename = std::string(pipe_filesystem_prefix) + pipe_name;
81  this->fd = ::open(filename.c_str(), O_RDWR | O_NONBLOCK);
82 
83  this->xbuf_poll_fd[0].fd = this->fd;
84  this->xbuf_poll_fd[0].events = POLLIN;
85  this->close_event_fd = eventfd(0, EFD_NONBLOCK);
86  this->xbuf_poll_fd[1].fd = this->close_event_fd;
87  this->xbuf_poll_fd[1].events = POLLIN;
88 }
89 
91 {
92  if (::close(this->fd) != 0) {
93  ERROR_MSG("Unable to close non-realtime side of X pipe");
94  }
95  if (rt_pipe_delete(&this->pipe_handle) < 0) {
96  ERROR_MSG("Unable to close real-time side of X pipe");
97  }
98 }
99 
100 int64_t RT::OS::xenomaiFifo::read(void* buf, size_t buf_size)
101 {
102  // We need to specify to compiler that we are using read from c lib
103  return ::read(this->fd, buf, buf_size);
104 }
105 
106 int64_t RT::OS::xenomaiFifo::write(void* buf, size_t buf_size)
107 {
108  // we need to specify to compiler that we are using write from c lib
109  return ::write(this->fd, buf, buf_size);
110 }
111 
112 int64_t RT::OS::xenomaiFifo::readRT(void* buf, size_t buf_size)
113 {
114  return rt_pipe_read(&this->pipe_handle, buf, buf_size, TM_NONBLOCK);
115 }
116 
117 int64_t RT::OS::xenomaiFifo::writeRT(void* buf, size_t buf_size)
118 {
119  return rt_pipe_write(&this->pipe_handle, buf, buf_size, P_NORMAL);
120 }
121 
123 {
124  int errcode = ::poll(this->xbuf_poll_fd.data(), 2, -1);
125  if (errcode < 0) {
126  ERROR_MSG("RT::OS::FIFO(evl)::poll : returned with failure code {} : ",
127  errcode);
128  ERROR_MSG("{}", strerror(errcode));
129  } else if ((this->xbuf_poll_fd[1].revents & POLLIN) != 0) {
130  this->closed = true;
131  }
132 }
133 
135 {
136  return this->fd;
137 }
138 
140 {
141  std::array<int64_t, 1> buf {};
142  buf[0] = 1;
143  ::write(this->close_event_fd, buf.data(), sizeof(int64_t));
144 }
145 
147 {
148  return this->fifo_capacity;
149 }
150 
151 int RT::OS::getFifo(std::unique_ptr<Fifo>& fifo, size_t fifo_size)
152 {
153  auto tmp_fifo = std::make_unique<RT::OS::xenomaiFifo>(fifo_size);
154  fifo = std::move(tmp_fifo);
155  return 0;
156 }
xenomaiFifo(size_t size)
xenomaiFifo(const xenomaiFifo &fifo)=delete
int64_t read(void *buf, size_t buf_size) override
int64_t writeRT(void *buf, size_t buf_size) override
void close() override
size_t getCapacity() override
xenomaiFifo(xenomaiFifo &&)=default
~xenomaiFifo() override
xenomaiFifo & operator=(const xenomaiFifo &fifo)=delete
int64_t write(void *buf, size_t buf_size) override
xenomaiFifo & operator=(xenomaiFifo &&)=default
int64_t readRT(void *buf, size_t buf_size) override
void poll() override
void ERROR_MSG(const std::string &errmsg, Args... args)
Definition: debug.hpp:36
constexpr std::string_view pipe_filesystem_prefix
int FIFO_COUNT
Definition: fifo.cpp:31
int getFifo(std::unique_ptr< Fifo > &fifo, size_t fifo_size)
Definition: fifo.cpp:194