/* * Copyright (C) 2012-2017 Samsung Electronics, Inc. * * This software is licensed under the terms of the GNU General Public * License version 2, as published by the Free Software Foundation, and * may be copied, distributed, and modified under those terms. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef __LIB_CIRC_BUF_H__ #define __LIB_CIRC_BUF_H__ #include /* One more byte is used for differentiating between empty and full buffer */ #define CIRC_BUF_EMPTY_FLAG_SIZE 1 #define CIRC_BUF_META_SIZE (sizeof(struct circ_buf) + CIRC_BUF_EMPTY_FLAG_SIZE) struct circ_buf { u32 write_count; u32 read_count; char buffer[]; } __packed; struct circ_buf_desc { struct circ_buf *circ_buf; unsigned int size; /* These are local copies of circ_buf counters * for tracking actual state (circ_buf counters are shared * between reader and writer and thus should only be updated * when new state is ok for the reader to see). */ unsigned int write_count; unsigned int read_count; }; enum circ_buf_user_mode { CIRC_BUF_MODE_KERNEL, CIRC_BUF_MODE_USER, CIRC_BUF_MODE_DROP }; /** * Function creates circ_buf_desc structure with circ_buf of specified size. * @param[in] size size of circ_buf * @return descriptor of allocated circ_buf, or NULL if allocation failed */ struct circ_buf_desc *circ_buf_create(unsigned long size); /** * Function destroys circ_buf_desc structure along with its circ_buf. * @param[in] circ_buf_desc descriptor of buffer to destroy */ void circ_buf_destroy(struct circ_buf_desc *circ_buf_desc); /** * Function allocates circ_buf_desc structure and initializes its fields. * @return allocated circ_buf descriptor, or NULL if allocation failed */ struct circ_buf_desc *circ_buf_desc_alloc(void); /** * Function sets circ_buf_desc structure pointing to previously allocated buffer * and initializes its fields. * @return allocated circ_buf descriptor, or NULL if allocation failed */ struct circ_buf *circ_buf_set(void *buf); /** * Function frees circ_buf descriptor. * @param[in] circ_buf_desc circ_buf descriptor to free */ void circ_buf_desc_free(struct circ_buf_desc *circ_buf_desc); /** * Function allocates circ_buf of specified size. * @param[in] size size of circ_buf * @return pointer to allocated circ_buf, or NULL of allocation failed */ struct circ_buf *circ_buf_alloc(unsigned long size); /** * Function frees circ_buf. * @param[in] circ_buf circ_buf to free */ void circ_buf_free(struct circ_buf *circ_buf); /** * Function initialized circ_buf to be empty. * @param[in] circ_buf circ_buf to initialize */ void circ_buf_init(struct circ_buf *circ_buf); /** * Function connects circ_buf of specified size to the circ_buf desc. * @param[in] circ_buf_desc descriptor to connect circ_buf to * @param[in] circ_buf circ_buf to connect * @param[in] size size of circ_buf * @return error code */ void circ_buf_connect(struct circ_buf_desc *circ_buf_desc, struct circ_buf *circ_buf, unsigned long size); /** * Function writes specified buf to circ_buf and updates * circ_buf write counter. * @param[in] circ_buf_desc descriptor of circ_buf to write buf to * @param[in] buf input buf to write to circ_buf * @param[in] length amount of bytes to write * @param[in] mode enum indicating whether passed buf * belongs to userspace or kernel memory * @return number on bytes written on success or error code */ ssize_t circ_buf_write(struct circ_buf_desc *circ_buf_desc, const char *buf, size_t length, enum circ_buf_user_mode mode); /** * Function writes specified buf to circ_buf without updating circ_buf write counter. * @param[in] circ_buf_desc descriptor of circ_buf to write buf to * @param[in] buf input buf to write to circ_buf * @param[in] length amount of bytes to write * @param[in] mode enum indicating whether passed buf * belongs to userspace or kernel memory * @return number of bytes written on success or error code */ ssize_t circ_buf_write_local(struct circ_buf_desc *circ_buf_desc, const char *buf, size_t length, enum circ_buf_user_mode mode); /** * Function reads contents of circ_buf to output buf and updates * circ_buf read counter. * @param[in] circ_buf_desc descriptor of circ_buf to read from * @param[in] buf output buf to read from circ_buf * @param[in] length amount of bytes to read * @param[in] mode enum indicating whether passed buf * belongs to userspace or kernel memory, * or contents of circ_buf must be simply dropped. * @return number of bytes read on success or error code */ ssize_t circ_buf_read(struct circ_buf_desc *circ_buf_desc, char *buf, size_t length, enum circ_buf_user_mode mode); /** * Function reads contents of circ_buf to output buf without updating circ_buf read counter. * @param[in] circ_buf_desc descriptor of circ_buf to read from * @param[in] buf output buf to read from circ_buf * @param[in] length amount of bytes to read * @param[in] mode enum indicating whether passed buf * belongs to userspace or kernel memory, * or contents of circ_buf must be simply dropped. * @return number of bytes read on success or error code */ ssize_t circ_buf_read_local(struct circ_buf_desc *circ_buf_desc, char *buf, size_t length, enum circ_buf_user_mode mode); /** * Function reads contents of circ_buf by specified offset from read_count, * not updating circ_buf read counter. Not intended to be used by clients, * required for API extensions. * @param[in] circ_buf_desc descriptor of circ_buf to read from * @param[in] buf output buf to read from circ_buf * @param[in] length amount of bytes to read * @param[in] offset offset from read_count to start reading from * @param[in] mode enum indicating whether passed buf * belongs to userspace or kernel memory, * or contents of circ_buf must be simply dropped. * @return number of bytes read on success or error code */ ssize_t __circ_buf_read_local(struct circ_buf_desc *circ_buf_desc, char *buf, size_t length, size_t offset, enum circ_buf_user_mode mode); /** * Function updates circ_buf write counter, so reader can see new value. * @param[in] circ_buf_desc descriptor of circ_buf to update counter in */ void circ_buf_flush_write(struct circ_buf_desc *circ_buf_desc); /** * Function updates circ_buf read counter, so writer can see new value. * @param[in] circ_buf_desc descriptor of circ_buf to update counter in */ void circ_buf_flush_read(struct circ_buf_desc *circ_buf_desc); /** * Function restores circ_buf_desc write counter to the value its circ_buf has. * @param[in] circ_buf_desc descriptor of circ_buf to update counter in */ void circ_buf_rollback_write(struct circ_buf_desc *circ_buf_desc); /** * Function restores circ_buf_desc read counter to the value its circ_buf has. * @param[in] circ_buf_desc descriptor of circ_buf to update counter in */ void circ_buf_rollback_read(struct circ_buf_desc *circ_buf_desc); /** * Function checks if circ_buf is empty. * Should be used with care, because result is not guaranteed to be valid * after the access, unless there is external locking mechanism. * @param[in] circ_buf_desc descriptor of circ_buf to check * @return non-0 is circ_buf is empty and 0 otherwise */ unsigned int circ_buf_is_empty(struct circ_buf_desc *circ_buf_desc); /** * Function checks if circ_buf is full. * Should be used with care, because result is not guaranteed to be valid * after the access, unless there is external locking mechanism. * @param[in] circ_buf_desc descriptor of circ_buf to check * @return non-0 is circ_bufis full and 0 otherwise */ unsigned int circ_buf_is_full(struct circ_buf_desc *circ_buf_desc); /** * Function calculates amount of bytes in buffer currently available to write. * Should be used with care, because result is not guaranteed to be valid * after the access, unless there is external locking mechanism. * @param[in] circ_buf_desc descriptor of circ_buf to check * @return number of free bytes */ size_t circ_buf_bytes_free(struct circ_buf_desc *circ_buf_desc); /** * Function calculates amount of bytes written in buffer and not read yet. * Should be used with care, because result is not guaranteed to be valid * after the access, unless there is external locking mechanism. * @param[in] circ_buf_desc descriptor of circ_buf to check * @return number of used bytes */ size_t circ_buf_bytes_used(struct circ_buf_desc *circ_buf_desc); #endif /* __LIB_CIRC_BUF_H__ */