#define PIPE_BUF_FLAG_LRU 0x01 /* page is on the LRU */ #define PIPE_BUF_FLAG_ATOMIC 0x02 /* was atomically mapped */ #define PIPE_BUF_FLAG_GIFT 0x04 /* page is a gift */ #define PIPE_BUF_FLAG_PACKET 0x08 /* read() as a packet */ #define PIPE_BUF_FLAG_CAN_MERGE 0x10 /* can merge buffers */ #define PIPE_BUF_FLAG_WHOLE 0x20 /* read() must return entire buffer or error */ #ifdef CONFIG_WATCH_QUEUE #define PIPE_BUF_FLAG_LOSS 0x40 /* Message loss happened after this buffer */ #endif
/** * struct pipe_buffer - a linux kernel pipe buffer * @page: the page containing the data for the pipe buffer * @offset: offset of data inside the @page * @len: length of data inside the @page * @ops: operations associated with this buffer. See @pipe_buf_operations. * @flags: pipe buffer flags. See above. * @private: private data owned by the ops.
**/ struct pipe_buffer { struct page *page; unsignedint offset, len; conststruct pipe_buf_operations *ops; unsignedint flags; unsignedlongprivate;
};
/* * Really only alpha needs 32-bit fields, but * might as well do it for 64-bit architectures * since that's what we've historically done, * and it makes 'head_tail' always be a simple * 'unsigned long'.
*/ #ifdef CONFIG_64BIT typedefunsignedint pipe_index_t; #else typedefunsignedshort pipe_index_t; #endif
/* * We have to declare this outside 'struct pipe_inode_info', * but then we can't use 'union pipe_index' for an anonymous * union, so we end up having to duplicate this declaration * below. Annoying.
*/ union pipe_index { unsignedlong head_tail; struct {
pipe_index_t head;
pipe_index_t tail;
};
};
/** * struct pipe_inode_info - a linux kernel pipe * @mutex: mutex protecting the whole thing * @rd_wait: reader wait point in case of empty pipe * @wr_wait: writer wait point in case of full pipe * @head: The point of buffer production * @tail: The point of buffer consumption * @head_tail: unsigned long union of @head and @tail * @note_loss: The next read() should insert a data-lost message * @max_usage: The maximum number of slots that may be used in the ring * @ring_size: total number of buffers (should be a power of 2) * @nr_accounted: The amount this pipe accounts for in user->pipe_bufs * @tmp_page: cached released page * @readers: number of current readers of this pipe * @writers: number of current writers of this pipe * @files: number of struct file referring this pipe (protected by ->i_lock) * @r_counter: reader counter * @w_counter: writer counter * @poll_usage: is this pipe used for epoll, which has crazy wakeups? * @fasync_readers: reader side fasync * @fasync_writers: writer side fasync * @bufs: the circular array of pipe buffers * @user: the user who created this pipe * @watch_queue: If this pipe is a watch_queue, this is the stuff for that
**/ struct pipe_inode_info { struct mutex mutex;
wait_queue_head_t rd_wait, wr_wait;
/* This has to match the 'union pipe_index' above */ union { unsignedlong head_tail; struct {
pipe_index_t head;
pipe_index_t tail;
};
};
/* * Note on the nesting of these functions: * * ->confirm() * ->try_steal() * * That is, ->try_steal() must be called on a confirmed buffer. See below for * the meaning of each operation. Also see the kerneldoc in fs/pipe.c for the * pipe and generic variants of these hooks.
*/ struct pipe_buf_operations { /* * ->confirm() verifies that the data in the pipe buffer is there * and that the contents are good. If the pages in the pipe belong * to a file system, we may need to wait for IO completion in this * hook. Returns 0 for good, or a negative error value in case of * error. If not present all pages are considered good.
*/ int (*confirm)(struct pipe_inode_info *, struct pipe_buffer *);
/* * When the contents of this pipe buffer has been completely * consumed by a reader, ->release() is called.
*/ void (*release)(struct pipe_inode_info *, struct pipe_buffer *);
/* * Attempt to take ownership of the pipe buffer and its contents. * ->try_steal() returns %true for success, in which case the contents * of the pipe (the buf->page) is locked and now completely owned by the * caller. The page may then be transferred to a different mapping, the * most often used case is insertion into different file address space * cache.
*/ bool (*try_steal)(struct pipe_inode_info *, struct pipe_buffer *);
/* * Get a reference to the pipe buffer.
*/ bool (*get)(struct pipe_inode_info *, struct pipe_buffer *);
};
/** * pipe_has_watch_queue - Check whether the pipe is a watch_queue, * i.e. it was created with O_NOTIFICATION_PIPE * @pipe: The pipe to check * * Return: true if pipe is a watch queue, false otherwise.
*/ staticinlinebool pipe_has_watch_queue(conststruct pipe_inode_info *pipe)
{ #ifdef CONFIG_WATCH_QUEUE return pipe->watch_queue != NULL; #else returnfalse; #endif
}
/** * pipe_occupancy - Return number of slots used in the pipe * @head: The pipe ring head pointer * @tail: The pipe ring tail pointer
*/ staticinlineunsignedint pipe_occupancy(unsignedint head, unsignedint tail)
{ return (pipe_index_t)(head - tail);
}
/** * pipe_empty - Return true if the pipe is empty * @head: The pipe ring head pointer * @tail: The pipe ring tail pointer
*/ staticinlinebool pipe_empty(unsignedint head, unsignedint tail)
{ return !pipe_occupancy(head, tail);
}
/** * pipe_full - Return true if the pipe is full * @head: The pipe ring head pointer * @tail: The pipe ring tail pointer * @limit: The maximum amount of slots available.
*/ staticinlinebool pipe_full(unsignedint head, unsignedint tail, unsignedint limit)
{ return pipe_occupancy(head, tail) >= limit;
}
/** * pipe_is_full - Return true if the pipe is full * @pipe: the pipe
*/ staticinlinebool pipe_is_full(conststruct pipe_inode_info *pipe)
{ return pipe_full(pipe->head, pipe->tail, pipe->max_usage);
}
/** * pipe_is_empty - Return true if the pipe is empty * @pipe: the pipe
*/ staticinlinebool pipe_is_empty(conststruct pipe_inode_info *pipe)
{ return pipe_empty(pipe->head, pipe->tail);
}
/** * pipe_buf_usage - Return how many pipe buffers are in use * @pipe: the pipe
*/ staticinlineunsignedint pipe_buf_usage(conststruct pipe_inode_info *pipe)
{ return pipe_occupancy(pipe->head, pipe->tail);
}
/** * pipe_buf - Return the pipe buffer for the specified slot in the pipe ring * @pipe: The pipe to access * @slot: The slot of interest
*/ staticinlinestruct pipe_buffer *pipe_buf(conststruct pipe_inode_info *pipe, unsignedint slot)
{ return &pipe->bufs[slot & (pipe->ring_size - 1)];
}
/** * pipe_head_buf - Return the pipe buffer at the head of the pipe ring * @pipe: The pipe to access
*/ staticinlinestruct pipe_buffer *pipe_head_buf(conststruct pipe_inode_info *pipe)
{ return pipe_buf(pipe, pipe->head);
}
/** * pipe_buf_get - get a reference to a pipe_buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer to get a reference to * * Return: %true if the reference was successfully obtained.
*/ staticinline __must_check bool pipe_buf_get(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
{ return buf->ops->get(pipe, buf);
}
/** * pipe_buf_release - put a reference to a pipe_buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer to put a reference to
*/ staticinlinevoid pipe_buf_release(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
{ conststruct pipe_buf_operations *ops = buf->ops;
buf->ops = NULL;
ops->release(pipe, buf);
}
/** * pipe_buf_confirm - verify contents of the pipe buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer to confirm
*/ staticinlineint pipe_buf_confirm(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
{ if (!buf->ops->confirm) return 0; return buf->ops->confirm(pipe, buf);
}
/** * pipe_buf_try_steal - attempt to take ownership of a pipe_buffer * @pipe: the pipe that the buffer belongs to * @buf: the buffer to attempt to steal
*/ staticinlinebool pipe_buf_try_steal(struct pipe_inode_info *pipe, struct pipe_buffer *buf)
{ if (!buf->ops->try_steal) returnfalse; return buf->ops->try_steal(pipe, buf);
}
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ #define PIPE_SIZE PAGE_SIZE
/* Wait for a pipe to be readable/writable while dropping the pipe lock */ void pipe_wait_readable(struct pipe_inode_info *); void pipe_wait_writable(struct pipe_inode_info *);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.