haproxy/src/pipe.c
Willy Tarreau 8ceae72d44 MEDIUM: init: use initcall for all fixed size pool creations
This commit replaces the explicit pool creation that are made in
constructors with a pool registration. Not only this simplifies the
pools declaration (it can be done on a single line after the head is
declared), but it also removes references to pools from within
constructors. The only remaining create_pool() calls are those
performed in init functions after the config is parsed, so there
is no more user of potentially uninitialized pool now.

It has been the opportunity to remove no less than 12 constructors
and 6 init functions.
2018-11-26 19:50:32 +01:00

119 lines
2.6 KiB
C

/*
* Pipe management
*
* Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <unistd.h>
#include <fcntl.h>
#include <common/config.h>
#include <common/hathreads.h>
#include <common/memory.h>
#include <types/global.h>
#include <types/pipe.h>
DECLARE_STATIC_POOL(pool_head_pipe, "pipe", sizeof(struct pipe));
struct pipe *pipes_live = NULL; /* pipes which are still ready to use */
__decl_spinlock(pipes_lock); /* lock used to protect pipes list */
int pipes_used = 0; /* # of pipes in use (2 fds each) */
int pipes_free = 0; /* # of pipes unused */
/* return a pre-allocated empty pipe. Try to allocate one if there isn't any
* left. NULL is returned if a pipe could not be allocated.
*/
struct pipe *get_pipe()
{
struct pipe *ret = NULL;
int pipefd[2];
HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
if (likely(pipes_live)) {
ret = pipes_live;
pipes_live = pipes_live->next;
pipes_free--;
pipes_used++;
goto out;
}
if (pipes_used >= global.maxpipes)
goto out;
ret = pool_alloc(pool_head_pipe);
if (!ret)
goto out;
if (pipe(pipefd) < 0) {
pool_free(pool_head_pipe, ret);
goto out;
}
#ifdef F_SETPIPE_SZ
if (global.tune.pipesize)
fcntl(pipefd[0], F_SETPIPE_SZ, global.tune.pipesize);
#endif
ret->data = 0;
ret->prod = pipefd[1];
ret->cons = pipefd[0];
ret->next = NULL;
pipes_used++;
out:
HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
return ret;
}
static void inline __kill_pipe(struct pipe *p)
{
close(p->prod);
close(p->cons);
pool_free(pool_head_pipe, p);
pipes_used--;
return;
}
/* destroy a pipe, possibly because an error was encountered on it. Its FDs
* will be closed and it will not be reinjected into the live pool.
*/
void kill_pipe(struct pipe *p)
{
HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
__kill_pipe(p);
HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
return;
}
/* put back a unused pipe into the live pool. If it still has data in it, it is
* closed and not reinjected into the live pool. The caller is not allowed to
* use it once released.
*/
void put_pipe(struct pipe *p)
{
HA_SPIN_LOCK(PIPES_LOCK, &pipes_lock);
if (p->data) {
__kill_pipe(p);
goto out;
}
p->next = pipes_live;
pipes_live = p;
pipes_free++;
pipes_used--;
out:
HA_SPIN_UNLOCK(PIPES_LOCK, &pipes_lock);
}
/*
* Local variables:
* c-indent-level: 8
* c-basic-offset: 8
* End:
*/