On Mon, Jul 15, 2019 at 12:14:00PM +0200, Sebastien Marie wrote: > Hi, > > Next move in revisiting pipe initialization. > > After some discussion with mpi@, it seems better to have the whole > `struct pipe' allocation and initialization inside pipe_create() > function, aka moving pool_get() inside pipe_create() instead of > allocating the struct in dopipe() and initialize it in pipe_create(). > > It makes pipe_create() to return a `struct pipe *' instead of an error > code. The sole possible error was ENOMEM, so returning NULL in such case > is fine. > > > In the same move, I revisited the freeing of the struct pipe: the > pipeclose() function. > > About pipeclose(): > > - I dislike having both pipe_close() and pipeclose() functions. So I > renamed pipeclose() to pipe_free(). The function does a bit more that > freeing resources, as it ensures all customers possibling in wait state > are aware of the pipe terminaison. but I don't have better name...
I used *_destroy() in similar cases but honestly I don't mind pipe_free(). > - I inversed the if-condition to return early, and move the whole > if-body in the function. It is more readable, and match what we usually > do in such case. > > This way, pipe_create() and pipe_free() are symetric: allocation in one, > and free in another. > > Comments or OK ? > -- > Sebastien Marie > > > Index: sys/kern/sys_pipe.c > =================================================================== > --- sys/kern/sys_pipe.c.orig 2019-07-15 11:06:05.015708914 +0200 > +++ sys/kern/sys_pipe.c 2019-07-15 11:11:35.667317769 +0200 > @@ -97,12 +97,12 @@ static unsigned int amountpipekva; > struct pool pipe_pool; > > int dopipe(struct proc *, int *, int); > -void pipeclose(struct pipe *); > -int pipe_create(struct pipe *); > int pipelock(struct pipe *); > void pipeunlock(struct pipe *); > void pipeselwakeup(struct pipe *); > > +struct pipe *pipe_create(); Please make this a real void function: struct pipe *pipe_create(void); > +void pipe_free(struct pipe *); > int pipe_buffer_realloc(struct pipe *, u_int); > void pipe_buffer_free(struct pipe *); > > @@ -144,14 +144,11 @@ dopipe(struct proc *p, int *ufds, int fl > > cloexec = (flags & O_CLOEXEC) ? UF_EXCLOSE : 0; > > - rpipe = pool_get(&pipe_pool, PR_WAITOK | PR_ZERO); > - error = pipe_create(rpipe); > - if (error != 0) > - goto free1; > - wpipe = pool_get(&pipe_pool, PR_WAITOK | PR_ZERO); > - error = pipe_create(wpipe); > - if (error != 0) > + if (((rpipe = pipe_create()) == NULL) || > + ((wpipe = pipe_create()) == NULL)) { > + error = ENOMEM; > goto free1; > + } > > fdplock(fdp); > > @@ -202,8 +199,8 @@ free3: > free2: > fdpunlock(fdp); > free1: > - pipeclose(wpipe); > - pipeclose(rpipe); > + pipe_free(wpipe); > + pipe_free(rpipe); > return (error); > } > > @@ -247,16 +244,19 @@ pipe_buffer_realloc(struct pipe *cpipe, > /* > * initialize and allocate VM and memory for pipe > */ > -int > -pipe_create(struct pipe *cpipe) > +struct pipe * > +pipe_create() again make this really not take any arguments by using pipe_create(void) > { > int error; > - > - sigio_init(&cpipe->pipe_sigio); > + struct pipe *cpipe = pool_get(&pipe_pool, PR_WAITOK | PR_ZERO); In general complex functions should not be used in initializers. So maybe make this: struct pipe *cpipe; cpipe = pool_get(&pipe_pool, PR_WAITOK | PR_ZERO); > error = pipe_buffer_realloc(cpipe, PIPE_SIZE); > - if (error != 0) > - return (error); > + if (error != 0) { > + pool_put(&pipe_pool, cpipe); > + return (NULL); > + } > + > + sigio_init(&cpipe->pipe_sigio); > > getnanotime(&cpipe->pipe_ctime); > cpipe->pipe_atime = cpipe->pipe_ctime; > @@ -768,7 +768,7 @@ pipe_close(struct file *fp, struct proc > fp->f_ops = NULL; > fp->f_data = NULL; > KERNEL_LOCK(); > - pipeclose(cpipe); > + pipe_free(cpipe); > KERNEL_UNLOCK(); > return (0); > } > @@ -799,44 +799,46 @@ pipe_buffer_free(struct pipe *cpipe) > } > > /* > - * shutdown the pipe > + * shutdown the pipe, and free resources. > */ > void > -pipeclose(struct pipe *cpipe) > +pipe_free(struct pipe *cpipe) > { > struct pipe *ppipe; > - if (cpipe) { > - pipeselwakeup(cpipe); > - sigio_free(&cpipe->pipe_sigio); > > - /* > - * If the other side is blocked, wake it up saying that > - * we want to close it down. > - */ > - cpipe->pipe_state |= PIPE_EOF; > - while (cpipe->pipe_busy) { > - wakeup(cpipe); > - cpipe->pipe_state |= PIPE_WANTD; > - tsleep(cpipe, PRIBIO, "pipecl", 0); > - } > + if (cpipe == NULL) > + return; > > - /* > - * Disconnect from peer > - */ > - if ((ppipe = cpipe->pipe_peer) != NULL) { > - pipeselwakeup(ppipe); > + pipeselwakeup(cpipe); > + sigio_free(&cpipe->pipe_sigio); > > - ppipe->pipe_state |= PIPE_EOF; > - wakeup(ppipe); > - ppipe->pipe_peer = NULL; > - } > + /* > + * If the other side is blocked, wake it up saying that > + * we want to close it down. > + */ > + cpipe->pipe_state |= PIPE_EOF; > + while (cpipe->pipe_busy) { > + wakeup(cpipe); > + cpipe->pipe_state |= PIPE_WANTD; > + tsleep(cpipe, PRIBIO, "pipecl", 0); > + } > > - /* > - * free resources > - */ > - pipe_buffer_free(cpipe); > - pool_put(&pipe_pool, cpipe); > + /* > + * Disconnect from peer > + */ > + if ((ppipe = cpipe->pipe_peer) != NULL) { > + pipeselwakeup(ppipe); > + > + ppipe->pipe_state |= PIPE_EOF; > + wakeup(ppipe); > + ppipe->pipe_peer = NULL; > } > + > + /* > + * free resources > + */ > + pipe_buffer_free(cpipe); > + pool_put(&pipe_pool, cpipe); > } > > int > Apart from that OK claudio@ -- :wq Claudio