|  | /* Copyright (c) 2013 The Regents of the University of California | 
|  | * Barret Rhoden <brho@cs.berkeley.edu> | 
|  | * See LICENSE for details. | 
|  | * | 
|  | * Atomic pipes.  Multi-reader, multi-writer pipes, similar to sys_pipe except | 
|  | * that they operate on fixed sized chunks of data. | 
|  | * | 
|  | * Basic usage: | 
|  | * | 
|  | * Given: | 
|  | * 		struct some_struct {...}; | 
|  | * 		struct atomic_pipe ap; | 
|  | * 		void *kpage_addr; | 
|  | * | 
|  | * 		apipe_init(&ap, kpage_addr, PGSIZE, sizeof(struct some_struct)); | 
|  | * 		ret = apipe_write(&ap, &from_local_struct, 1); | 
|  | * 		... | 
|  | * 		ret = apipe_read(&ap, &to_local_struct, 1); | 
|  | * 		apipe_close_writer(&ap); | 
|  | * 		apipe_close_reader(&ap); | 
|  | * | 
|  | * Read and write return the number of elements copied.  If they copied any | 
|  | * amount, they will return.  They will block if the pipe is empty/full, | 
|  | * and there exist corresponding writers/readers. | 
|  | * | 
|  | * The only time the number of readers or writers matter is when the pipe | 
|  | * is empty or full.  I even allow writers to write, even if there are no | 
|  | * readers, so long as the pipe isn't full yet.  This allows new readers | 
|  | * to reattach, and pick up whatever was put in while there was no | 
|  | * readers.  If you don't plan to shut down the pipe, you can ignore the | 
|  | * readers/writers. | 
|  | * | 
|  | * Basically, this style prevents you from blocking if there is no one who | 
|  | * will ever wake you up.  In these cases (e.g. reader sees an empty pipe | 
|  | * and there are no writers), the read/write op returns 0, which means | 
|  | * "nothing to do, and can't block since you (possibly) won't wake up". | 
|  | * You might be able to try again in the future, but that's up to whatever | 
|  | * subsystem/code is using the pipes. | 
|  | * | 
|  | * I don't make any assumptions about the memory for the apipe.  It could be | 
|  | * kmalloced, embedded in a struct, whatever.  Hence the lack of refcnts too. | 
|  | * | 
|  | * Everything is multi-reader, multi-writer.  Pretty simple inside (no | 
|  | * fancy tricks, just went with a cv_lock for all ops).  If we want to | 
|  | * make this faster in the future, we can take a look at using some tricks | 
|  | * from the BCQs and Xen ring buffers to allow concurrent reads and writes. | 
|  | * | 
|  | * Likewise, we can make this a little more complicated and optimize for copying | 
|  | * many elements at once (like sys_pipe).  But we can hold off til we see how | 
|  | * people use this.  For now, this is built for one copy at a time. */ | 
|  |  | 
|  | #pragma once | 
|  |  | 
|  | #include <ros/common.h> | 
|  | #include <kthread.h> | 
|  |  | 
|  | struct atomic_pipe { | 
|  | char						*ap_buf; | 
|  | size_t						ap_ring_sz; | 
|  | size_t						ap_elem_sz; | 
|  | size_t						ap_rd_off; | 
|  | size_t						ap_wr_off; | 
|  | unsigned int				ap_nr_readers; | 
|  | unsigned int				ap_nr_writers; | 
|  | spinlock_t					ap_lock; | 
|  | struct cond_var				ap_priority_reader; | 
|  | struct cond_var				ap_general_readers; | 
|  | struct cond_var				ap_writers; | 
|  | bool						ap_has_priority_reader; | 
|  | }; | 
|  |  | 
|  | void apipe_init(struct atomic_pipe *ap, void *buf, size_t buf_sz, | 
|  | size_t elem_sz); | 
|  | int apipe_read(struct atomic_pipe *ap, void *buf, size_t nr_elem); | 
|  | int apipe_read_cond(struct atomic_pipe *ap, | 
|  | int(*f)(struct atomic_pipe *pipe, void *arg), void *arg); | 
|  | int apipe_write(struct atomic_pipe *ap, void *buf, size_t nr_elem); | 
|  | void *apipe_head(struct atomic_pipe *ap); | 
|  |  | 
|  | void apipe_open_reader(struct atomic_pipe *ap); | 
|  | void apipe_open_writer(struct atomic_pipe *ap); | 
|  | void apipe_close_reader(struct atomic_pipe *ap); | 
|  | void apipe_close_writer(struct atomic_pipe *ap); |