From owner-freebsd-hackers Mon Jun 4 13:16:34 2001 Delivered-To: freebsd-hackers@freebsd.org Received: from ns.skynet.cz (ns.skynet.cz [193.165.192.9]) by hub.freebsd.org (Postfix) with ESMTP id 73C8E37B405; Mon, 4 Jun 2001 13:16:29 -0700 (PDT) (envelope-from dolecek@saruman.ics.muni.cz) Received: from saruman.ics.muni.cz (asasync80.skynet.cz [193.165.192.180]) by ns.skynet.cz (8.9.3/8.9.2) with ESMTP id WAA84108; Mon, 4 Jun 2001 22:16:22 +0200 (CEST) (envelope-from dolecek@saruman.ics.muni.cz) Received: (from dolecek@localhost) by saruman.ics.muni.cz (8.11.4/8.10.1) id f54KIAV00619; Mon, 4 Jun 2001 22:18:10 +0200 (CEST) From: Jaromír Dolecek Message-Id: <200106042018.f54KIAV00619@saruman.ics.muni.cz> Subject: pipe implementation questions To: hackers@freebsd.org Date: Mon, 4 Jun 2001 22:18:10 +0200 (CEST) Cc: alfred@freebsd.org X-Mailer: ELM [version 2.4ME+ PL78 (25)] MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset=US-ASCII Sender: owner-freebsd-hackers@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.ORG Hi folks, I'm working on a port of FreeBSD pipe implementation to NetBSD. So far, the results are pretty owesame, the new pipes are significantly faster than the old socketpair-based ones. Good work! However, I found couple of things I don't quite understand and would like to clarify if this is how things are supposed to work or if I'm consfused :) 1) SIGIO for O_ASYNC reader, sync writer I made a test program which makes a pipe, sets owner of the read end, setup signal handler for SIGIO and switches the read end to O_NONBLOCK|O_ASYNC mode. Program forks, child makes sync write to the write (synchronous) end of pipe. When parents loops calling read() on the read end until it succeeds. However, I found out the parent gets SIGIO for each read(2) attempt. This behaviour seems to be due to last couple of lines of pipe_read(): if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF) pipeselwakeup(rpipe); This condition is commonly true if the reader is polling for input. The code should signal the writer, not the reader - it doesn't make sense to signal possibility of writing more data to the reader itself. IMHO the code should be like: if ((rpipe->pipe_buffer.size - rpipe->pipe_buffer.cnt) >= PIPE_BUF) { struct pipe *wpipe = rpipe->pipe_peer; if (wpipe) pipeselwakeup(wpipe); } Also, the code could possibly only call the pipeselwakeup() if anything was actually read from the pipe previously (or, even better, only once since last write(2)), to avoid sending SIGIO's to the writer if the the reader found the pipe empty. 2) direct write - first uio only FreeBSD direct write code seems to handle only first uio buffer, so e.g. writev(2) with multiple buffers doesn't write all data at once. This is valid behaviour (return short write and expect writer to update itself and try again with rest), I'd like just to ensure I read the code correctly. 3) direct write - loses for huge buffers? It seems pipe_build_write_buffer() tries to fault all the address space specified by uio. However, pipe_map.ms[] has only (BIG_PIPE_SIZE/PAGE_SIZE+1) members, so this seems to lose if the covered address space (size of buffer passed to write(2)) is > 64+4=68KB. Also, the code which calls pmap_qenter() thinks the buffer size is wpipe->pipe_buffer.size + PAGE_SIZE maximum. Do I read the code correctly, or is there anything I miss? The current port to NetBSD doesn't use this particular piece of code (the difference between FreeBSD VM and UVM is too big), but it's something I encountered and would like to understand :) Thanks for you cooperation :) Jaromir P.S. Please CC: me, I'm not on the list -- Jaromir Dolecek http://www.ics.muni.cz/~dolecek/ NetBSD - just plain best OS! -=*=- Got spare MCA cards or docs? Hand me them! To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-hackers" in the body of the message