Commit 303726fd authored by Dridi Boukelmoune's avatar Dridi Boukelmoune Committed by Nils Goroll

vca: Eliminate heap allocations of sock_opt arguments

They can be stored directly in the sock_opts array or on the stack.
parent 42e1ca3b
...@@ -80,15 +80,21 @@ struct poolsock { ...@@ -80,15 +80,21 @@ struct poolsock {
* TCP options we want to control * TCP options we want to control
*/ */
union sock_arg {
struct linger lg;
struct timeval tv;
int i;
};
static struct sock_opt { static struct sock_opt {
int level; int level;
int optname; int optname;
const char *strname; const char *strname;
socklen_t sz;
void *ptr;
int need; int need;
socklen_t sz;
union sock_arg arg[1];
} sock_opts[] = { } sock_opts[] = {
#define SOCK_OPT(lvl, nam, typ) { lvl, nam, #nam, sizeof(typ), NULL, 0 }, #define SOCK_OPT(lvl, nam, typ) { lvl, nam, #nam, 0, sizeof(typ) },
SOCK_OPT(SOL_SOCKET, SO_LINGER, struct linger) SOCK_OPT(SOL_SOCKET, SO_LINGER, struct linger)
SOCK_OPT(SOL_SOCKET, SO_KEEPALIVE, int) SOCK_OPT(SOL_SOCKET, SO_KEEPALIVE, int)
...@@ -152,35 +158,30 @@ vca_sock_opt_init(void) ...@@ -152,35 +158,30 @@ vca_sock_opt_init(void)
int n; int n;
int one = 1; int one = 1;
struct sock_opt *so; struct sock_opt *so;
struct timeval tv; union sock_arg tmp;
int chg = 0; int chg = 0;
int x;
memset(&tv, 0, sizeof tv); memset(&tmp, 0, sizeof tmp);
memset(&x, 0, sizeof x);
for (n = 0; n < n_sock_opts; n++) { for (n = 0; n < n_sock_opts; n++) {
so = &sock_opts[n]; so = &sock_opts[n];
if (so->ptr == NULL)
so->ptr = calloc(1, so->sz);
AN(so->ptr);
if (!strcmp(so->strname, "SO_LINGER")) { if (!strcmp(so->strname, "SO_LINGER")) {
assert(so->sz == sizeof linger); assert(so->sz == sizeof linger);
memcpy(so->ptr, &linger, sizeof linger); memcpy(so->arg, &linger, sizeof linger);
so->need = 1; so->need = 1;
} else if (!strcmp(so->strname, "TCP_NODELAY")) { } else if (!strcmp(so->strname, "TCP_NODELAY")) {
assert(so->sz == sizeof one); assert(so->sz == sizeof one);
memcpy(so->ptr, &one, sizeof one); memcpy(so->arg, &one, sizeof one);
so->need = 1; so->need = 1;
} else if (!strcmp(so->strname, "SO_KEEPALIVE")) { } else if (!strcmp(so->strname, "SO_KEEPALIVE")) {
assert(so->sz == sizeof one); assert(so->sz == sizeof one);
memcpy(so->ptr, &one, sizeof one); memcpy(so->arg, &one, sizeof one);
so->need = 1; so->need = 1;
#define NEW_VAL(so, xx) \ #define NEW_VAL(so, xx) \
do { \ do { \
assert(so->sz == sizeof xx); \ assert(so->sz == sizeof xx); \
if (memcmp(so->ptr, &(xx), sizeof xx)) { \ if (memcmp(so->arg, &(xx), sizeof xx)) { \
memcpy(so->ptr, &(xx), sizeof xx); \ memcpy(so->arg, &(xx), sizeof xx); \
so->need = 1; \ so->need = 1; \
chg = 1; \ chg = 1; \
need_test = 1; \ need_test = 1; \
...@@ -188,21 +189,21 @@ vca_sock_opt_init(void) ...@@ -188,21 +189,21 @@ vca_sock_opt_init(void)
} while (0) } while (0)
} else if (!strcmp(so->strname, "SO_SNDTIMEO")) { } else if (!strcmp(so->strname, "SO_SNDTIMEO")) {
tv = VTIM_timeval(cache_param->idle_send_timeout); tmp.tv = VTIM_timeval(cache_param->idle_send_timeout);
NEW_VAL(so, tv); NEW_VAL(so, tmp.tv);
} else if (!strcmp(so->strname, "SO_RCVTIMEO")) { } else if (!strcmp(so->strname, "SO_RCVTIMEO")) {
tv = VTIM_timeval(cache_param->timeout_idle); tmp.tv = VTIM_timeval(cache_param->timeout_idle);
NEW_VAL(so, tv); NEW_VAL(so, tmp.tv);
#ifdef HAVE_TCP_KEEP #ifdef HAVE_TCP_KEEP
} else if (!strcmp(so->strname, "TCP_KEEPIDLE")) { } else if (!strcmp(so->strname, "TCP_KEEPIDLE")) {
x = (int)(cache_param->tcp_keepalive_time); tmp.i = (int)(cache_param->tcp_keepalive_time);
NEW_VAL(so, x); NEW_VAL(so, tmp.i);
} else if (!strcmp(so->strname, "TCP_KEEPCNT")) { } else if (!strcmp(so->strname, "TCP_KEEPCNT")) {
x = (int)(cache_param->tcp_keepalive_probes); tmp.i = (int)(cache_param->tcp_keepalive_probes);
NEW_VAL(so, x); NEW_VAL(so, tmp.i);
} else if (!strcmp(so->strname, "TCP_KEEPINTVL")) { } else if (!strcmp(so->strname, "TCP_KEEPINTVL")) {
x = (int)(cache_param->tcp_keepalive_intvl); tmp.i = (int)(cache_param->tcp_keepalive_intvl);
NEW_VAL(so, x); NEW_VAL(so, tmp.i);
#endif #endif
} }
} }
...@@ -212,10 +213,10 @@ vca_sock_opt_init(void) ...@@ -212,10 +213,10 @@ vca_sock_opt_init(void)
static void static void
vca_sock_opt_test(const struct listen_sock *ls, const struct sess *sp) vca_sock_opt_test(const struct listen_sock *ls, const struct sess *sp)
{ {
int i, n;
struct sock_opt *so; struct sock_opt *so;
union sock_arg tmp;
socklen_t l; socklen_t l;
void *ptr; int i, n;
CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC); CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
...@@ -225,13 +226,11 @@ vca_sock_opt_test(const struct listen_sock *ls, const struct sess *sp) ...@@ -225,13 +226,11 @@ vca_sock_opt_test(const struct listen_sock *ls, const struct sess *sp)
if (so->level == IPPROTO_TCP && ls->uds) if (so->level == IPPROTO_TCP && ls->uds)
continue; continue;
so->need = 1; so->need = 1;
ptr = calloc(1, so->sz); memset(&tmp, 0, sizeof tmp);
AN(ptr);
l = so->sz; l = so->sz;
i = getsockopt(sp->fd, so->level, so->optname, ptr, &l); i = getsockopt(sp->fd, so->level, so->optname, &tmp, &l);
if (i == 0 && !memcmp(ptr, so->ptr, so->sz)) if (i == 0 && !memcmp(&tmp, so->arg, so->sz))
so->need = 0; so->need = 0;
free(ptr);
if (i && errno != ENOPROTOOPT) if (i && errno != ENOPROTOOPT)
VTCP_Assert(i); VTCP_Assert(i);
} }
...@@ -240,8 +239,8 @@ vca_sock_opt_test(const struct listen_sock *ls, const struct sess *sp) ...@@ -240,8 +239,8 @@ vca_sock_opt_test(const struct listen_sock *ls, const struct sess *sp)
static void static void
vca_sock_opt_set(const struct listen_sock *ls, const struct sess *sp) vca_sock_opt_set(const struct listen_sock *ls, const struct sess *sp)
{ {
int n, sock;
struct sock_opt *so; struct sock_opt *so;
int n, sock;
CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC); CHECK_OBJ_NOTNULL(ls, LISTEN_SOCK_MAGIC);
CHECK_OBJ_ORNULL(sp, SESS_MAGIC); CHECK_OBJ_ORNULL(sp, SESS_MAGIC);
...@@ -253,7 +252,7 @@ vca_sock_opt_set(const struct listen_sock *ls, const struct sess *sp) ...@@ -253,7 +252,7 @@ vca_sock_opt_set(const struct listen_sock *ls, const struct sess *sp)
continue; continue;
if (so->need || sp == NULL) { if (so->need || sp == NULL) {
VTCP_Assert(setsockopt(sock, VTCP_Assert(setsockopt(sock,
so->level, so->optname, so->ptr, so->sz)); so->level, so->optname, so->arg, so->sz));
} }
} }
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment