1 /* Copyright (c) 2013 The Regents of the University of California
2 * Barret Rhoden <brho@cs.berkeley.edu>
3 * See LICENSE for details.
5 * Atomic pipes. Multi-reader, multi-writer pipes, similar to sys_pipe except
6 * that they operate on fixed sized chunks of data.
11 * struct some_struct {...};
12 * struct atomic_pipe ap;
15 * apipe_init(&ap, kpage_addr, PGSIZE, sizeof(struct some_struct));
16 * ret = apipe_write(&ap, &from_local_struct, 1);
18 * ret = apipe_read(&ap, &to_local_struct, 1);
19 * apipe_close_writer(&ap);
20 * apipe_close_reader(&ap);
22 * Read and write return the number of elements copied. If they copied any
23 * amount, they will return. They will block if the pipe is empty/full,
24 * and there exist corresponding writers/readers.
26 * The only time the number of readers or writers matter is when the pipe
27 * is empty or full. I even allow writers to write, even if there are no
28 * readers, so long as the pipe isn't full yet. This allows new readers
29 * to reattach, and pick up whatever was put in while there was no
30 * readers. If you don't plan to shut down the pipe, you can ignore the
33 * Basically, this style prevents you from blocking if there is no one who
34 * will ever wake you up. In these cases (e.g. reader sees an empty pipe
35 * and there are no writers), the read/write op returns 0, which means
36 * "nothing to do, and can't block since you (possibly) won't wake up".
37 * You might be able to try again in the future, but that's up to whatever
38 * subsystem/code is using the pipes.
40 * I don't make any assumptions about the memory for the apipe. It could be
41 * kmalloced, embedded in a struct, whatever. Hence the lack of refcnts too.
43 * Everything is multi-reader, multi-writer. Pretty simple inside (no
44 * fancy tricks, just went with a cv_lock for all ops). If we want to
45 * make this faster in the future, we can take a look at using some tricks
46 * from the BCQs and Xen ring buffers to allow concurrent reads and writes.
48 * Likewise, we can make this a little more complicated and optimize for copying
49 * many elements at once (like sys_pipe). But we can hold off til we see how
50 * people use this. For now, this is built for one copy at a time. */
52 #ifndef ROS_KERN_APIPE_H
53 #define ROS_KERN_APIPE_H
55 #include <ros/common.h>
64 unsigned int ap_nr_readers;
65 unsigned int ap_nr_writers;
67 struct cond_var ap_priority_reader;
68 struct cond_var ap_general_readers;
69 struct cond_var ap_writers;
70 bool ap_has_priority_reader;
73 void apipe_init(struct atomic_pipe *ap, void *buf, size_t buf_sz,
75 int apipe_read(struct atomic_pipe *ap, void *buf, size_t nr_elem);
76 int apipe_read_cond(struct atomic_pipe *ap,
77 int(*f)(struct atomic_pipe *pipe, void *arg), void *arg);
78 int apipe_write(struct atomic_pipe *ap, void *buf, size_t nr_elem);
79 void *apipe_head(struct atomic_pipe *ap);
81 void apipe_open_reader(struct atomic_pipe *ap);
82 void apipe_open_writer(struct atomic_pipe *ap);
83 void apipe_close_reader(struct atomic_pipe *ap);
84 void apipe_close_writer(struct atomic_pipe *ap);
86 #endif /* ROS_KERN_APIPE_H */