⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pipe.c

📁 xenomai 很好的linux实时补丁
💻 C
📖 第 1 页 / 共 3 页
字号:
 * associated special device. rt_pipe_write() always preserves message * boundaries, which means that all data sent through a single call of * this service will be gathered in a single read(2) operation from * the special device. This service differs from rt_pipe_send() in * that it accepts a pointer to the raw data to be sent, instead of a * canned message buffer. This call is useful whenever the caller does * not need to prepare the message contents separately from its * sending. * * @param pipe The descriptor address of the pipe to write to. * * @param buf The address of the first data byte to send. The * data will be copied to an internal buffer before transmission. * * @param size The size in bytes of the message (payload data * only). Zero is a valid value, in which case the service returns * immediately without sending any message. * * Additionally, rt_pipe_write() causes any data buffered by * rt_pipe_stream() to be flushed prior to sending the message. For * this reason, rt_pipe_write() can return a non-zero byte count to * the caller if some pending data has been flushed, even if @a size * was zero on entry. * * @param mode A set of flags affecting the operation: * * - P_URGENT causes the message to be prepended to the output * queue, ensuring a LIFO ordering. * * - P_NORMAL causes the message to be appended to the output * queue, ensuring a FIFO ordering. * * @return Upon success, this service returns @a size if the latter is * non-zero, or the number of bytes flushed otherwise. Upon error, one * of the following error codes is returned: * * - -EINVAL is returned if @a pipe is not a pipe descriptor. * * - -EPIPE is returned if the associated special device is not yet * open. * * - -ENOMEM is returned if not enough buffer space is available to * complete the operation. * * - -EIDRM is returned if @a pipe is a closed pipe descriptor. * * - -ENODEV or -EBADF are returned if @a pipe is scrambled. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task * * Rescheduling: possible. */ssize_t rt_pipe_write (RT_PIPE *pipe,		       const void *buf,		       size_t size,		       int mode){    RT_PIPE_MSG *msg;    ssize_t nbytes;    if (size == 0)	/* Try flushing the streaming buffer in any case. */	return rt_pipe_send(pipe,NULL,0,mode);    msg = rt_pipe_alloc(pipe,size);    if (!msg)	return -ENOMEM;    memcpy(P_MSGPTR(msg),buf,size);    nbytes = rt_pipe_send(pipe,msg,size,mode);    if (nbytes != size)	/* If the operation failed, we need to free the message buffer	   by ourselves. */       rt_pipe_free(pipe,msg);    return nbytes;}/** * @fn ssize_t rt_pipe_stream(RT_PIPE *pipe,const void *buf,size_t size) * * @brief Stream bytes to a pipe. * * This service writes a sequence of bytes to be received from the * associated special device. Unlike rt_pipe_send(), this service does * not preserve message boundaries. Instead, an internal buffer is * filled on the fly with the data. The actual sending may be delayed * until the internal buffer is full, or the Linux kernel is * re-entered after the real-time system enters a quiescent state. * * Data buffers sent by the rt_pipe_stream() service are always * transmitted in FIFO order (i.e. P_NORMAL mode). * * @param pipe The descriptor address of the pipe to write to. * * @param buf The address of the first data byte to send. The * data will be copied to an internal buffer before transmission. * * @param size The size in bytes of the buffer. Zero is a valid value, * in which case the service returns immediately without buffering any * data. * * @return The number of sent bytes upon success; this value will be * equal to @a size. Otherwise: * * - -EINVAL is returned if @a pipe is not a pipe descriptor. * * - -EPIPE is returned if the associated special device is not yet * open. * * - -ENOMEM is returned if not enough buffer space is available to * complete the operation. * * - -EIDRM is returned if @a pipe is a closed pipe descriptor. * * - -ENODEV or -EBADF are returned if @a pipe is scrambled. * * - -ENOSYS is returned if the byte streaming mode has been disabled * at configuration time by nullifying the size of the pipe buffer * (see CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ). * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * - User-space task * * Rescheduling: possible. */ssize_t rt_pipe_stream (RT_PIPE *pipe,			const void *buf,			size_t size){    ssize_t outbytes = 0;    size_t n;    spl_t s;#if CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ <= 0    return -ENOSYS;#else /* CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ > 0 */    xnlock_get_irqsave(&nklock,s);    pipe = xeno_h2obj_validate(pipe,XENO_PIPE_MAGIC,RT_PIPE);    if (!pipe)	{	outbytes = xeno_handle_error(pipe,XENO_PIPE_MAGIC,RT_PIPE);	goto unlock_and_exit;	}    while (size > 0)	{	if (size >= CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ - pipe->fillsz)	    n = CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ - pipe->fillsz;	else	    n = size;	if (n == 0)	    {	    ssize_t err = __pipe_flush(pipe);	    if (__test_and_clear_bit(0,&pipe->flushable))		removeq(&__pipe_flush_q,&pipe->link);	    if (err < 0)		{		outbytes = err;		goto unlock_and_exit;		}	    continue;	    }	if (pipe->buffer == NULL)	    {           pipe->buffer = rt_pipe_alloc(pipe,CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ);	    if (pipe->buffer == NULL)		{		outbytes = -ENOMEM;		goto unlock_and_exit;		}	    }	memcpy(P_MSGPTR(pipe->buffer) + pipe->fillsz,(caddr_t)buf + outbytes,n);	pipe->fillsz += n;	outbytes += n;	size -= n;	}    /* The flushable bit is not that elegant, but we must make sure       that we won't enqueue the pipe descriptor twice in the flush       queue, but we still have to enqueue it before the virq is made       pending if necessary since it could preempt a Linux-based       caller, so... */    if (pipe->fillsz > 0 && !__test_and_set_bit(0,&pipe->flushable))	{	appendq(&__pipe_flush_q,&pipe->link);	rthal_apc_schedule(__pipe_flush_apc);	} unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return outbytes;#endif /* CONFIG_XENO_OPT_NATIVE_PIPE_BUFSZ <= 0 */}/** * @fn ssize_t rt_pipe_flush(RT_PIPE *pipe) * * @brief Flush the pipe. * * This service flushes any pending data buffered by rt_pipe_stream(). * This operation makes the data available for reading from the * associated special device. * * @param pipe The descriptor address of the pipe to flush. * * @return The number of bytes flushed upon success. Otherwise: * * - -EINVAL is returned if @a pipe is not a pipe descriptor. * * - -EPIPE is returned if the associated special device is not yet * open. * * - -EIDRM is returned if @a pipe is a closed pipe descriptor. * * - -ENODEV or -EBADF are returned if @a pipe is scrambled. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * * Rescheduling: possible. */ssize_t rt_pipe_flush (RT_PIPE *pipe){    ssize_t n = 0;    spl_t s;    xnlock_get_irqsave(&nklock,s);    pipe = xeno_h2obj_validate(pipe,XENO_PIPE_MAGIC,RT_PIPE);    if (!pipe)	{	n = xeno_handle_error(pipe,XENO_PIPE_MAGIC,RT_PIPE);	goto unlock_and_exit;	}    if (__test_and_clear_bit(0,&pipe->flushable))	{	removeq(&__pipe_flush_q,&pipe->link);	n = __pipe_flush(pipe);	} unlock_and_exit:    xnlock_put_irqrestore(&nklock,s);    return n <= 0 ? n : n - sizeof(RT_PIPE_MSG);}/** * @fn RT_PIPE_MSG *rt_pipe_alloc(RT_PIPE *pipe,size_t size) * * @brief Allocate a message pipe buffer. * * This service allocates a message buffer from the pipe's heap which * can be subsequently filled by the caller then passed to * rt_pipe_send() for sending. The beginning of the available data * area of @a size contiguous bytes is accessible from P_MSGPTR(msg). * * @param pipe The descriptor address of the affected pipe. * * @param size The requested size in bytes of the buffer. This value * should represent the size of the payload data. * * @return The address of the allocated message buffer upon success, * or NULL if the allocation fails. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * * Rescheduling: never. */RT_PIPE_MSG *rt_pipe_alloc (RT_PIPE *pipe,                            size_t size){    RT_PIPE_MSG *msg = (RT_PIPE_MSG *)xnheap_alloc(pipe->bufpool,size + sizeof(RT_PIPE_MSG));    if (msg)	{	inith(&msg->link);	msg->size = size;	}    return msg;}/** * @fn int rt_pipe_free(RT_PIPE *pipe,RT_PIPE_MSG *msg) * * @brief Free a message pipe buffer. * * This service releases a message buffer returned by * rt_pipe_receive() to the pipe's heap. * * @param pipe The descriptor address of the affected pipe. * * @param msg The address of the message buffer to free. * * @return 0 is returned upon success, or -EINVAL if @a msg is not a * valid message buffer previously allocated by the rt_pipe_alloc() * service. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * - Kernel-based task * * Rescheduling: never. */int rt_pipe_free (RT_PIPE *pipe,RT_PIPE_MSG *msg){    return xnheap_free(pipe->bufpool,msg);}/*@}*/EXPORT_SYMBOL(rt_pipe_create);EXPORT_SYMBOL(rt_pipe_delete);EXPORT_SYMBOL(rt_pipe_receive);EXPORT_SYMBOL(rt_pipe_send);EXPORT_SYMBOL(rt_pipe_read);EXPORT_SYMBOL(rt_pipe_write);EXPORT_SYMBOL(rt_pipe_stream);EXPORT_SYMBOL(rt_pipe_flush);EXPORT_SYMBOL(rt_pipe_alloc);EXPORT_SYMBOL(rt_pipe_free);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -