From owner-freebsd-arch@FreeBSD.ORG Wed Feb 8 05:49:46 2012 Return-Path: Delivered-To: freebsd-arch@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id CA77B1065674; Wed, 8 Feb 2012 05:49:46 +0000 (UTC) (envelope-from brde@optusnet.com.au) Received: from mail08.syd.optusnet.com.au (mail08.syd.optusnet.com.au [211.29.132.189]) by mx1.freebsd.org (Postfix) with ESMTP id 385BB8FC0A; Wed, 8 Feb 2012 05:49:45 +0000 (UTC) Received: from c211-30-171-136.carlnfd1.nsw.optusnet.com.au (c211-30-171-136.carlnfd1.nsw.optusnet.com.au [211.30.171.136]) by mail08.syd.optusnet.com.au (8.13.1/8.13.1) with ESMTP id q185nfS8015540 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Wed, 8 Feb 2012 16:49:43 +1100 Date: Wed, 8 Feb 2012 16:49:41 +1100 (EST) From: Bruce Evans X-X-Sender: bde@besplex.bde.org To: Giovanni Trematerra In-Reply-To: Message-ID: <20120208151251.J1853@besplex.bde.org> References: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII; format=flowed X-Mailman-Approved-At: Wed, 08 Feb 2012 06:20:03 +0000 Cc: flo@FreeBSD.org, Kip Macy , John Baldwin , Peter Holm , Attilio Rao , Konstantin Belousov , bde@FreeBSD.org, freebsd-arch@FreeBSD.org, jilles@FreeBSD.org Subject: Re: [LAST ROUND] fifo/pipe merge code X-BeenThere: freebsd-arch@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: Discussion related to FreeBSD architecture List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 08 Feb 2012 05:49:46 -0000 On Tue, 7 Feb 2012, Giovanni Trematerra wrote: > Hi All, > Here a commit candidate patch of the experimental one posted on Jan 8 > http://www.trematerra.net/patches/pipefifo_merge.4.3.patch > > The patch aims to > - not introduce any performance regressions in pipe code > - speed up performance for fifos > - not introduce any regressions > - fifos and pipes have to have the same behavior as before the patch. > - share as much code as possible between pipes and fifos. > > The patch is greatly improved from its first experimental form. > Now it's more clean and compact and integrates all the good suggestions > from previous reviewers. Here some of the major differences: > - no more different UMA zones to allocate things. > - no more pipeinfo structure. > - fix a bug at fifo_close. > - fix a different behavior for fifos during truncate (thanks to jilles). > > The patch was reviewed in a previous form by jhb@, bde@, jilles@, > attilio@(only style bug) > This version of the patch was reviewed privately by jilles@, > attilio@(only style bug) It looks quite good now. I see only a few minor style bugs: % diff --git a/sys/fs/fifofs/fifo_vnops.c b/sys/fs/fifofs/fifo_vnops.c % index 94a2713..0d35877 100644 % --- a/sys/fs/fifofs/fifo_vnops.c % +++ b/sys/fs/fifofs/fifo_vnops.c % ... % +int % +fifo_iseof(struct file *fp) % ... % + KASSERT(fp->f_vnode != NULL, ("fifo_iseof: no vnode info.")); % + KASSERT(fp->f_vnode->v_fifoinfo != NULL, ("fifo_iseof: no fifoinfo.")); Error messages should not be terminated by a ".". All other KASSERT()s in this file and in sys_pipe.c follow this rule. But 1 old one in sys_pipe.c is terminated by a "!", and some in sys_pipe.c don't follow the rule that error messages should not be capitalized. I wonder if you can assert that some suitable lock is held here. % + fip = fp->f_vnode->v_fifoinfo; % + return (fp->f_seqcount == fip->fi_wgen); % } % ... % diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c % index 9edcb74..5892e9f 100644 % --- a/sys/kern/sys_pipe.c % +++ b/sys/kern/sys_pipe.c % @@ -1,4 +1,5 @@ % /*- % + * Copyright (c) 2012 Giovanni Trematerra % * Copyright (c) 1996 John S. Dyson % * All rights reserved. % * Copyrights should be in historical order, as in fifo_vnops.c. % @@ -135,6 +138,10 @@ __FBSDID("$FreeBSD$"); % */ % /* #define PIPE_NODIRECT */ % % +#define PIPE_PEER(pipe) \ % + (((pipe)->pipe_state & PIPE_NAMED) ? \ % + (pipe) : ((pipe)->pipe_peer)) % + This has strange indentation for the macro body, and weird indentation for the backslashes to not line them up at all. With more normal indentation, there is no need to split the macro body and thus not enough backslashes to need lining up: %%% #define PIPE_PEER(pipe) \ (((pipe)->pipe_state & PIPE_NAMED) ? (pipe) : ((pipe)->pipe_peer)) %%% % ... % @@ -175,6 +184,11 @@ static struct filterops pipe_wfiltops = { % .f_detach = filt_pipedetach, % .f_event = filt_pipewrite % }; % +static struct filterops pipe_nfiltops = { % + .f_isfd = 1, % + .f_detach = filt_pipedetach_notsup, % + .f_event = filt_pipenotsup % +}; This should probably be sorted before the others (order nrw, not rwn). % % /* % * Default pipe buffer size(s), this can be kind-of large now because pipe % @@ -220,6 +234,7 @@ static void pipe_clone_write_buffer(struct pipe *wpipe); % static int pipespace(struct pipe *cpipe, int size); % static int pipespace_new(struct pipe *cpipe, int size); % % +static int pipe_paircreate(struct thread *td, struct pipepair **p_pp); % static int pipe_zone_ctor(void *mem, int size, void *arg, int flags); % static int pipe_zone_init(void *mem, int size, int flags); % static void pipe_zone_fini(void *mem, int size); This seems to be unsorted. I see no reason to sort it with the pipe_zone constriuctors and desstructors, especially if you don't name it pipe_zone_*. The declarations of lots of other constructors are unsorted into the main list. Old style bugs: the pipe_zone functions shouldn't be in a separate section and that section shouldn't have a different indentation style (although that style is closer to KNF), especially since these functions are more systematically named than the others (the zone_ in their prefix keeps them together when they are sorted alphabetically). % @@ -1284,6 +1348,17 @@ pipe_ioctl(fp, cmd, data, active_cred, td) % break; % % case FIONREAD: % + Extra blank line. % + /* % + * FIONREAD will return 0 for non-readable descriptors, and % + * the results of FIONREAD on the read pipe for readable % + * descriptors. % + */ % + if (!(fp->f_flag & FREAD)) { % + *(int *)data = 0; % + PIPE_UNLOCK(mpipe); % + return (0); % + } % if (mpipe->pipe_state & PIPE_DIRECTW) % *(int *)data = mpipe->pipe_map.cnt; % else Urk, now I see many major style bugs: % @@ -1333,47 +1408,55 @@ pipe_poll(fp, events, active_cred, td) % int error; % #endif % % - wpipe = rpipe->pipe_peer; % + wpipe = PIPE_PEER(rpipe); % PIPE_LOCK(rpipe); % #ifdef MAC % error = mac_pipe_check_poll(active_cred, rpipe->pipe_pair); % if (error) % goto locked_error; % #endif % - if (events & (POLLIN | POLLRDNORM)) % - if ((rpipe->pipe_state & PIPE_DIRECTW) || % - (rpipe->pipe_buffer.cnt > 0)) % - revents |= events & (POLLIN | POLLRDNORM); % - % - if (events & (POLLOUT | POLLWRNORM)) % - if (wpipe->pipe_present != PIPE_ACTIVE || % - (wpipe->pipe_state & PIPE_EOF) || % - (((wpipe->pipe_state & PIPE_DIRECTW) == 0) && % - ((wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= PIPE_BUF || % - wpipe->pipe_buffer.size == 0))) % - revents |= events & (POLLOUT | POLLWRNORM); % - % - if ((events & POLLINIGNEOF) == 0) { % - if (rpipe->pipe_state & PIPE_EOF) { % - revents |= (events & (POLLIN | POLLRDNORM)); % - if (wpipe->pipe_present != PIPE_ACTIVE || % - (wpipe->pipe_state & PIPE_EOF)) % - revents |= POLLHUP; % + if (fp->f_flag & FREAD) { % + if (events & (POLLIN | POLLRDNORM)) % + if ((rpipe->pipe_state & PIPE_DIRECTW) || % + (rpipe->pipe_buffer.cnt > 0)) % + revents |= events & (POLLIN | POLLRDNORM); % + This part of the patch is still unreadable since it indents everything to add FREAD and FWRITE checks. I don't like those anyway (they should probably produce POLLERR POLLNVAL instead of ignoring the error -- see previous mail), but they are needed for now for compatibility in the FIFO case (hopefully they don't break compatibility for the plain pipe case). To avoid churning this code for them now and later when the behaviour is fixed, they should be added in a non-invasive way like the old fifo code did. That involved using && instead of a nested if. In the old code, everything was under the combined && if. Now there are 3 nested ifs. This logic change seems to be non-null and give bugs (1). % + if (rpipe->pipe_state & PIPE_NAMED) % + if (fifo_iseof(fp)) Here the (unrelated) nested if is just a style bug. It gives verboseness and extra indentation. % + events |= POLLINIGNEOF; % + (1) In the old code, POLLINIGNEOF was only set here if we are polling for some input condition (and this is valid). Now it is set if the file is just open for input. Either way could be right, but this is a change. If we are not polling for input, we don't care about it, but POSIX requires POLLHUP to be set in some cases, and this affects whether we return or block, and POLLINIGNEOF interacts with this subtly. There may also be a problem not going through here to set POLLINIGNEOF in the !FREAD case. % + if ((events & POLLINIGNEOF) == 0) { % + if (rpipe->pipe_state & PIPE_EOF) { % + revents |= (events & (POLLIN | POLLRDNORM)); % + if (wpipe->pipe_present != PIPE_ACTIVE || % + (wpipe->pipe_state & PIPE_EOF)) % + revents |= POLLHUP; % + } % } This is the old sys_pipe.c logic, indented under the FREAD condition. It is also move up to be inside the FREAD block. To avoid the re-indentation, repeat the FREAD test in and && condition. After avoiding all re-indentations by repeating FREAD and FWRITE tests, you don't need to re-order either. % } This is not consistently verbose in adding extra blank lines. % + if (fp->f_flag & FWRITE) % + if (events & (POLLOUT | POLLWRNORM)) % + if (wpipe->pipe_present != PIPE_ACTIVE || % + (wpipe->pipe_state & PIPE_EOF) || % + (((wpipe->pipe_state & PIPE_DIRECTW) == 0) && % + ((wpipe->pipe_buffer.size - wpipe->pipe_buffer.cnt) >= % + PIPE_BUF || wpipe->pipe_buffer.size == 0))) % + revents |= events & (POLLOUT | POLLWRNORM); % I don't like excessive braces, but this statement needs unnecessary ones. It should also be written using &&, not using a nested if. Since there is nothing like POLLINIGNEOF to complicate things, only 1 if statement is needed for FWRITE (until we get to slrecording). % if (revents == 0) { % - if (events & (POLLIN | POLLRDNORM)) { % - selrecord(td, &rpipe->pipe_sel); % - if (SEL_WAITING(&rpipe->pipe_sel)) % - rpipe->pipe_state |= PIPE_SEL; % - } % + if (fp->f_flag & FREAD) % + if (events & (POLLIN | POLLRDNORM)) { Use && here. It already has sufficient braces, at least after this change. % + selrecord(td, &rpipe->pipe_sel); % + if (SEL_WAITING(&rpipe->pipe_sel)) % + rpipe->pipe_state |= PIPE_SEL; % + } % % - if (events & (POLLOUT | POLLWRNORM)) { % - selrecord(td, &wpipe->pipe_sel); % - if (SEL_WAITING(&wpipe->pipe_sel)) % - wpipe->pipe_state |= PIPE_SEL; % - } % + if (fp->f_flag & FWRITE) % + if (events & (POLLOUT | POLLWRNORM)) { Use && here, as above. % + selrecord(td, &wpipe->pipe_sel); % + if (SEL_WAITING(&wpipe->pipe_sel)) % + wpipe->pipe_state |= PIPE_SEL; % + } % } % #ifdef MAC % locked_error: % ... % diff --git a/sys/sys/pipe.h b/sys/sys/pipe.h % index 20b1092..479223f 100644 % --- a/sys/sys/pipe.h % +++ b/sys/sys/pipe.h % ... % @@ -138,5 +139,9 @@ struct pipepair { % #define PIPE_UNLOCK(pipe) mtx_unlock(PIPE_MTX(pipe)) % #define PIPE_LOCK_ASSERT(pipe, type) mtx_assert(PIPE_MTX(pipe), (type)) % % +extern struct fileops pipeops; This should be declared in the existing extern section for data at the top of the file. That section has just one declaration. Old bug: that section has a bogus comment. It says /* See sys_pipe.c for info on what these limits mean. */" (actually a block comment to be verbose about this unimportant and misdescribed point), but there are no limits here; there is just 1 variable declaration. There are many more variables and limits, but the others are all in sys_pipe.c. This one (maxpipekva) unfortunately has to be declared here so that subr_param.c can initialize it, but this is an implementation detail unrelated to the meaning of this variable. maxpipekva is also instantiated in a wrong place (in subr_param.c instead of in sys_pipe.c). % + % +int pipe_fifo_ctor(struct pipe **ppipe, struct thread *td); % +void pipe_dtor(struct pipe *dpipe); These are sorted backwards. They aren't really even in logical order (ctor before dtor, which is also alphabetical), because the ctor is for fifos only but the dtor is generic. % % #endif /* !_SYS_PIPE_H_ */ Bruce