📄 pipe.c
字号:
*/int rt_pipe_delete (RT_PIPE *pipe){ int err; spl_t s; if (xnpod_asynch_p()) return -EPERM; xnlock_get_irqsave(&nklock,s); pipe = xeno_h2obj_validate(pipe,XENO_PIPE_MAGIC,RT_PIPE); if (!pipe) { err = xeno_handle_error(pipe,XENO_PIPE_MAGIC,RT_PIPE); xnlock_put_irqrestore(&nklock,s); return err; } if (__test_and_clear_bit(0,&pipe->flushable)) { /* Purge data waiting for flush. */ removeq(&__pipe_flush_q,&pipe->link); rt_pipe_free(pipe,pipe->buffer); } err = xnpipe_disconnect(pipe->minor);#ifdef CONFIG_XENO_OPT_REGISTRY if (pipe->handle) xnregistry_remove(pipe->handle);#endif /* CONFIG_XENO_OPT_REGISTRY */ xeno_mark_deleted(pipe); xnlock_put_irqrestore(&nklock,s); if (pipe->bufpool == &pipe->privpool) xnheap_destroy(&pipe->privpool,__pipe_flush_pool,NULL); return err;}/** * @fn ssize_t rt_pipe_receive(RT_PIPE *pipe,RT_PIPE_MSG **msgp,RTIME timeout) * * @brief Receive a message from a pipe. * * This service retrieves the next message written to the associated * special device in user-space. rt_pipe_receive() always preserves * message boundaries, which means that all data sent through the same * write(2) operation to the special device will be gathered in a * single message by this service. This service differs from * rt_pipe_read() in that it returns a pointer to the internal buffer * holding the message, which improves performances by saving a data * copy to a user-provided buffer, especially when large messages are * involved. * * Unless otherwise specified, the caller is blocked for a given * amount of time if no data is immediately available on entry. * * @param pipe The descriptor address of the pipe to receive from. * * @param msgp A pointer to a memory location which will be written * upon success with the address of the received message. Once * consumed, the message space should be freed using rt_pipe_free(). * The application code can retrieve the actual data and size carried * by the message by respectively using the P_MSGPTR() and P_MSGSIZE() * macros. * * @param timeout The number of clock ticks to wait for some message * to arrive (see note). Passing TM_INFINITE causes the caller to * block indefinitely until some data is eventually available. Passing * TM_NONBLOCK causes the service to return immediately without * waiting if no data is available on entry. * * @return The number of read bytes available from the received * message is returned upon success; this value will be equal to * P_MSGSIZE(*msgp). Otherwise: * * - -EINVAL is returned if @a pipe is not a pipe descriptor. * * - -EIDRM is returned if @a pipe is a closed pipe descriptor. * * - -ENODEV or -EBADF are returned if @a pipe is scrambled. * * - -ETIMEDOUT is returned if @a timeout is different from * TM_NONBLOCK and no data is available within the specified amount of * time. * * - -EWOULDBLOCK is returned if @a timeout is equal to TM_NONBLOCK * and no data is immediately available on entry. * * - -EINTR is returned if rt_task_unblock() has been called for the * waiting task before any data was available. * * - -EPERM is returned if this service should block, but was called * from a context which cannot sleep (e.g. interrupt, non-realtime or * scheduler locked). * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * only if @a timeout is equal to TM_NONBLOCK. * * - Kernel-based task * * Rescheduling: always unless the request is immediately satisfied or * @a timeout specifies a non-blocking operation. * * @note This service is sensitive to the current operation mode of * the system timer, as defined by the rt_timer_start() service. In * periodic mode, clock ticks are interpreted as periodic jiffies. In * oneshot mode, clock ticks are interpreted as nanoseconds. */ssize_t rt_pipe_receive (RT_PIPE *pipe, RT_PIPE_MSG **msgp, RTIME timeout){ ssize_t n; spl_t s; if (timeout != TM_NONBLOCK && xnpod_unblockable_p()) return -EPERM; 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; } n = xnpipe_recv(pipe->minor,msgp,timeout); unlock_and_exit: xnlock_put_irqrestore(&nklock,s); return n;}/** * @fn ssize_t rt_pipe_read(RT_PIPE *pipe,void *buf,size_t size,RTIME timeout) * * @brief Read a message from a pipe. * * This service retrieves the next message written to the associated * special device in user-space. rt_pipe_read() always preserves * message boundaries, which means that all data sent through the same * write(2) operation to the special device will be gathered in a * single message by this service. This services differs from * rt_pipe_receive() in that it copies back the payload data to a * user-defined memory area, instead of returning a pointer to the * internal message buffer holding such data. * * Unless otherwise specified, the caller is blocked for a given * amount of time if no data is immediately available on entry. * * @param pipe The descriptor address of the pipe to read from. * * @param buf A pointer to a memory location which will be written * upon success with the read message contents. * * @param size The count of bytes from the received message to read up * into @a buf. If @a size is lower than the actual message size, * -ENOBUFS is returned since the incompletely received message would * be lost. If @a size is zero, this call returns immediately with no * other action. * * @param timeout The number of clock ticks to wait for some message * to arrive (see note). Passing TM_INFINITE causes the caller to * block indefinitely until some data is eventually available. Passing * TM_NONBLOCK causes the service to return immediately without * waiting if no data is available on entry. * * @return The number of read bytes copied to the @a buf is returned * upon success. Otherwise: * * - -EINVAL is returned if @a pipe is not a pipe descriptor. * * - -EIDRM is returned if @a pipe is a closed pipe descriptor. * * - -ENODEV or -EBADF are returned if @a pipe is scrambled. * * - -ETIMEDOUT is returned if @a timeout is different from * TM_NONBLOCK and no data is available within the specified amount of * time. * * - -EWOULDBLOCK is returned if @a timeout is equal to TM_NONBLOCK * and no data is immediately available on entry. * * - -EINTR is returned if rt_task_unblock() has been called for the * waiting task before any data was available. * * - -EPERM is returned if this service should block, but was called * from a context which cannot sleep (e.g. interrupt, non-realtime or * scheduler locked). * * - -ENOBUFS is returned if @a size is not large enough to collect the * message data. * * Environments: * * This service can be called from: * * - Kernel module initialization/cleanup code * - Interrupt service routine * only if @a timeout is equal to TM_NONBLOCK. * * - Kernel-based task * - User-space task (switches to primary mode) * * Rescheduling: always unless the request is immediately satisfied or * @a timeout specifies a non-blocking operation. * * @note This service is sensitive to the current operation mode of * the system timer, as defined by the rt_timer_start() service. In * periodic mode, clock ticks are interpreted as periodic jiffies. In * oneshot mode, clock ticks are interpreted as nanoseconds. */ssize_t rt_pipe_read (RT_PIPE *pipe, void *buf, size_t size, RTIME timeout){ RT_PIPE_MSG *msg; ssize_t nbytes; if (size == 0) return 0; nbytes = rt_pipe_receive(pipe,&msg,timeout); if (nbytes < 0) return nbytes; if (size < P_MSGSIZE(msg)) nbytes = -ENOBUFS; else if (P_MSGSIZE(msg) > 0) memcpy(buf,P_MSGPTR(msg),P_MSGSIZE(msg)); /* Zero-sized messages are allowed, so we still need to free the message buffer even if no data copy took place. */ rt_pipe_free(pipe,msg); return nbytes;} /** * @fn ssize_t rt_pipe_send(RT_PIPE *pipe,RT_PIPE_MSG *msg,size_t size,int mode) * * @brief Send a message through a pipe. * * This service writes a complete message to be received from the * associated special device. rt_pipe_send() 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_write() in * that it accepts a canned message buffer, instead of a pointer to * the raw data to be sent. This call is useful whenever the caller * wants to prepare the message contents separately from its sending, * which does not require to have all the data to be sent available at * once but allows for incremental updates of the message, and also * saves a message copy, since rt_pipe_send() deals internally with * message buffers. * * @param pipe The descriptor address of the pipe to send to. * * @param msg The address of the message to be sent. The message * space must have been allocated using the rt_pipe_alloc() service. * Once passed to rt_pipe_send(), the memory pointed to by @a msg is * no more under the control of the application code and thus should * not be referenced by it anymore; deallocation of this memory will * be automatically handled as needed. As a special exception, @a msg * can be NULL and will not be dereferenced if @a size is zero. * * @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. This parameter allows * you to actually send less data than you reserved using the * rt_pipe_alloc() service, which may be the case if you did not * know how much space you needed at the time of allocation. In all * other cases it may be more convenient to just pass P_MSGSIZE(msg). * * Additionally, rt_pipe_send() causes any data buffered by * rt_pipe_stream() to be flushed prior to sending the message. For * this reason, rt_pipe_send() 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. * * - -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_send (RT_PIPE *pipe, RT_PIPE_MSG *msg, size_t size, int mode){ 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); if (n < 0) goto unlock_and_exit; } if (size > 0) /* We need to add the size of the message header here. */ n = xnpipe_send(pipe->minor,msg,size + sizeof(RT_PIPE_MSG),mode); unlock_and_exit: xnlock_put_irqrestore(&nklock,s); return n <= 0 ? n : n - sizeof(RT_PIPE_MSG);} /** * @fn ssize_t rt_pipe_write(RT_PIPE *pipe,const void *buf,size_t size,int mode) * * @brief Write a message to a pipe. * * This service writes a complete message to be received from the
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -