From: phk Date: Thu, 10 Jul 2008 10:26:17 +0000 (+0000) Subject: Add Semaphore facility to synchronize different treads in the tester X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=cf0cb1e82ef61fa017d09cd0c49205af8d3a7684;p=varnish Add Semaphore facility to synchronize different treads in the tester with each other. git-svn-id: svn+ssh://projects.linpro.no/svn/varnish/trunk@2915 d4fa192b-c00b-0410-8231-f00ffab90ce4 --- diff --git a/varnish-cache/bin/varnishtest/Makefile.am b/varnish-cache/bin/varnishtest/Makefile.am index 3a219d03..3eb45591 100644 --- a/varnish-cache/bin/varnishtest/Makefile.am +++ b/varnish-cache/bin/varnishtest/Makefile.am @@ -10,6 +10,7 @@ varnishtest_SOURCES = \ vtc_client.c \ vtc_http.c \ vtc_log.c \ + vtc_sema.c \ vtc_server.c \ vtc_varnish.c diff --git a/varnish-cache/bin/varnishtest/vtc.c b/varnish-cache/bin/varnishtest/vtc.c index 729470ea..92e7e0c1 100644 --- a/varnish-cache/bin/varnishtest/vtc.c +++ b/varnish-cache/bin/varnishtest/vtc.c @@ -283,6 +283,7 @@ static struct cmds cmds[] = { { "delay", cmd_delay }, { "test", cmd_test }, { "shell", cmd_shell }, + { "sema", cmd_sema }, { NULL, NULL } }; @@ -328,6 +329,7 @@ main(int argc, char * const *argv) } argc -= optind; argv += optind; + init_sema(); for (ch = 0; ch < argc; ch++) exec_file(argv[ch]); fok = fopen("_.ok", "w"); diff --git a/varnish-cache/bin/varnishtest/vtc.h b/varnish-cache/bin/varnishtest/vtc.h index 22332637..5da5cf2b 100644 --- a/varnish-cache/bin/varnishtest/vtc.h +++ b/varnish-cache/bin/varnishtest/vtc.h @@ -46,6 +46,9 @@ cmd_f cmd_server; cmd_f cmd_client; cmd_f cmd_stats; cmd_f cmd_varnish; +cmd_f cmd_sema; + +void init_sema(void); void http_process(struct vtclog *vl, const char *spec, int sock, int client); diff --git a/varnish-cache/bin/varnishtest/vtc_http.c b/varnish-cache/bin/varnishtest/vtc_http.c index 15147383..e96c105a 100644 --- a/varnish-cache/bin/varnishtest/vtc_http.c +++ b/varnish-cache/bin/varnishtest/vtc_http.c @@ -606,6 +606,7 @@ static struct cmds http_cmds[] = { { "send", cmd_http_send }, { "chunked", cmd_http_chunked }, { "delay", cmd_delay }, + { "sema", cmd_sema }, { NULL, NULL } }; diff --git a/varnish-cache/bin/varnishtest/vtc_sema.c b/varnish-cache/bin/varnishtest/vtc_sema.c new file mode 100644 index 00000000..6276ee95 --- /dev/null +++ b/varnish-cache/bin/varnishtest/vtc_sema.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2006-2008 Linpro AS + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: vtc_sema.c 2906 2008-07-08 10:29:07Z phk $ + */ + +#include +#include +#include +#include +#include + +#include "vtc.h" + +#include "vqueue.h" +#include "miniobj.h" +#include "libvarnish.h" + +struct sema { + unsigned magic; +#define SEMA_MAGIC 0x29b64317 + char *name; + struct vtclog *vl; + VTAILQ_ENTRY(sema) list; + pthread_mutex_t mtx; + pthread_cond_t cond; + + unsigned waiters; + unsigned expected; +}; + +static pthread_mutex_t sema_mtx; +static VTAILQ_HEAD(, sema) semas = VTAILQ_HEAD_INITIALIZER(semas); + +/********************************************************************** + * Allocate and initialize a sema + */ + +static struct sema * +sema_new(char *name) +{ + struct sema *r; + + ALLOC_OBJ(r, SEMA_MAGIC); + AN(r); + r->vl = vtc_logopen(name); + AN(r->vl); + r->name = name; + if (*name != 'r') + vtc_log(r->vl, 0, "Sema name must start with 'r'"); + + AZ(pthread_mutex_init(&r->mtx, NULL)); + AZ(pthread_cond_init(&r->cond, NULL)); + r->waiters = 0; + r->expected = 0; + VTAILQ_INSERT_TAIL(&semas, r, list); + return (r); +} + +/********************************************************************** + * Sync a sema + */ + +static void +sema_sync(struct sema *r, const char *av) +{ + unsigned u; + + u = strtoul(av, NULL, 0); + + AZ(pthread_mutex_lock(&r->mtx)); + if (r->expected == 0) + r->expected = u; + assert(r->expected == u); + + if (++r->waiters == r->expected) { + vtc_log(r->vl, 4, "Wake %u", r->expected); + AZ(pthread_cond_broadcast(&r->cond)); + r->waiters = 0; + r->expected = 0; + } else + AZ(pthread_cond_wait(&r->cond, &r->mtx)); + AZ(pthread_mutex_unlock(&r->mtx)); +} + +/********************************************************************** + * Semaphore command dispatch + */ + +void +cmd_sema(CMD_ARGS) +{ + struct sema *r, *r2; + + (void)priv; + (void)cmd; + + if (av == NULL) { + AZ(pthread_mutex_lock(&sema_mtx)); + /* Reset and free */ + VTAILQ_FOREACH_SAFE(r, &semas, list, r2) { + VTAILQ_REMOVE(&semas, r, list); + FREE_OBJ(r); + /* XXX: MEMLEAK */ + } + AZ(pthread_mutex_unlock(&sema_mtx)); + return; + } + + assert(!strcmp(av[0], "sema")); + av++; + + AZ(pthread_mutex_lock(&sema_mtx)); + VTAILQ_FOREACH(r, &semas, list) + if (!strcmp(r->name, av[0])) + break; + if (r == NULL) + r = sema_new(av[0]); + AZ(pthread_mutex_unlock(&sema_mtx)); + av++; + + for (; *av != NULL; av++) { + if (!strcmp(*av, "sync")) { + av++; + AN(*av); + sema_sync(r, *av); + continue; + } + vtc_log(r->vl, 0, "Unknown sema argument: %s", *av); + } +} + +void +init_sema(void) +{ + AZ(pthread_mutex_init(&sema_mtx, NULL)); +}