Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
Pipe.cxx
Go to the documentation of this file.
1
34#include <sys/select.h>
35#include <unistd.h>
36#include <fcntl.h>
37
38#include "Devtab.hxx"
39#include "utils/constants.hxx"
40#include "utils/RingBuffer.hxx"
41
43const size_t DEFAULT_PIPE_SIZE = 256;
44
46class Pipe : public Node
47{
48public:
52 Pipe(const char *name)
53 : Node(name)
54 , selInfoRd()
55 , selInfoWr()
56 , ring(NULL)
58 {
59 mode_ = S_IFIFO;
60 }
61
65 {
66 if (ring)
67 {
68 ring->destroy();
69 }
70 }
71
77 static int pipe(int pipefds[2]);
78
79private:
84 int close(File *file) OVERRIDE;
85
92 ssize_t read(File *file, void *buf, size_t count) OVERRIDE;
93
100 ssize_t write(File *file, const void *buf, size_t count) OVERRIDE;
101
109 off_t lseek(File* f, off_t offset, int whence) override
110 {
111 return (off_t)-ESPIPE;
112 }
113
121 int fcntl(File *file, int cmd, unsigned long data) OVERRIDE;
122
129 bool select(File* file, int mode) OVERRIDE;
130
131 void enable() OVERRIDE {}
132 void disable() OVERRIDE {};
140 size_t size;
143};
144
151ssize_t Pipe::read(File *file, void *buf, size_t count)
152{
153 if ((file->flags & O_ACCMODE) == O_WRONLY)
154 {
155 return -EBADF;
156 }
157
158 uint8_t *data = (uint8_t*)buf;
159 ssize_t result = 0;
160
161 while (count)
162 {
163 size_t bytes;
164 {
165 OSMutexLock locker(&lock_);
166 if (ring == NULL)
167 {
169 }
170 bytes = ring->get(data, count);
171
172 count -= bytes;
173 result += bytes;
174 data += bytes;
175 }
176
177 if (bytes)
178 {
180 }
181
182 if (count)
183 {
184 /* no more data to receive */
185 if (file->flags & O_NONBLOCK || result > 0)
186 {
187 break;
188 }
189 else
190 {
191 /* blocking mode, wait for writer */
192 fd_set rdfds;
193 FD_ZERO(&rdfds);
194 int fd = fd_lookup(file);
195 FD_SET(fd, &rdfds);
196 ::select(fd + 1, &rdfds, NULL, NULL, NULL);
197 }
198 }
199 }
200
201 return result;
202}
203
210ssize_t Pipe::write(File *file, const void *buf, size_t count)
211{
212 if ((file->flags & O_ACCMODE) == O_RDONLY)
213 {
214 return -EBADF;
215 }
216
217 const uint8_t *data = (const uint8_t*)buf;
218 ssize_t result = 0;
219
220 while (count)
221 {
222 size_t bytes;
223 {
224 OSMutexLock locker(&lock_);
225 if (ring == NULL)
226 {
228 }
229 bytes = ring->put(data, count);
230
231 count -= bytes;
232 result += bytes;
233 data += bytes;
234 }
235
236 if (bytes)
237 {
239 }
240
241 if (count)
242 {
243 /* no more room left */
244 if (file->flags & O_NONBLOCK || result > 0)
245 {
246 break;
247 }
248 else
249 {
250 /* blocking mode, wait for reader */
251 fd_set wrfds;
252 FD_ZERO(&wrfds);
253 int fd = fd_lookup(file);
254 FD_SET(fd, &wrfds);
255 ::select(fd + 1, NULL, &wrfds, NULL, NULL);
256 }
257 }
258 }
259
260 return result;
261}
262
268{
269 mutex.lock();
270 if (--references_ == 0)
271 {
272 mutex.unlock();
273 HASSERT(file->device);
274 delete static_cast<Device *>(file->dev);
275 }
276 else
277 {
278 mutex.unlock();
279 }
280
281 return 0;
282}
283
291int Pipe::fcntl(File *file, int cmd, unsigned long data)
292{
293 switch (cmd)
294 {
295 default:
296 return 0;
297 case F_SETPIPE_SZ:
298 size = data;
299 return 0;
300 }
301}
302
309bool Pipe::select(File* file, int mode)
310{
311 bool retval = false;
312 switch (mode)
313 {
314 case FREAD:
315 portENTER_CRITICAL();
316 if (ring->items())
317 {
318 retval = true;
319 }
320 else
321 {
323 }
324 portEXIT_CRITICAL();
325 break;
326 case FWRITE:
327 portENTER_CRITICAL();
328 if (ring->space())
329 {
330 retval = true;
331 }
332 else
333 {
335 }
336 portEXIT_CRITICAL();
337 break;
338 default:
339 case 0:
340 /* we don't support any exceptions */
341 break;
342 }
343 return retval;
344}
345
346
352int Pipe::pipe(int pipefds[2])
353{
354 Pipe *new_pipe = new Pipe(NULL);
355
356 mutex.lock();
357 pipefds[0] = fd_alloc();
358 if (pipefds[0] < 0)
359 {
360 mutex.unlock();
361 errno = EMFILE;
362 return -1;
363 }
364 pipefds[1] = fd_alloc();
365 mutex.unlock();
366 if (pipefds[1] < 0)
367 {
368 fd_free(pipefds[0]);
369 errno = EMFILE;
370 return -1;
371 }
372
373 File *files[2] = {file_lookup(pipefds[0]), file_lookup(pipefds[1])};
374
375 files[0]->dev = new_pipe;
376 files[1]->dev = new_pipe;
377 files[0]->flags = O_RDONLY;
378 files[1]->flags = O_WRONLY;
379
380 new_pipe->references_ = 2;
381 new_pipe->enable();
382
383 return 0;
384}
385
391int pipe(int pipefds[2])
392{
393 return Pipe::pipe(pipefds);
394}
int pipe(int pipefds[2])
Create a Unix style pipe.
Definition Pipe.cxx:391
const size_t DEFAULT_PIPE_SIZE
Default value of the buffer size in the pipe implementation for FreeRTOS.
Definition Pipe.cxx:43
static void fd_free(int fd)
Free up a file descriptor.
Definition Fileio.cxx:71
static File * file_lookup(int fd)
Looks up a reference to a File corresponding to a given file descriptor.
Definition Fileio.cxx:82
static File files[]
File descriptor pool.
Definition Devtab.hxx:261
static int fd_lookup(File *file)
Looks up a file descriptor corresponding to a given File reference.
Definition Fileio.cxx:101
const char * name
device name
Definition Devtab.hxx:266
static int fd_alloc(void)
Allocate a free file descriptor.
Definition Fileio.cxx:47
static OSMutex mutex
mutual exclusion for fileio
Definition Devtab.hxx:264
Node information.
Definition Devtab.hxx:549
unsigned int references_
number of open references
Definition Devtab.hxx:592
OSMutex lock_
protects internal structures.
Definition Devtab.hxx:588
mode_t mode_
File open mode, such as O_NONBLOCK.
Definition Devtab.hxx:590
Class to allow convenient locking and unlocking of mutexes in a C context.
Definition OS.hxx:494
void lock()
Lock a mutex.
Definition OS.hxx:446
void unlock()
Unlock a mutex.
Definition OS.hxx:453
Private data for a can device.
Definition Pipe.cxx:47
SelectInfo selInfoRd
called after disable
Definition Pipe.cxx:135
void flush_buffers() OVERRIDE
function to disable device
Definition Pipe.cxx:133
ssize_t write(File *file, const void *buf, size_t count) OVERRIDE
Write to a file or device.
Definition Pipe.cxx:210
static int pipe(int pipefds[2])
Create a Unix style pipe.
Definition Pipe.cxx:352
off_t lseek(File *f, off_t offset, int whence) override
Seek method.
Definition Pipe.cxx:109
size_t size
pipe size
Definition Pipe.cxx:140
Pipe(const char *name)
Constructor.
Definition Pipe.cxx:52
bool select(File *file, int mode) OVERRIDE
Device select method.
Definition Pipe.cxx:309
RingBuffer< uint8_t > * ring
ring buffer for storing the data
Definition Pipe.cxx:138
void disable() OVERRIDE
This will be called when reference count goes from non-zero to 0.
Definition Pipe.cxx:132
SelectInfo selInfoWr
select wakeup metadata for write active
Definition Pipe.cxx:136
int close(File *file) OVERRIDE
Close method.
Definition Pipe.cxx:267
void enable() OVERRIDE
function to enable device
Definition Pipe.cxx:131
int fcntl(File *file, int cmd, unsigned long data) OVERRIDE
Manipulate a file descriptor.
Definition Pipe.cxx:291
ssize_t read(File *file, void *buf, size_t count) OVERRIDE
Read from a file or device.
Definition Pipe.cxx:151
~Pipe()
Destructor.
Definition Pipe.cxx:64
Implements a vanilla ring buffer.
size_t get(T *buf, size_t items)
remove a number of items from the buffer.
void destroy()
Destroy an existing ring buffer instance.
size_t space()
space left in buffer of buffer in number items.
size_t put(const T *buf, size_t items)
Insert a number of items to the buffer.
static RingBuffer * create(size_t size)
Factory method to create a ring buffer instance.
size_t items()
Number of items in the buffer.
#define FWRITE
Workaround for missing header defines on some newlib versions.
Definition fcntl.h:58
#define FREAD
Workaround for missing header defines on some newlib versions.
Definition fcntl.h:53
#define F_SETPIPE_SZ
ioctl to set the length of the internal fifo buffer.
Definition fcntl.h:48
#define OVERRIDE
Function attribute for virtual functions declaring that this funciton is overriding a funciton that s...
Definition macros.h:180
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171
Select wakeup information.
Definition Devtab.hxx:491
Device tab structure.
Definition Devtab.hxx:432
static void select_insert(SelectInfo *info)
Add client to list of clients needing woken.
Definition Select.cxx:197
static void select_wakeup(SelectInfo *info)
Wakeup the list of clients needing woken.
Definition Select.cxx:210
File information.
Definition Devtab.hxx:52
int flags
open flags
Definition Devtab.hxx:63
uint8_t device
true if this is a device, false if file system
Definition Devtab.hxx:66
FileIO * dev
file operations
Definition Devtab.hxx:53