Migrated Akaros code to use pragma once (XCC)
[akaros.git] / kern / include / apipe.h
1 /* Copyright (c) 2013 The Regents of the University of California
2  * Barret Rhoden <brho@cs.berkeley.edu>
3  * See LICENSE for details.
4  *
5  * Atomic pipes.  Multi-reader, multi-writer pipes, similar to sys_pipe except
6  * that they operate on fixed sized chunks of data.
7  *
8  * Basic usage:
9  *
10  * Given:
11  *              struct some_struct {...};
12  *              struct atomic_pipe ap;
13  *              void *kpage_addr;
14  *
15  *              apipe_init(&ap, kpage_addr, PGSIZE, sizeof(struct some_struct));
16  *              ret = apipe_write(&ap, &from_local_struct, 1);
17  *              ...
18  *              ret = apipe_read(&ap, &to_local_struct, 1);
19  *              apipe_close_writer(&ap);
20  *              apipe_close_reader(&ap);
21  *      
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.
25  *
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
31  * readers/writers.
32  *
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.
39  *
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.
42  *
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.
47  *
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. */
51
52 #pragma once
53
54 #include <ros/common.h>
55 #include <kthread.h>
56
57 struct atomic_pipe {
58         char                                            *ap_buf;
59         size_t                                          ap_ring_sz;
60         size_t                                          ap_elem_sz;
61         size_t                                          ap_rd_off;
62         size_t                                          ap_wr_off;
63         unsigned int                            ap_nr_readers;
64         unsigned int                            ap_nr_writers;
65         spinlock_t                                      ap_lock;
66         struct cond_var                         ap_priority_reader;
67         struct cond_var                         ap_general_readers;
68         struct cond_var                         ap_writers;
69         bool                                            ap_has_priority_reader;
70 };
71
72 void apipe_init(struct atomic_pipe *ap, void *buf, size_t buf_sz,
73                 size_t elem_sz);
74 int apipe_read(struct atomic_pipe *ap, void *buf, size_t nr_elem);
75 int apipe_read_cond(struct atomic_pipe *ap,
76                     int(*f)(struct atomic_pipe *pipe, void *arg), void *arg);
77 int apipe_write(struct atomic_pipe *ap, void *buf, size_t nr_elem);
78 void *apipe_head(struct atomic_pipe *ap);
79
80 void apipe_open_reader(struct atomic_pipe *ap);
81 void apipe_open_writer(struct atomic_pipe *ap);
82 void apipe_close_reader(struct atomic_pipe *ap);
83 void apipe_close_writer(struct atomic_pipe *ap);