From patchwork Thu Dec 1 05:28:43 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pranith Kumar X-Patchwork-Id: 9455569 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 800A660585 for ; Thu, 1 Dec 2016 08:20:53 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 58ADB2849C for ; Thu, 1 Dec 2016 08:20:53 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 4A408284A4; Thu, 1 Dec 2016 08:20:53 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 57AE42849C for ; Thu, 1 Dec 2016 08:20:41 +0000 (UTC) Received: from localhost ([::1]:48829 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cCMbg-00079T-B4 for patchwork-qemu-devel@patchwork.kernel.org; Thu, 01 Dec 2016 03:20:40 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46865) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cCJvm-00074R-1a for qemu-devel@nongnu.org; Thu, 01 Dec 2016 00:29:37 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cCJvP-0004Kr-LM for qemu-devel@nongnu.org; Thu, 01 Dec 2016 00:29:14 -0500 Received: from mail-yb0-x244.google.com ([2607:f8b0:4002:c09::244]:34462) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1cCJvO-0004KM-Op for qemu-devel@nongnu.org; Thu, 01 Dec 2016 00:28:51 -0500 Received: by mail-yb0-x244.google.com with SMTP id h184so2991399ybb.1 for ; Wed, 30 Nov 2016 21:28:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=tSMlqCYbdenO9o5HuPje1KQRf4QMZnPsV4tDLV28D68=; b=BOAM4GlmkZqjDr5Z0XBcbtWEd7qdtr46hBRyhqRmoPjajRFMbpgou1G6nZT9zx55dd sYFT+QNrdGuod1iUixy8PlSF3E2ZaeeGBKy32Bs+LM8ZlqX4L9tzYKsC6AZk1Hg9A0S1 ehYfaWOrQSmYlRUIPpLYP+Sg2BG699JY+K08L9knnjS97ScyGm/hwGVTmEzsMzGJfnxY AB9nb9j+z1+AQUbkzXWfXrnFgJEKF7vWlCN9nPlBZoy/UvMui+hG9orIQpLK2DMSAvuQ M7TSjFwXPfIxv1t518v+V5j4wJPMuu1ltg8cvK50nM/dwVIg12uoJRTGOd8q3mAQYDUG 00Iw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=tSMlqCYbdenO9o5HuPje1KQRf4QMZnPsV4tDLV28D68=; b=Gd4eRc6AmuWISBUogVjKm1U3gJecG1QKNQEn5nRh1TjtvmqO7uzQbLW2ito9yNZUBG dvvep50yw9L4PMEMv2xX9LA6afmsQK+ZiEmjJ8eA0cs9BQxhi5ce1+ewMn8WLNu7Zox3 qN6pX1D0vcJUIQnIbcY2d2OQYi4eEpW4pCLPEJL+F6Rn2yWef9odz+OObiiErhCSYqIJ eKSavCJo0Tw5HE5w2cFW9C4s36UV6266A6pPkmoxJP1ocu/XeSuw4k8dNUgLzVXDRx/h ncOO8L9hzmcTxd+UPvD6h0/Lh9Hm32D81Zm9Pgt6xRsbFpzCtE2ZuXjcJa1+8fS55PuY 0RGg== X-Gm-Message-State: AKaTC02Q5Z4joBouzrDRaNsQJ/aCR2RcwF2A6gZvObUsKvP8YSAGu75doxe1etetDuBksQ== X-Received: by 10.37.234.71 with SMTP id o7mr10857704ybe.136.1480570128012; Wed, 30 Nov 2016 21:28:48 -0800 (PST) Received: from localhost.localdomain (c-73-207-178-95.hsd1.ga.comcast.net. [73.207.178.95]) by smtp.gmail.com with ESMTPSA id v137sm24778382ywa.30.2016.11.30.21.28.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Wed, 30 Nov 2016 21:28:47 -0800 (PST) From: Pranith Kumar To: alex.bennee@linaro.org Date: Thu, 1 Dec 2016 00:28:43 -0500 Message-Id: <20161201052844.31819-3-bobby.prani@gmail.com> X-Mailer: git-send-email 2.10.2 In-Reply-To: <20161201052844.31819-1-bobby.prani@gmail.com> References: <20161201052844.31819-1-bobby.prani@gmail.com> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:4002:c09::244 X-Mailman-Approved-At: Thu, 01 Dec 2016 03:20:02 -0500 Subject: [Qemu-devel] [PATCH v5 2/3] tests/tcg: Add aarch64 litmus tests X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org, rth@twiddle.net Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Signed-off-by: Pranith Kumar --- tests/tcg/aarch64/litmus/ARMARM00.c | 501 +++++++++++++ tests/tcg/aarch64/litmus/ARMARM01.c | 504 +++++++++++++ tests/tcg/aarch64/litmus/ARMARM02.c | 571 ++++++++++++++ tests/tcg/aarch64/litmus/ARMARM03.c | 498 +++++++++++++ tests/tcg/aarch64/litmus/ARMARM04+BIS.c | 556 ++++++++++++++ tests/tcg/aarch64/litmus/ARMARM04+TER.c | 538 ++++++++++++++ tests/tcg/aarch64/litmus/ARMARM04.c | 556 ++++++++++++++ tests/tcg/aarch64/litmus/ARMARM05.c | 553 ++++++++++++++ tests/tcg/aarch64/litmus/ARMARM06+AP+AA.c | 581 +++++++++++++++ tests/tcg/aarch64/litmus/ARMARM06+AP+AP.c | 581 +++++++++++++++ tests/tcg/aarch64/litmus/ARMARM06.c | 581 +++++++++++++++ tests/tcg/aarch64/litmus/ARMARM07+SAL.c | 497 +++++++++++++ tests/tcg/aarch64/litmus/Makefile | 53 ++ tests/tcg/aarch64/litmus/README.txt | 22 + tests/tcg/aarch64/litmus/affinity.c | 159 ++++ tests/tcg/aarch64/litmus/affinity.h | 34 + tests/tcg/aarch64/litmus/comp.sh | 30 + tests/tcg/aarch64/litmus/litmus_rand.c | 64 ++ tests/tcg/aarch64/litmus/litmus_rand.h | 29 + tests/tcg/aarch64/litmus/outs.c | 148 ++++ tests/tcg/aarch64/litmus/outs.h | 49 ++ tests/tcg/aarch64/litmus/run.sh | 378 ++++++++++ tests/tcg/aarch64/litmus/show.awk | 2 + tests/tcg/aarch64/litmus/utils.c | 1148 +++++++++++++++++++++++++++++ tests/tcg/aarch64/litmus/utils.h | 275 +++++++ 25 files changed, 8908 insertions(+) create mode 100644 tests/tcg/aarch64/litmus/ARMARM00.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM01.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM02.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM03.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM04+BIS.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM04+TER.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM04.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM05.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM06+AP+AA.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM06+AP+AP.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM06.c create mode 100644 tests/tcg/aarch64/litmus/ARMARM07+SAL.c create mode 100644 tests/tcg/aarch64/litmus/Makefile create mode 100644 tests/tcg/aarch64/litmus/README.txt create mode 100644 tests/tcg/aarch64/litmus/affinity.c create mode 100644 tests/tcg/aarch64/litmus/affinity.h create mode 100644 tests/tcg/aarch64/litmus/comp.sh create mode 100644 tests/tcg/aarch64/litmus/litmus_rand.c create mode 100644 tests/tcg/aarch64/litmus/litmus_rand.h create mode 100644 tests/tcg/aarch64/litmus/outs.c create mode 100644 tests/tcg/aarch64/litmus/outs.h create mode 100755 tests/tcg/aarch64/litmus/run.sh create mode 100644 tests/tcg/aarch64/litmus/show.awk create mode 100644 tests/tcg/aarch64/litmus/utils.c create mode 100644 tests/tcg/aarch64/litmus/utils.h diff --git a/tests/tcg/aarch64/litmus/ARMARM00.c b/tests/tcg/aarch64/litmus/ARMARM00.c new file mode 100644 index 0000000..3664ef2 --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM00.c @@ -0,0 +1,501 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 2 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_1_x2; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_1_x2) { + switch (_out_1_x0) { + case 1: + switch (_out_1_x2) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 2 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x2_f = 1 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 1:X2=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_1_x2_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x2 = malloc_check(size_of_test*sizeof(*(_a->out_1_x2))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x2); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_1_x2[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM00, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM00, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM00"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"str %w[x0],[%[x1]]\n" +"#_litmus_P0_2\n\t" +"mov %w[x2],#1\n" +"#_litmus_P0_3\n\t" +"stlr %w[x2],[%[x3]]\n" +"#END _litmus_P0\n\t" +:[x2] "=&r" (trashed_x2),[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM00"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + int *out_1_x2 = _a->out_1_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P1_2\n\t" +"b.ne 0f\n" +"#_litmus_P1_3\n\t" +"ldr %w[x2],[%[x3]]\n" +"#_litmus_P1_4\n" +"0:\n" +"#END _litmus_P1\n\t" +:[x2] "=&r" (out_1_x2[_i]),[x0] "=&r" (out_1_x0[_i]) +:[x1] "r" (&_a->y[_i]),"[x2]" (-1),[x3] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x2_i = ctx.out_1_x2[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x2_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_1_x2_f] = _out_1_x2_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM00 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 1:X2=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=8b05db686103708c048891dddc96e8bd\n"); + fprintf(out,"Com=Rf Fr\n"); + fprintf(out,"Orig=PodWWPL RfeLA PodRRAP Fre\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM00 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM00 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM00: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM00, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM00, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM01.c b/tests/tcg/aarch64/litmus/ARMARM01.c new file mode 100644 index 0000000..4320bb0 --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM01.c @@ -0,0 +1,504 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 2 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_1_x3; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_1_x3) { + switch (_out_1_x0) { + case 1: + switch (_out_1_x3) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 2 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x3_f = 1 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 1:X3=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_1_x3_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x3 = malloc_check(size_of_test*sizeof(*(_a->out_1_x3))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x3); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_1_x3[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM01, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM01, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM01"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"str %w[x0],[%[x1]]\n" +"#_litmus_P0_2\n\t" +"mov %w[x2],#1\n" +"#_litmus_P0_3\n\t" +"stlr %w[x2],[%[x3]]\n" +"#END _litmus_P0\n\t" +:[x2] "=&r" (trashed_x2),[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM01"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + int *out_1_x3 = _a->out_1_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P1_2\n\t" +"b.ne 0f\n" +"#_litmus_P1_3\n\t" +"eor %w[x2],%w[x0],%w[x0]\n" +"#_litmus_P1_4\n\t" +"ldr %w[x3],[%[x4],%w[x2],sxtw]\n" +"#_litmus_P1_5\n" +"0:\n" +"#END _litmus_P1\n\t" +:[x3] "=&r" (out_1_x3[_i]),[x0] "=&r" (out_1_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->y[_i]),"[x3]" (-1),[x4] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x3_i = ctx.out_1_x3[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x3_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_1_x3_f] = _out_1_x3_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM01 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 1:X3=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=e5d401d98b0063559060cb31236f54de\n"); + fprintf(out,"Com=Rf Fr\n"); + fprintf(out,"Orig=PodWWPL RfeLP DpAddrdR Fre\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM01 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM01 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM01: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM01, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM01, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM02.c b/tests/tcg/aarch64/litmus/ARMARM02.c new file mode 100644 index 0000000..0846b53 --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM02.c @@ -0,0 +1,571 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 3 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_1_x3; + int *out_2_x0; + int *out_2_x3; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_1_x3,int _out_2_x0,int _out_2_x3) { + switch (_out_1_x0) { + case 1: + switch (_out_1_x3) { + case 0: + return 1; + default: + goto label00; + } + default: + goto label00; + } + label00: /* occs=2 */ + switch (_out_2_x0) { + case 1: + switch (_out_2_x3) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 4 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x3_f = 1 ; +static const int out_2_x0_f = 2 ; +static const int out_2_x3_f = 3 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 1:X3=%i; 2:X0=%i; 2:X3=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_1_x3_f],(int)o[out_2_x0_f],(int)o[out_2_x3_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x3 = malloc_check(size_of_test*sizeof(*(_a->out_1_x3))); + _a->out_2_x0 = malloc_check(size_of_test*sizeof(*(_a->out_2_x0))); + _a->out_2_x3 = malloc_check(size_of_test*sizeof(*(_a->out_2_x3))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x3); + free((void *)_a->out_2_x0); + free((void *)_a->out_2_x3); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_1_x3[_i] = -239487; + _a->out_2_x0[_i] = -239487; + _a->out_2_x3[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM02, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM02, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM02"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"str %w[x0],[%[x1]]\n" +"#_litmus_P0_2\n\t" +"mov %w[x2],#1\n" +"#_litmus_P0_3\n\t" +"stlr %w[x2],[%[x3]]\n" +"#END _litmus_P0\n\t" +:[x2] "=&r" (trashed_x2),[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM02"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + int *out_1_x3 = _a->out_1_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P1_2\n\t" +"b.ne 0f\n" +"#_litmus_P1_3\n\t" +"eor %w[x2],%w[x0],%w[x0]\n" +"#_litmus_P1_4\n\t" +"ldr %w[x3],[%[x4],%w[x2],sxtw]\n" +"#_litmus_P1_5\n" +"0:\n" +"#END _litmus_P1\n\t" +:[x3] "=&r" (out_1_x3[_i]),[x0] "=&r" (out_1_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->y[_i]),"[x3]" (-1),[x4] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM02"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_2_x0 = _a->out_2_x0; + int *out_2_x3 = _a->out_2_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P2_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P2_2\n\t" +"b.ne 0f\n" +"#_litmus_P2_3\n\t" +"eor %w[x2],%w[x0],%w[x0]\n" +"#_litmus_P2_4\n\t" +"ldr %w[x3],[%[x4],%w[x2],sxtw]\n" +"#_litmus_P2_5\n" +"0:\n" +"#END _litmus_P2\n\t" +:[x3] "=&r" (out_2_x3[_i]),[x0] "=&r" (out_2_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->y[_i]),"[x3]" (-1),[x4] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x3_i = ctx.out_1_x3[_i]; + int _out_2_x0_i = ctx.out_2_x0[_i]; + int _out_2_x3_i = ctx.out_2_x3[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x3_i,_out_2_x0_i,_out_2_x3_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_1_x3_f] = _out_1_x3_i; + o[out_2_x0_f] = _out_2_x0_i; + o[out_2_x3_f] = _out_2_x3_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM02 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 1:X3=0 \\/ 2:X0=1 /\\ 2:X3=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=331667937512d41933d43e7fe662a69e\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM02 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM02 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM02: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM02, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM02, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM03.c b/tests/tcg/aarch64/litmus/ARMARM03.c new file mode 100644 index 0000000..cc7ef33 --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM03.c @@ -0,0 +1,498 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 2 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *z; + int* *y; + int *x; +/* Final content of observed registers */ + int* *out_1_x0; + int *out_1_x9; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int* _out_1_x0,int _out_1_x9,void *_val_x) { + return (_out_1_x0 == _val_x) && (_out_1_x9 == 0); +} + +inline static int final_ok(int cond) { + return cond; +} + +static int idx_addr(ctx_t *_a,int _i,void *v_addr) { + if (v_addr == NULL) { return 0;} + else if (v_addr == (void *)&(_a->z[_i])) return 1; + else if (v_addr == (void *)&(_a->y[_i])) return 2; + else if (v_addr == (void *)&(_a->x[_i])) return 3; + else { fatal("ARMARM03, ???"); return -1;} +} + +static char *pretty_addr[4] = {"0","z","y","x",}; + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 2 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x9_f = 1 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%s; 1:X9=%i;\n",c,show ? '*' : ':',pretty_addr[o[out_1_x0_f]],(int)o[out_1_x9_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x9 = malloc_check(size_of_test*sizeof(*(_a->out_1_x9))); + _a->z = malloc_check(size_of_test*sizeof(*(_a->z))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->z); + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x9); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->z[_i] = -1; + _a->y[_i] = ((int *)&(_a->z[_i])); + _a->x[_i] = 0; + _a->out_1_x0[_i] = NULL; + _a->out_1_x9[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *z = _a->z; + int* *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && z[_i] != -1) fatal("ARMARM03, check_globals failed"); + if (rand_bit(&(_a->seed)) && y[_i] != ((int *)&(_a->z[_i]))) fatal("ARMARM03, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM03, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM03"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"str %w[x0],[%[x1]]\n" +"#_litmus_P0_2\n\t" +"stlr %[x1],[%[x3]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM03"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int* *out_1_x0 = _a->out_1_x0; + int *out_1_x9 = _a->out_1_x9; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldr %[x0],[%[x3]]\n" +"#_litmus_P1_1\n\t" +"ldr %w[x9],[%[x0]]\n" +"#END _litmus_P1\n\t" +:[x9] "=&r" (out_1_x9[_i]),[x0] "=&r" (out_1_x0[_i]) +:[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int* _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x9_i = ctx.out_1_x9[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x9_i,&(ctx.x[_i]))); + o[out_1_x0_f] = idx_addr(&ctx,_i,_out_1_x0_i); + o[out_1_x9_f] = _out_1_x9_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM03 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=x /\\ 1:X9=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=5576fb6a46ae70aa15a1087a51748a39\n"); + fprintf(out,"Com=Rf Fr\n"); + fprintf(out,"Orig=PodWWPL RfeLP DpAddrdR Fre\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM03 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM03 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM03: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM03, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM03, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM04+BIS.c b/tests/tcg/aarch64/litmus/ARMARM04+BIS.c new file mode 100644 index 0000000..41a2bc4 --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM04+BIS.c @@ -0,0 +1,556 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 3 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_2_x0; + int *out_2_x3; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_2_x0,int _out_2_x3) { + switch (_out_1_x0) { + case 1: + switch (_out_2_x0) { + case 1: + switch (_out_2_x3) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 3 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_2_x0_f = 1 ; +static const int out_2_x3_f = 2 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 2:X0=%i; 2:X3=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_2_x0_f],(int)o[out_2_x3_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_2_x0 = malloc_check(size_of_test*sizeof(*(_a->out_2_x0))); + _a->out_2_x3 = malloc_check(size_of_test*sizeof(*(_a->out_2_x3))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_2_x0); + free((void *)_a->out_2_x3); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_2_x0[_i] = -239487; + _a->out_2_x3[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM04+BIS, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM04+BIS, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04+BIS"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04+BIS"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P1_2\n\t" +"b.ne 0f\n" +"#_litmus_P1_3\n\t" +"mov %w[x2],#1\n" +"#_litmus_P1_4\n\t" +"str %w[x2],[%[x3]]\n" +"#_litmus_P1_5\n" +"0:\n" +"#END _litmus_P1\n\t" +:[x0] "=&r" (out_1_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04+BIS"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_2_x0 = _a->out_2_x0; + int *out_2_x3 = _a->out_2_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; + void* trashed_x5; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P2_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P2_2\n\t" +"b.ne 0f\n" +"#_litmus_P2_3\n\t" +"eor %w[x2],%w[x0],%w[x0]\n" +"#_litmus_P2_4\n\t" +"add %[x5],%[x4],%w[x2],sxtw\n" +"#_litmus_P2_5\n\t" +"ldr %w[x3],[%[x5]]\n" +"#_litmus_P2_6\n" +"0:\n" +"#END _litmus_P2\n\t" +:[x3] "=&r" (out_2_x3[_i]),[x0] "=&r" (out_2_x0[_i]),[x5] "=&r" (trashed_x5),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->y[_i]),"[x3]" (-1),[x4] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_2_x0_i = ctx.out_2_x0[_i]; + int _out_2_x3_i = ctx.out_2_x3[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_2_x0_i,_out_2_x3_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_2_x0_f] = _out_2_x0_i; + o[out_2_x3_f] = _out_2_x3_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM04+BIS Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 2:X0=1 /\\ 2:X3=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=cc1a451a55f22a8237344520956968ae\n"); + fprintf(out,"Com=Rf Rf Fr\n"); + fprintf(out,"Orig=RfeLA PodRWAP Rfe DpAddrdRPA FreAL\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM04+BIS %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM04+BIS %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM04+BIS: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM04+BIS, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM04+BIS, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM04+TER.c b/tests/tcg/aarch64/litmus/ARMARM04+TER.c new file mode 100644 index 0000000..46dcc3a --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM04+TER.c @@ -0,0 +1,538 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 3 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_2_x0; + int *out_2_x2; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_2_x0,int _out_2_x2) { + switch (_out_1_x0) { + case 1: + switch (_out_2_x0) { + case 1: + switch (_out_2_x2) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 3 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_2_x0_f = 1 ; +static const int out_2_x2_f = 2 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 2:X0=%i; 2:X2=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_2_x0_f],(int)o[out_2_x2_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_2_x0 = malloc_check(size_of_test*sizeof(*(_a->out_2_x0))); + _a->out_2_x2 = malloc_check(size_of_test*sizeof(*(_a->out_2_x2))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_2_x0); + free((void *)_a->out_2_x2); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_2_x0[_i] = -239487; + _a->out_2_x2[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM04+TER, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM04+TER, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04+TER"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04+TER"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"mov %w[x2],#1\n" +"#_litmus_P1_2\n\t" +"str %w[x2],[%[x3]]\n" +"#END _litmus_P1\n\t" +:[x0] "=&r" (out_1_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04+TER"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_2_x0 = _a->out_2_x0; + int *out_2_x2 = _a->out_2_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P2_1\n\t" +"ldar %w[x2],[%[x3]]\n" +"#END _litmus_P2\n\t" +:[x2] "=&r" (out_2_x2[_i]),[x0] "=&r" (out_2_x0[_i]) +:[x1] "r" (&_a->y[_i]),[x3] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_2_x0_i = ctx.out_2_x0[_i]; + int _out_2_x2_i = ctx.out_2_x2[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_2_x0_i,_out_2_x2_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_2_x0_f] = _out_2_x0_i; + o[out_2_x2_f] = _out_2_x2_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM04+TER Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 2:X0=1 /\\ 2:X2=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=b4e4b307db93ea419e3d73d315f6593d\n"); + fprintf(out,"Com=Rf Rf Fr\n"); + fprintf(out,"Orig=RfeLA PodRWAP Rfe PodRRPA FreAL\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM04+TER %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM04+TER %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM04+TER: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM04+TER, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM04+TER, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM04.c b/tests/tcg/aarch64/litmus/ARMARM04.c new file mode 100644 index 0000000..c514bcd --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM04.c @@ -0,0 +1,556 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 3 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_2_x0; + int *out_2_x3; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_2_x0,int _out_2_x3) { + switch (_out_1_x0) { + case 1: + switch (_out_2_x0) { + case 1: + switch (_out_2_x3) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 3 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_2_x0_f = 1 ; +static const int out_2_x3_f = 2 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 2:X0=%i; 2:X3=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_2_x0_f],(int)o[out_2_x3_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_2_x0 = malloc_check(size_of_test*sizeof(*(_a->out_2_x0))); + _a->out_2_x3 = malloc_check(size_of_test*sizeof(*(_a->out_2_x3))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_2_x0); + free((void *)_a->out_2_x3); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_2_x0[_i] = -239487; + _a->out_2_x3[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM04, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM04, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P1_2\n\t" +"b.ne 0f\n" +"#_litmus_P1_3\n\t" +"mov %w[x2],#1\n" +"#_litmus_P1_4\n\t" +"str %w[x2],[%[x3]]\n" +"#_litmus_P1_5\n" +"0:\n" +"#END _litmus_P1\n\t" +:[x0] "=&r" (out_1_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM04"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_2_x0 = _a->out_2_x0; + int *out_2_x3 = _a->out_2_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; + void* trashed_x5; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P2_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P2_2\n\t" +"b.ne 0f\n" +"#_litmus_P2_3\n\t" +"eor %w[x2],%w[x0],%w[x0]\n" +"#_litmus_P2_4\n\t" +"add %[x5],%[x4],%w[x2],sxtw\n" +"#_litmus_P2_5\n\t" +"ldar %w[x3],[%[x5]]\n" +"#_litmus_P2_6\n" +"0:\n" +"#END _litmus_P2\n\t" +:[x3] "=&r" (out_2_x3[_i]),[x0] "=&r" (out_2_x0[_i]),[x5] "=&r" (trashed_x5),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->y[_i]),"[x3]" (-1),[x4] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_2_x0_i = ctx.out_2_x0[_i]; + int _out_2_x3_i = ctx.out_2_x3[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_2_x0_i,_out_2_x3_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_2_x0_f] = _out_2_x0_i; + o[out_2_x3_f] = _out_2_x3_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM04 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 2:X0=1 /\\ 2:X3=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=bd6e92e9864bd5671cb7e479e9221bae\n"); + fprintf(out,"Com=Rf Rf Fr\n"); + fprintf(out,"Orig=RfeLA PodRWAP Rfe DpAddrdRPA FreAL\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM04 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM04 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM04: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM04, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM04, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM05.c b/tests/tcg/aarch64/litmus/ARMARM05.c new file mode 100644 index 0000000..3b80ddc --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM05.c @@ -0,0 +1,553 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 3 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_2_x0; + int *out_2_x3; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_2_x0,int _out_2_x3) { + switch (_out_1_x0) { + case 1: + switch (_out_2_x0) { + case 1: + switch (_out_2_x3) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 3 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_2_x0_f = 1 ; +static const int out_2_x3_f = 2 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 2:X0=%i; 2:X3=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_2_x0_f],(int)o[out_2_x3_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_2_x0 = malloc_check(size_of_test*sizeof(*(_a->out_2_x0))); + _a->out_2_x3 = malloc_check(size_of_test*sizeof(*(_a->out_2_x3))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_2_x0); + free((void *)_a->out_2_x3); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_2_x0[_i] = -239487; + _a->out_2_x3[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM05, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM05, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM05"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"str %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM05"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P1_2\n\t" +"b.ne 0f\n" +"#_litmus_P1_3\n\t" +"mov %w[x2],#1\n" +"#_litmus_P1_4\n\t" +"stlr %w[x2],[%[x3]]\n" +"#_litmus_P1_5\n" +"0:\n" +"#END _litmus_P1\n\t" +:[x0] "=&r" (out_1_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM05"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_2_x0 = _a->out_2_x0; + int *out_2_x3 = _a->out_2_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x2; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"ldr %w[x0],[%[x1]]\n" +"#_litmus_P2_1\n\t" +"cmp %w[x0],#1\n" +"#_litmus_P2_2\n\t" +"b.ne 0f\n" +"#_litmus_P2_3\n\t" +"eor %w[x2],%w[x0],%w[x0]\n" +"#_litmus_P2_4\n\t" +"ldr %w[x3],[%[x4],%w[x2],sxtw]\n" +"#_litmus_P2_5\n" +"0:\n" +"#END _litmus_P2\n\t" +:[x3] "=&r" (out_2_x3[_i]),[x0] "=&r" (out_2_x0[_i]),[x2] "=&r" (trashed_x2) +:[x1] "r" (&_a->y[_i]),"[x3]" (-1),[x4] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_2_x0_i = ctx.out_2_x0[_i]; + int _out_2_x3_i = ctx.out_2_x3[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_2_x0_i,_out_2_x3_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_2_x0_f] = _out_2_x0_i; + o[out_2_x3_f] = _out_2_x3_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM05 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 2:X0=1 /\\ 2:X3=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=87598a116e95069f91ea38314a500157\n"); + fprintf(out,"Com=Rf Rf Fr\n"); + fprintf(out,"Orig=Rfe PodRWPL RfeLP DpAddrdR Fre\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM05 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM05 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM05: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM05, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM05, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM06+AP+AA.c b/tests/tcg/aarch64/litmus/ARMARM06+AP+AA.c new file mode 100644 index 0000000..c44721e --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM06+AP+AA.c @@ -0,0 +1,581 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 4 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_1_x2; + int *out_3_x0; + int *out_3_x2; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_1_x2,int _out_3_x0,int _out_3_x2) { + switch (_out_1_x0) { + case 1: + switch (_out_1_x2) { + case 0: + switch (_out_3_x0) { + case 1: + switch (_out_3_x2) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 4 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x2_f = 1 ; +static const int out_3_x0_f = 2 ; +static const int out_3_x2_f = 3 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 1:X2=%i; 3:X0=%i; 3:X2=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_1_x2_f],(int)o[out_3_x0_f],(int)o[out_3_x2_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x2 = malloc_check(size_of_test*sizeof(*(_a->out_1_x2))); + _a->out_3_x0 = malloc_check(size_of_test*sizeof(*(_a->out_3_x0))); + _a->out_3_x2 = malloc_check(size_of_test*sizeof(*(_a->out_3_x2))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x2); + free((void *)_a->out_3_x0); + free((void *)_a->out_3_x2); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_1_x2[_i] = -239487; + _a->out_3_x0[_i] = -239487; + _a->out_3_x2[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM06+AP+AA, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM06+AP+AA, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AA"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AA"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + int *out_1_x2 = _a->out_1_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"ldr %w[x2],[%[x3]]\n" +"#END _litmus_P1\n\t" +:[x2] "=&r" (out_1_x2[_i]),[x0] "=&r" (out_1_x0[_i]) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AA"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P2_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P2\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P3(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AA"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_3_x0 = _a->out_3_x0; + int *out_3_x2 = _a->out_3_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P3\n" +"#_litmus_P3_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P3_1\n\t" +"ldar %w[x2],[%[x3]]\n" +"#END _litmus_P3\n\t" +:[x2] "=&r" (out_3_x2[_i]),[x0] "=&r" (out_3_x0[_i]) +:[x1] "r" (&_a->y[_i]),[x3] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2,&P3}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x2_i = ctx.out_1_x2[_i]; + int _out_3_x0_i = ctx.out_3_x0[_i]; + int _out_3_x2_i = ctx.out_3_x2[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x2_i,_out_3_x0_i,_out_3_x2_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_1_x2_f] = _out_1_x2_i; + o[out_3_x0_f] = _out_3_x0_i; + o[out_3_x2_f] = _out_3_x2_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM06+AP+AA Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 1:X2=0 /\\ 3:X0=1 /\\ 3:X2=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=09790f7c95472c70e7c2cd1b8b1f7c97\n"); + fprintf(out,"Com=Rf Fr Rf Fr\n"); + fprintf(out,"Orig=RfeLA PodRRAP FrePL RfeLA PodRRAA FreAL\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM06+AP+AA %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM06+AP+AA %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM06+AP+AA: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM06+AP+AA, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM06+AP+AA, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM06+AP+AP.c b/tests/tcg/aarch64/litmus/ARMARM06+AP+AP.c new file mode 100644 index 0000000..7389809 --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM06+AP+AP.c @@ -0,0 +1,581 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 4 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_1_x2; + int *out_3_x0; + int *out_3_x2; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_1_x2,int _out_3_x0,int _out_3_x2) { + switch (_out_1_x0) { + case 1: + switch (_out_1_x2) { + case 0: + switch (_out_3_x0) { + case 1: + switch (_out_3_x2) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 4 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x2_f = 1 ; +static const int out_3_x0_f = 2 ; +static const int out_3_x2_f = 3 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 1:X2=%i; 3:X0=%i; 3:X2=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_1_x2_f],(int)o[out_3_x0_f],(int)o[out_3_x2_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x2 = malloc_check(size_of_test*sizeof(*(_a->out_1_x2))); + _a->out_3_x0 = malloc_check(size_of_test*sizeof(*(_a->out_3_x0))); + _a->out_3_x2 = malloc_check(size_of_test*sizeof(*(_a->out_3_x2))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x2); + free((void *)_a->out_3_x0); + free((void *)_a->out_3_x2); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_1_x2[_i] = -239487; + _a->out_3_x0[_i] = -239487; + _a->out_3_x2[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM06+AP+AP, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM06+AP+AP, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AP"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AP"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + int *out_1_x2 = _a->out_1_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"ldr %w[x2],[%[x3]]\n" +"#END _litmus_P1\n\t" +:[x2] "=&r" (out_1_x2[_i]),[x0] "=&r" (out_1_x0[_i]) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AP"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P2_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P2\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P3(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06+AP+AP"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_3_x0 = _a->out_3_x0; + int *out_3_x2 = _a->out_3_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P3\n" +"#_litmus_P3_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P3_1\n\t" +"ldr %w[x2],[%[x3]]\n" +"#END _litmus_P3\n\t" +:[x2] "=&r" (out_3_x2[_i]),[x0] "=&r" (out_3_x0[_i]) +:[x1] "r" (&_a->y[_i]),[x3] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2,&P3}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x2_i = ctx.out_1_x2[_i]; + int _out_3_x0_i = ctx.out_3_x0[_i]; + int _out_3_x2_i = ctx.out_3_x2[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x2_i,_out_3_x0_i,_out_3_x2_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_1_x2_f] = _out_1_x2_i; + o[out_3_x0_f] = _out_3_x0_i; + o[out_3_x2_f] = _out_3_x2_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM06+AP+AP Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 1:X2=0 /\\ 3:X0=1 /\\ 3:X2=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=73c88d83e9bc423599f9750ed7d77ac2\n"); + fprintf(out,"Com=Rf Fr Rf Fr\n"); + fprintf(out,"Orig=RfeLA PodRRAP FrePL RfeLA PodRRAP FrePL\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM06+AP+AP %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM06+AP+AP %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM06+AP+AP: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM06+AP+AP, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM06+AP+AP, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM06.c b/tests/tcg/aarch64/litmus/ARMARM06.c new file mode 100644 index 0000000..a2fa38e --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM06.c @@ -0,0 +1,581 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 4 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_1_x0; + int *out_1_x2; + int *out_3_x0; + int *out_3_x2; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_1_x0,int _out_1_x2,int _out_3_x0,int _out_3_x2) { + switch (_out_1_x0) { + case 1: + switch (_out_1_x2) { + case 0: + switch (_out_3_x0) { + case 1: + switch (_out_3_x2) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 4 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_1_x0_f = 0 ; +static const int out_1_x2_f = 1 ; +static const int out_3_x0_f = 2 ; +static const int out_3_x2_f = 3 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>1:X0=%i; 1:X2=%i; 3:X0=%i; 3:X2=%i;\n",c,show ? '*' : ':',(int)o[out_1_x0_f],(int)o[out_1_x2_f],(int)o[out_3_x0_f],(int)o[out_3_x2_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_1_x0 = malloc_check(size_of_test*sizeof(*(_a->out_1_x0))); + _a->out_1_x2 = malloc_check(size_of_test*sizeof(*(_a->out_1_x2))); + _a->out_3_x0 = malloc_check(size_of_test*sizeof(*(_a->out_3_x0))); + _a->out_3_x2 = malloc_check(size_of_test*sizeof(*(_a->out_3_x2))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_1_x0); + free((void *)_a->out_1_x2); + free((void *)_a->out_3_x0); + free((void *)_a->out_3_x2); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_1_x0[_i] = -239487; + _a->out_1_x2[_i] = -239487; + _a->out_3_x0[_i] = -239487; + _a->out_3_x2[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("ARMARM06, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("ARMARM06, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P0\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x0 = _a->out_1_x0; + int *out_1_x2 = _a->out_1_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P1_1\n\t" +"ldar %w[x2],[%[x3]]\n" +"#END _litmus_P1\n\t" +:[x2] "=&r" (out_1_x2[_i]),[x0] "=&r" (out_1_x0[_i]) +:[x1] "r" (&_a->x[_i]),[x3] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P2(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P2\n" +"#_litmus_P2_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P2_1\n\t" +"stlr %w[x0],[%[x1]]\n" +"#END _litmus_P2\n\t" +:[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P3(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"ARMARM06"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_3_x0 = _a->out_3_x0; + int *out_3_x2 = _a->out_3_x2; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); +asm __volatile__ ( +"\n" +"#START _litmus_P3\n" +"#_litmus_P3_0\n\t" +"ldar %w[x0],[%[x1]]\n" +"#_litmus_P3_1\n\t" +"ldar %w[x2],[%[x3]]\n" +"#END _litmus_P3\n\t" +:[x2] "=&r" (out_3_x2[_i]),[x0] "=&r" (out_3_x0[_i]) +:[x1] "r" (&_a->y[_i]),[x3] "r" (&_a->x[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1,&P2,&P3}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_1_x0_i = ctx.out_1_x0[_i]; + int _out_1_x2_i = ctx.out_1_x2[_i]; + int _out_3_x0_i = ctx.out_3_x0[_i]; + int _out_3_x2_i = ctx.out_3_x2[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_1_x0_i,_out_1_x2_i,_out_3_x0_i,_out_3_x2_i)); + o[out_1_x0_f] = _out_1_x0_i; + o[out_1_x2_f] = _out_1_x2_i; + o[out_3_x0_f] = _out_3_x0_i; + o[out_3_x2_f] = _out_3_x2_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test ARMARM06 Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (1:X0=1 /\\ 1:X2=0 /\\ 3:X0=1 /\\ 3:X2=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=e1d155e0765dad3f8a9955c387076a95\n"); + fprintf(out,"Com=Rf Fr Rf Fr\n"); + fprintf(out,"Orig=RfeLA PodRRAA FreAL RfeLA PodRRAA FreAL\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation ARMARM06 %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time ARMARM06 %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "ARMARM06: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("ARMARM06, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("ARMARM06, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/ARMARM07+SAL.c b/tests/tcg/aarch64/litmus/ARMARM07+SAL.c new file mode 100644 index 0000000..82e8c7e --- /dev/null +++ b/tests/tcg/aarch64/litmus/ARMARM07+SAL.c @@ -0,0 +1,497 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* This C source is a product of litmus7 and includes source that is */ +/* governed by the CeCILL-B license. */ +/****************************************************************************/ +/* Parameters */ +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +#define N 2 +#define AFF_INCR (0) +/* Includes */ +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" +#include "outs.h" +#include "affinity.h" + +/* params */ +typedef struct { + int verbose; + int size_of_test,max_run; + int stride; + aff_mode_t aff_mode; + int ncpus, ncpus_used; + int do_change; +} param_t; + + +/* Full memory barrier */ +inline static void mbar(void) { + asm __volatile__ ("dsb sy" ::: "memory"); +} + +/* Barriers macros */ +inline static void barrier_wait(unsigned int id, unsigned int k, int volatile *b) { + if ((k % N) == id) { + *b = 1 ; + } else { + while (*b == 0) ; + } +} + +/**********************/ +/* Context definition */ +/**********************/ + + +typedef struct { +/* Shared variables */ + int *y; + int *x; +/* Final content of observed registers */ + int *out_0_x3; + int *out_1_x3; +/* Check data */ + pb_t *fst_barrier; +/* Barrier for litmus loop */ + int volatile *barrier; +/* Instance seed */ + st_t seed; +/* Parameters */ + param_t *_p; +} ctx_t; + +inline static int final_cond(int _out_0_x3,int _out_1_x3) { + switch (_out_0_x3) { + case 0: + switch (_out_1_x3) { + case 0: + return 1; + default: + return 0; + } + default: + return 0; + } +} + +inline static int final_ok(int cond) { + return cond; +} + +/**********************/ +/* Outcome collection */ +/**********************/ +#define NOUTS 2 +typedef intmax_t outcome_t[NOUTS]; + +static const int out_0_x3_f = 0 ; +static const int out_1_x3_f = 1 ; + + +typedef struct hist_t { + outs_t *outcomes ; + count_t n_pos,n_neg ; +} hist_t ; + +static hist_t *alloc_hist(void) { + hist_t *p = malloc_check(sizeof(*p)) ; + p->outcomes = NULL ; + p->n_pos = p->n_neg = 0 ; + return p ; +} + +static void free_hist(hist_t *h) { + free_outs(h->outcomes) ; + free(h) ; +} + +static void add_outcome(hist_t *h, count_t v, outcome_t o, int show) { + h->outcomes = add_outcome_outs(h->outcomes,o,NOUTS,v,show) ; +} + +static void merge_hists(hist_t *h0, hist_t *h1) { + h0->n_pos += h1->n_pos ; + h0->n_neg += h1->n_neg ; + h0->outcomes = merge_outs(h0->outcomes,h1->outcomes,NOUTS) ; +} + +static count_t sum_hist(hist_t *h) { + return sum_outs(h->outcomes) ; +} + + +static void do_dump_outcome(FILE *fhist, intmax_t *o, count_t c, int show) { + fprintf(fhist,"%-6"PCTR"%c>0:X3=%i; 1:X3=%i;\n",c,show ? '*' : ':',(int)o[out_0_x3_f],(int)o[out_1_x3_f]); +} + +static void just_dump_outcomes(FILE *fhist, hist_t *h) { + outcome_t buff ; + dump_outs(fhist,do_dump_outcome,h->outcomes,buff,NOUTS) ; +} + +/*******************************************************/ +/* Context allocation, freeing and reinitialization */ +/*******************************************************/ + +static void init(ctx_t *_a) { + int size_of_test = _a->_p->size_of_test; + + _a->seed = rand(); + _a->out_0_x3 = malloc_check(size_of_test*sizeof(*(_a->out_0_x3))); + _a->out_1_x3 = malloc_check(size_of_test*sizeof(*(_a->out_1_x3))); + _a->y = malloc_check(size_of_test*sizeof(*(_a->y))); + _a->x = malloc_check(size_of_test*sizeof(*(_a->x))); + _a->fst_barrier = pb_create(N); + _a->barrier = malloc_check(size_of_test*sizeof(*(_a->barrier))); +} + +static void finalize(ctx_t *_a) { + free((void *)_a->y); + free((void *)_a->x); + free((void *)_a->out_0_x3); + free((void *)_a->out_1_x3); + pb_free(_a->fst_barrier); + free((void *)_a->barrier); +} + +static void reinit(ctx_t *_a) { + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + _a->y[_i] = 0; + _a->x[_i] = 0; + _a->out_0_x3[_i] = -239487; + _a->out_1_x3[_i] = -239487; + _a->barrier[_i] = 0; + } +} + +/**************************************/ +/* Prefetch (and check) global values */ +/**************************************/ + +static void check_globals(ctx_t *_a) { + int *y = _a->y; + int *x = _a->x; + for (int _i = _a->_p->size_of_test-1 ; _i >= 0 ; _i--) { + if (rand_bit(&(_a->seed)) && y[_i] != 0) fatal("SAL, check_globals failed"); + if (rand_bit(&(_a->seed)) && x[_i] != 0) fatal("SAL, check_globals failed"); + } + pb_wait(_a->fst_barrier); +} + +/***************/ +/* Litmus code */ +/***************/ + +typedef struct { + int th_id; /* I am running on this thread */ + int *cpu; /* On this cpu */ + ctx_t *_a; /* In this context */ +} parg_t; + + + + + +static void *P0(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"SAL"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_0_x3 = _a->out_0_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P0\n" +"#_litmus_P0_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P0_1\n\t" +"str %w[x0],[%[x1]]\n" +"#_litmus_P0_2\n\t" +"dmb sy\n" +"#_litmus_P0_3\n\t" +"ldr %[x3],[%[x2]]\n" +"#END _litmus_P0\n\t" +:[x3] "=&r" (out_0_x3[_i]),[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]),[x2] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +static void *P1(void *_vb) { + mbar(); + parg_t *_b = (parg_t *)_vb; + ctx_t *_a = _b->_a; + int _ecpu = _b->cpu[_b->th_id]; + force_one_affinity(_ecpu,AVAIL,_a->_p->verbose,"SAL"); + check_globals(_a); + int _th_id = _b->th_id; + int volatile *barrier = _a->barrier; + int _size_of_test = _a->_p->size_of_test; + int _stride = _a->_p->stride; + int *out_1_x3 = _a->out_1_x3; + for (int _j = _stride ; _j > 0 ; _j--) { + for (int _i = _size_of_test-_j ; _i >= 0 ; _i -= _stride) { + barrier_wait(_th_id,_i,&barrier[_i]); + int trashed_x0; +asm __volatile__ ( +"\n" +"#START _litmus_P1\n" +"#_litmus_P1_0\n\t" +"mov %w[x0],#1\n" +"#_litmus_P1_1\n\t" +"str %w[x0],[%[x2]]\n" +"#_litmus_P1_2\n\t" +"dmb sy\n" +"#_litmus_P1_3\n\t" +"ldr %[x3],[%[x1]]\n" +"#END _litmus_P1\n\t" +:[x3] "=&r" (out_1_x3[_i]),[x0] "=&r" (trashed_x0) +:[x1] "r" (&_a->x[_i]),[x2] "r" (&_a->y[_i]) +:"cc","memory" +); + } + } + mbar(); + return NULL; +} + +typedef struct { + pm_t *p_mutex; + pb_t *p_barrier; + param_t *_p; + int z_id; + int *cpus; +} zyva_t; + +#define NT N + +static void *zyva(void *_va) { + zyva_t *_a = (zyva_t *) _va; + param_t *_b = _a->_p; + pb_wait(_a->p_barrier); + pthread_t thread[NT]; + parg_t parg[N]; + f_t *fun[] = {&P0,&P1}; + hist_t *hist = alloc_hist(); + ctx_t ctx; + ctx._p = _b; + + init(&ctx); + for (int _p = N-1 ; _p >= 0 ; _p--) { + parg[_p].th_id = _p; parg[_p]._a = &ctx; + parg[_p].cpu = &(_a->cpus[0]); + } + + for (int n_run = 0 ; n_run < _b->max_run ; n_run++) { + if (_b->aff_mode == aff_random) { + pb_wait(_a->p_barrier); + if (_a->z_id == 0) perm_prefix_ints(&ctx.seed,_a->cpus,_b->ncpus_used,_b->ncpus); + pb_wait(_a->p_barrier); + } else { + } + if (_b->verbose>1) fprintf(stderr,"Run %i of %i\r", n_run, _b->max_run); + reinit(&ctx); + if (_b->do_change) perm_funs(&ctx.seed,fun,N); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + launch(&thread[_p],fun[_p],&parg[_p]); + } + if (_b->do_change) perm_threads(&ctx.seed,thread,NT); + for (int _p = NT-1 ; _p >= 0 ; _p--) { + join(&thread[_p]); + } + /* Log final states */ + for (int _i = _b->size_of_test-1 ; _i >= 0 ; _i--) { + int _out_0_x3_i = ctx.out_0_x3[_i]; + int _out_1_x3_i = ctx.out_1_x3[_i]; + outcome_t o; + int cond; + + cond = final_ok(final_cond(_out_0_x3_i,_out_1_x3_i)); + o[out_0_x3_f] = _out_0_x3_i; + o[out_1_x3_f] = _out_1_x3_i; + add_outcome(hist,1,o,cond); + if (cond) { hist->n_pos++; } else { hist->n_neg++; } + } + } + + finalize(&ctx); + return hist; +} + +#define ENOUGH 10 + +static int postlude(FILE *out,cmd_t *cmd,hist_t *hist,count_t p_true,count_t p_false,tsc_t total) { + fprintf(out,"Test SAL Forbidden\n"); + fprintf(out,"Histogram (%i states)\n",finals_outs(hist->outcomes)); + just_dump_outcomes(out,hist); + int cond = p_true == 0; + fprintf(out,"%s\n",cond?"Ok":"No"); + fprintf(out,"\nWitnesses\n"); + fprintf(out,"Positive: %" PCTR ", Negative: %" PCTR "\n",p_false,p_true); + fprintf(out,"Condition ~exists (0:X3=0 /\\ 1:X3=0) is %svalidated\n",cond ? "" : "NOT "); + fprintf(out,"Hash=8d89ac48ecfc60bb2f37937f74cbba0d\n"); + count_t cond_true = p_true; + count_t cond_false = p_false; + fprintf(out,"Observation SAL %s %" PCTR " %" PCTR "\n",!cond_true ? "Never" : !cond_false ? "Always" : "Sometimes",cond_true,cond_false); + if (p_true > 0) { + } + fprintf(out,"Time SAL %.2f\n",total / 1000000.0); + fflush(out); + return cond; +} + +static int run(cmd_t *cmd,cpus_t *def_all_cpus,FILE *out) { + tsc_t start = timeofday(); + param_t prm ; +/* Set some parameters */ + prm.verbose = cmd->verbose; + prm.size_of_test = cmd->size_of_test; + prm.max_run = cmd->max_run; + prm.stride = cmd->stride; + prm.do_change = 1; + if (cmd->fix) prm.do_change = 0; +/* Computes number of test concurrent instances */ + int n_avail = cmd->avail > 0 ? cmd->avail : cmd->aff_cpus->sz; + if (n_avail > cmd->aff_cpus->sz) log_error("Warning: avail=%i, available=%i\n",n_avail, cmd->aff_cpus->sz); + int n_exe; + if (cmd->n_exe > 0) { + n_exe = cmd->n_exe; + } else { + n_exe = n_avail < N ? 1 : n_avail / N; + } +/* Set affinity parameters */ + cpus_t *all_cpus = cmd->aff_cpus; + int aff_cpus_sz = cmd->aff_mode == aff_random ? max(all_cpus->sz,N*n_exe) : N*n_exe; + int aff_cpus[aff_cpus_sz]; + prm.aff_mode = cmd->aff_mode; + prm.ncpus = aff_cpus_sz; + prm.ncpus_used = N*n_exe; +/* Show parameters to user */ + if (prm.verbose) { + log_error( "SAL: n=%i, r=%i, s=%i",n_exe,prm.max_run,prm.size_of_test); + log_error(", st=%i",prm.stride); + if (cmd->aff_mode == aff_incr) { + log_error( ", i=%i",cmd->aff_incr); + } else if (cmd->aff_mode == aff_random) { + log_error(", +ra"); + } else if (cmd->aff_mode == aff_custom) { + log_error(", +ca"); + } else if (cmd->aff_mode == aff_scan) { + log_error(", +sa"); + } + log_error(", p='"); + cpus_dump(stderr,cmd->aff_cpus); + log_error("'"); + log_error("\n"); + } + if (cmd->aff_mode == aff_random) { + for (int k = 0 ; k < aff_cpus_sz ; k++) { + aff_cpus[k] = all_cpus->cpu[k % all_cpus->sz]; + } + } + hist_t *hist = NULL; + int n_th = n_exe-1; + pthread_t th[n_th]; + zyva_t zarg[n_exe]; + pm_t *p_mutex = pm_create(); + pb_t *p_barrier = pb_create(n_exe); + int next_cpu = 0; + int delta = cmd->aff_incr; + if (delta <= 0) { + for (int k=0 ; k < all_cpus->sz ; k++) all_cpus->cpu[k] = -1; + delta = 1; + } else { + delta %= all_cpus->sz; + } + int start_scan=0, max_start=gcd(delta,all_cpus->sz); + int *aff_p = aff_cpus; + for (int k=0 ; k < n_exe ; k++) { + zyva_t *p = &zarg[k]; + p->_p = &prm; + p->p_mutex = p_mutex; p->p_barrier = p_barrier; + p->z_id = k; + p->cpus = aff_p; + if (cmd->aff_mode != aff_incr) { + aff_p += N; + } else { + for (int i=0 ; i < N ; i++) { + *aff_p = all_cpus->cpu[next_cpu]; aff_p++; + next_cpu += delta; next_cpu %= all_cpus->sz; + if (next_cpu == start_scan) { + start_scan++ ; start_scan %= max_start; + next_cpu = start_scan; + } + } + } + if (k < n_th) { + launch(&th[k],zyva,p); + } else { + hist = (hist_t *)zyva(p); + } + } + + count_t n_outs = prm.size_of_test; n_outs *= prm.max_run; + for (int k=0 ; k < n_th ; k++) { + hist_t *hk = (hist_t *)join(&th[k]); + if (sum_hist(hk) != n_outs || hk->n_pos + hk->n_neg != n_outs) { + fatal("SAL, sum_hist"); + } + merge_hists(hist,hk); + free_hist(hk); + } + cpus_free(all_cpus); + tsc_t total = timeofday() - start; + pm_free(p_mutex); + pb_free(p_barrier); + + n_outs *= n_exe ; + if (sum_hist(hist) != n_outs || hist->n_pos + hist->n_neg != n_outs) { + fatal("SAL, sum_hist") ; + } + count_t p_true = hist->n_pos, p_false = hist->n_neg; + int cond = postlude(out,cmd,hist,p_true,p_false,total); + free_hist(hist); + return cond; +} + + +int main(int argc, char **argv) { + cpus_t *def_all_cpus = read_force_affinity(AVAIL,0); + if (def_all_cpus->sz < N) { + cpus_free(def_all_cpus); + return EXIT_SUCCESS; + } + cmd_t def = { 0, NUMBER_OF_RUN, SIZE_OF_TEST, STRIDE, AVAIL, 0, 0, aff_incr, 0, 0, AFF_INCR, def_all_cpus, NULL, -1, MAX_LOOP, NULL, NULL, -1, -1, -1, 0, 0}; + cmd_t cmd = def; + parse_cmd(argc,argv,&def,&cmd); + int cond = run(&cmd,def_all_cpus,stdout); + if (def_all_cpus != cmd.aff_cpus) cpus_free(def_all_cpus); + return cond ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/tcg/aarch64/litmus/Makefile b/tests/tcg/aarch64/litmus/Makefile new file mode 100644 index 0000000..46178f2 --- /dev/null +++ b/tests/tcg/aarch64/litmus/Makefile @@ -0,0 +1,53 @@ +GCC=aarch64-linux-gnu-gcc +GCCOPTS=-D_GNU_SOURCE -DFORCE_AFFINITY -Wall -std=gnu99 -O2 -pthread -static +LINKOPTS= +SRC=\ + ARMARM00.c\ + ARMARM01.c\ + ARMARM02.c\ + ARMARM03.c\ + ARMARM04+BIS.c\ + ARMARM04.c\ + ARMARM04+TER.c\ + ARMARM05.c\ + ARMARM06+AP+AA.c\ + ARMARM06+AP+AP.c\ + ARMARM06.c\ + ARMARM07+SAL.c\ + +EXE=$(SRC:.c=.exe) +T=$(SRC:.c=.t) + +all: $(EXE) $(T) + +clean: + /bin/rm -f *.o *.s *.t *.exe *~ + +cleansource: + /bin/rm -f *.o *.c *.h *.s *~ + +affinity.o: affinity.c + $(GCC) $(GCCOPTS) -O2 -c affinity.c + +outs.o: outs.c + $(GCC) $(GCCOPTS) -O2 -c outs.c + +utils.o: utils.c + $(GCC) $(GCCOPTS) -O2 -c utils.c + +litmus_rand.o: litmus_rand.c + $(GCC) $(GCCOPTS) -O2 -c litmus_rand.c + +UTILS=affinity.o outs.o utils.o litmus_rand.o + +%.exe:%.s $(UTILS) + $(GCC) $(GCCOPTS) $(LINKOPTS) -o $@ $(UTILS) $< + +%.s:%.c + $(GCC) $(GCCOPTS) -S $< + +%.t:%.s + awk -f show.awk $< > $@ + +tests: all + ./run.sh diff --git a/tests/tcg/aarch64/litmus/README.txt b/tests/tcg/aarch64/litmus/README.txt new file mode 100644 index 0000000..c160b8d --- /dev/null +++ b/tests/tcg/aarch64/litmus/README.txt @@ -0,0 +1,22 @@ +Tests produced by litmus for architecture AArch64 on linux + +COMPILING + with command 'make [-j N]' or 'sh comp.sh' + +RUNNING ALL TESTS + with command 'sh run.sh'. Test result on standard output. + +RUNNING ONE TEST + Tests are .exe files, for instance ARMARM06.exe, run it by './ARMARM06.exe' + +RUNNING OPTIONS + Main options to the run.sh script and to .exe files: + -v be verbose (can be repeated). + -a number of (logical) processors available, default 0. + The default value of 0 means that .exe files attempt + to infer the actual number of logical threads. + -s one run operates on arrays of size , default 100000. + -r number of runs, default 10. + + For more options see for instance './ARMARM06.exe -help' and litmus documentation + diff --git a/tests/tcg/aarch64/litmus/affinity.c b/tests/tcg/aarch64/litmus/affinity.c new file mode 100644 index 0000000..9535bf2 --- /dev/null +++ b/tests/tcg/aarch64/litmus/affinity.c @@ -0,0 +1,159 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#include +#include +#include +#include "utils.h" +#include "affinity.h" + +#ifdef CPUS_DEFINED +cpus_t *read_affinity(void) { + cpu_set_t mask; + int sz = 0 ; + int res = pthread_getaffinity_np(pthread_self(), sizeof(mask), &mask) ; + + if (res != 0) { + errexit("pthread_getaffinity_np",res); + } + for (int p=0 ; p < CPU_SETSIZE ; p++) { + if (CPU_ISSET(p,&mask)) sz++ ; + } + + cpus_t *r = cpus_create(sz) ; + for (int p=0, *q=r->cpu ; p < CPU_SETSIZE ; p++) { + if (CPU_ISSET(p,&mask)) *q++ = p ; + } + return r ; +} + +#endif +/* Attempt to force processors wake up, on devices where unused procs + go to sleep... */ + + +#ifdef FORCE_AFFINITY +const static tsc_t sec = (tsc_t)1000000 ; + +static void* loop(void *p) { + tsc_t *q = p ; + tsc_t max = *q ; + while (timeofday() < max) ; + return NULL ; +} + + +static void warm_up(int sz, tsc_t d) { + pthread_t th[sz]; + d += timeofday() ; + for (int k = 0 ; k < sz ; k++) launch(&th[k], loop, &d) ; + for (int k = 0 ; k < sz ; k++) join(&th[k]) ; +} + +#ifdef CPUS_DEFINED +cpus_t *read_force_affinity(int n_avail, int verbose) { + int sz = n_avail <= 1 ? 1 : n_avail ; + tsc_t max = sec / 100 ; + + for ( ; ; ) { + warm_up(sz+1,max) ; + cpus_t *r = read_affinity() ; + if (n_avail <= r->sz) return r ; + if (verbose) { + fprintf(stderr,"Read affinity: '") ; + cpus_dump(stderr,r) ; + fprintf(stderr,"'\n") ; + } + cpus_free(r) ; + } +} +#endif +#endif + +#ifdef CPUS_DEFINED + +/* Enforcing processor affinity. + Notice that logical processor numbers may be negative. + In that case, affinity setting is ignored */ + + +void write_affinity(cpus_t *p) { + cpu_set_t mask; + int exists_pos = 0 ; + + CPU_ZERO(&mask) ; + for (int k = 0 ; k < p->sz ; k++) { + if (p->cpu[k] >= 0) { + CPU_SET(p->cpu[k],&mask) ; + exists_pos = 1 ; + } + } + if (exists_pos) { + int r = pthread_setaffinity_np(pthread_self(),sizeof(mask),&mask) ; + if (r != 0) { + errexit("pthread_setaffinity_np",r) ; + } + } +} +#endif + +void write_one_affinity(int a) { + if (a >= 0) { + cpu_set_t mask; + CPU_ZERO(&mask) ; + CPU_SET(a,&mask) ; + int r = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) ; + if (r != 0) { + errexit("pthread_setaffinity_np",r) ; + } + } +} + +#ifdef FORCE_AFFINITY +/* Get the number of present cpus, fragile */ + +static const char *present = "/sys/devices/system/cpu/present" ; + +static int get_present(void) { + FILE *fp = fopen(present,"r") ; + if (fp == NULL) return -1 ; + int r1,r2 ; + int n = fscanf(fp,"%d-%d\n",&r1,&r2) ; + fclose(fp) ; + if (n != 2) return -1 ; + return r2-r1+1 ; +} + +void force_one_affinity(int a, int sz,int verbose, char *name) { + if (a >= 0) { + cpu_set_t mask; + int r ; + CPU_ZERO(&mask) ; + CPU_SET(a,&mask) ; + do { + r = pthread_setaffinity_np(pthread_self(), sizeof(mask), &mask) ; + if (r != 0) { + if (verbose) + fprintf(stderr,"%s: force %i failed\n",name,a) ; + int nwarm = get_present() ; + if (verbose > 1) + fprintf(stderr,"%s: present=%i\n",name,nwarm) ; + if (nwarm < 0) nwarm = sz+1 ; + warm_up(nwarm,sec/100) ; + } + } while (r != 0) ; + } +} +#endif diff --git a/tests/tcg/aarch64/litmus/affinity.h b/tests/tcg/aarch64/litmus/affinity.h new file mode 100644 index 0000000..9fb6a25 --- /dev/null +++ b/tests/tcg/aarch64/litmus/affinity.h @@ -0,0 +1,34 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#ifndef _AFFINITY_H +#define _AFFINITY_H 1 + +#include "utils.h" + +#ifdef CPUS_DEFINED +cpus_t *read_affinity(void) ; +#ifdef FORCE_AFFINITY +cpus_t *read_force_affinity(int n_avail, int verbose) ; +#endif +void write_affinity(cpus_t *p) ; +#endif + +void write_one_affinity(int cpu) ; +#ifdef FORCE_AFFINITY +void force_one_affinity(int cpu, int sz, int verbose, char *name) ; +#endif + +#endif diff --git a/tests/tcg/aarch64/litmus/comp.sh b/tests/tcg/aarch64/litmus/comp.sh new file mode 100644 index 0000000..62d65ba --- /dev/null +++ b/tests/tcg/aarch64/litmus/comp.sh @@ -0,0 +1,30 @@ +GCC=gcc +GCCOPTS="-D_GNU_SOURCE -DFORCE_AFFINITY -Wall -std=gnu99 -O2 -pthread" +LINKOPTS="" +/bin/rm -f *.exe *.s +$GCC $GCCOPTS -O2 -c affinity.c +$GCC $GCCOPTS -O2 -c outs.c +$GCC $GCCOPTS -O2 -c utils.c +$GCC $GCCOPTS -O2 -c litmus_rand.c +$GCC $GCCOPTS $LINKOPTS -o ARMARM00.exe affinity.o outs.o utils.o litmus_rand.o ARMARM00.c +$GCC $GCCOPTS -S ARMARM00.c && awk -f show.awk ARMARM00.s > ARMARM00.t && /bin/rm ARMARM00.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM01.exe affinity.o outs.o utils.o litmus_rand.o ARMARM01.c +$GCC $GCCOPTS -S ARMARM01.c && awk -f show.awk ARMARM01.s > ARMARM01.t && /bin/rm ARMARM01.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM02.exe affinity.o outs.o utils.o litmus_rand.o ARMARM02.c +$GCC $GCCOPTS -S ARMARM02.c && awk -f show.awk ARMARM02.s > ARMARM02.t && /bin/rm ARMARM02.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM03.exe affinity.o outs.o utils.o litmus_rand.o ARMARM03.c +$GCC $GCCOPTS -S ARMARM03.c && awk -f show.awk ARMARM03.s > ARMARM03.t && /bin/rm ARMARM03.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM04+BIS.exe affinity.o outs.o utils.o litmus_rand.o ARMARM04+BIS.c +$GCC $GCCOPTS -S ARMARM04+BIS.c && awk -f show.awk ARMARM04+BIS.s > ARMARM04+BIS.t && /bin/rm ARMARM04+BIS.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM04.exe affinity.o outs.o utils.o litmus_rand.o ARMARM04.c +$GCC $GCCOPTS -S ARMARM04.c && awk -f show.awk ARMARM04.s > ARMARM04.t && /bin/rm ARMARM04.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM04+TER.exe affinity.o outs.o utils.o litmus_rand.o ARMARM04+TER.c +$GCC $GCCOPTS -S ARMARM04+TER.c && awk -f show.awk ARMARM04+TER.s > ARMARM04+TER.t && /bin/rm ARMARM04+TER.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM05.exe affinity.o outs.o utils.o litmus_rand.o ARMARM05.c +$GCC $GCCOPTS -S ARMARM05.c && awk -f show.awk ARMARM05.s > ARMARM05.t && /bin/rm ARMARM05.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM06+AP+AA.exe affinity.o outs.o utils.o litmus_rand.o ARMARM06+AP+AA.c +$GCC $GCCOPTS -S ARMARM06+AP+AA.c && awk -f show.awk ARMARM06+AP+AA.s > ARMARM06+AP+AA.t && /bin/rm ARMARM06+AP+AA.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM06+AP+AP.exe affinity.o outs.o utils.o litmus_rand.o ARMARM06+AP+AP.c +$GCC $GCCOPTS -S ARMARM06+AP+AP.c && awk -f show.awk ARMARM06+AP+AP.s > ARMARM06+AP+AP.t && /bin/rm ARMARM06+AP+AP.s +$GCC $GCCOPTS $LINKOPTS -o ARMARM06.exe affinity.o outs.o utils.o litmus_rand.o ARMARM06.c +$GCC $GCCOPTS -S ARMARM06.c && awk -f show.awk ARMARM06.s > ARMARM06.t && /bin/rm ARMARM06.s diff --git a/tests/tcg/aarch64/litmus/litmus_rand.c b/tests/tcg/aarch64/litmus/litmus_rand.c new file mode 100644 index 0000000..de33032 --- /dev/null +++ b/tests/tcg/aarch64/litmus/litmus_rand.c @@ -0,0 +1,64 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#include +#include "litmus_rand.h" + +/* + Simple generator + http://en.wikipedia.org/wiki/Linear_congruential_generator +*/ + + +/* + + From ocaml sources: (globroot.c) + Linear congruence with modulus = 2^32, multiplier = 69069 + (Knuth vol 2 p. 106, line 15 of table 1), additive = 25173. + + + Knuth (vol 2 p. 13) shows that the least significant bits are + "less random" than the most significant bits with a modulus of 2^m. + We just swap half words, enough? */ + +static const uint32_t a = 69069; +static const uint32_t c = 25173 ; + +inline static uint32_t unlocked_rand(st_t *st) { + uint32_t r = a * *st + c ; + *st = r ; + /* Swap high & low bits */ + uint32_t low = r & 0xffff ; + uint32_t high = r >> 16 ; + r = high | (low << 16) ; + return r ; +} + +int rand_bit(st_t *st) { + uint32_t r = unlocked_rand(st) ; + r &= 1 ; + return r ; +} + +static const uint32_t r_max = UINT32_MAX ; + +uint32_t rand_k (uint32_t *st,uint32_t k) { + uint32_t r, v ; + do { + r = unlocked_rand(st) ; + v = r % k ; + } while (r-v > r_max-k+1) ; + return v ; +} diff --git a/tests/tcg/aarch64/litmus/litmus_rand.h b/tests/tcg/aarch64/litmus/litmus_rand.h new file mode 100644 index 0000000..c358ccb --- /dev/null +++ b/tests/tcg/aarch64/litmus/litmus_rand.h @@ -0,0 +1,29 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#ifndef _LITMUS_RAND_H +#define _LITMUS_RAND_H 1 + +#include + +/* type of state for pseudorandom generators */ +typedef uint32_t st_t ; + +/* Unlocked random bit */ + +int rand_bit(st_t *st) ; +uint32_t rand_k(st_t *st,uint32_t n) ; + +#endif diff --git a/tests/tcg/aarch64/litmus/outs.c b/tests/tcg/aarch64/litmus/outs.c new file mode 100644 index 0000000..178f1d2 --- /dev/null +++ b/tests/tcg/aarch64/litmus/outs.c @@ -0,0 +1,148 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#include +#include +#include "outs.h" + +/**********************/ +/* Lexicographic tree */ +/**********************/ + +#if 0 +static void debug(int *t, int i, int j) { + for (int k=i ; k <= j ; k++) + fprintf(stderr,"%i",t[k]) ; + fprintf(stderr,"\n") ; +} +#endif + + +void *malloc_check(size_t sz) ; + +static outs_t *alloc_outs(intmax_t k) { + outs_t *r = malloc_check(sizeof(*r)) ; + r->k = k ; + r->c = 0 ; + r->show = 0 ; + r->next = r->down = NULL ; + return r ; +} + +void free_outs(outs_t *p) { + if (p == NULL) return ; + free_outs(p->next) ; + free_outs(p->down) ; + free(p) ; +} + +/* Worth writing as a loop, since called many times */ +static outs_t *loop_add_outcome_outs(outs_t *p, intmax_t *k, int i, count_t c, int show) { + outs_t *r = p ; + if (p == NULL || k[i] < p->k) { + r = alloc_outs(k[i]) ; + r->next = p ; + p = r ; + } + for ( ; ; ) { + outs_t **q ; + if (k[i] > p->k) { + q = &(p->next) ; + p = p->next ; + } else if (i <= 0) { + p->c += c ; + p->show = show || p->show ; + return r ; + } else { + i-- ; + q = &(p->down) ; + p = p->down ; + } + if (p == NULL || k[i] < p->k) { + outs_t *a = alloc_outs(k[i]) ; + a->next = p ; + p = a ; + *q = a ; + } + } +} + +outs_t *add_outcome_outs(outs_t *p, intmax_t *k, int sz, count_t c, int show) { + return loop_add_outcome_outs(p,k,sz-1,c,show) ; +} + +count_t sum_outs(outs_t *p) { + count_t r = 0 ; + for ( ; p ; p = p->next) { + r += p->c ; + r += sum_outs(p->down) ; + } + return r ; +} + +int finals_outs(outs_t *p) { + int r = 0 ; + for ( ; p ; p = p->next) { + if (p->c > 0) r++ ; + r += finals_outs(p->down) ; + } + return r ; +} + +void dump_outs (FILE *chan, dump_outcome *dout,outs_t *p, intmax_t *buff,int sz) { + for ( ; p ; p = p->next) { + buff[sz-1] = p->k ; + if (p->c > 0) { + dout(chan,buff,p->c,p->show) ; + } else if (p->down) { + dump_outs(chan,dout,p->down,buff,sz-1) ; + } + } +} + +/* merge p and q into p */ +static outs_t *do_merge_outs(outs_t *p, outs_t *q) { + if (q == NULL) { // Nothing to add + return p ; + } + if (p == NULL || q->k < p->k) { // Need a cell + outs_t *r = alloc_outs(q->k) ; + r->next = p ; + p = r ; + } + if (p->k == q->k) { + p->c += q->c ; + p->show = p->show || q->show ; + p->down = do_merge_outs(p->down,q->down) ; + p->next = do_merge_outs(p->next,q->next) ; + } else { + p->next = do_merge_outs(p->next,q) ; + } + return p ; +} + +outs_t *merge_outs(outs_t *p, outs_t *q, int sz) { + return do_merge_outs(p,q) ; +} + +int same_outs(outs_t *p,outs_t *q) { + while (p && q) { + if (p->k != q->k || p->c != q->c || p->show != q->show) return 0 ; + if (!same_outs(p->down,q->down)) return 0 ; + p = p->next ; + q = q->next ; + } + return p == q ; /* == NULL */ +} diff --git a/tests/tcg/aarch64/litmus/outs.h b/tests/tcg/aarch64/litmus/outs.h new file mode 100644 index 0000000..761590f --- /dev/null +++ b/tests/tcg/aarch64/litmus/outs.h @@ -0,0 +1,49 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#ifndef _OUTS_H +#define _OUTS_H 1 + +#include + +/************************/ +/* Histogram structure */ +/************************/ + + +/* 64bit counters, should be enough! */ +#include +typedef uint64_t count_t; +#define PCTR PRIu64 + + + + +typedef struct outs_t { + struct outs_t *next,*down ; + count_t c ; + intmax_t k ; + int show ; +} outs_t ; + +void free_outs(outs_t *p) ; +outs_t *add_outcome_outs(outs_t *p, intmax_t *o, int sz, count_t v, int show) ; +int finals_outs(outs_t *p) ; +count_t sum_outs(outs_t *p) ; +typedef void dump_outcome(FILE *chan, intmax_t *o, count_t c, int show) ; +void dump_outs (FILE *chan, dump_outcome *dout,outs_t *p, intmax_t *buff, int sz) ; +outs_t *merge_outs(outs_t *p,outs_t *q, int sz) ; +int same_outs(outs_t *p,outs_t *q) ; +#endif diff --git a/tests/tcg/aarch64/litmus/run.sh b/tests/tcg/aarch64/litmus/run.sh new file mode 100755 index 0000000..21604a1 --- /dev/null +++ b/tests/tcg/aarch64/litmus/run.sh @@ -0,0 +1,378 @@ +date +LITMUSOPTS="${@:-$LITMUSOPTS}" +SLEEP=0 +if [ ! -f ARMARM00.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM00.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM00 +"PodWWPL RfeLA PodRRAP Fre" + +{0:X1=x; 0:X3=y; 1:X1=y; 1:X3=x; 1:X2=-1;} + + P0 | P1 ; + MOV W0,#1 | LDAR W0,[X1] ; + STR W0,[X1] | CMP W0,#1 ; + MOV W2,#1 | B.NE Exit1 ; + STLR W2,[X3] | LDR W2,[X3] ; + | Exit1: ; + +~exists (1:X0=1 /\ 1:X2=0) +Generated assembler +EOF +cat ARMARM00.t +$QEMU ./ARMARM00.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM01.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM01.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM01 +"PodWWPL RfeLP DpAddrdR Fre" + +{0:X1=x; 0:X3=y; 1:X1=y; 1:X4=x; 1:X3=-1;} + + P0 | P1 ; + MOV W0,#1 | LDR W0,[X1] ; + STR W0,[X1] | CMP W0,#1 ; + MOV W2,#1 | B.NE Exit1 ; + STLR W2,[X3] | EOR W2,W0,W0 ; + | LDR W3,[X4,W2,SXTW] ; + | Exit1: ; + +~exists (1:X0=1 /\ 1:X3=0) +Generated assembler +EOF +cat ARMARM01.t +$QEMU ./ARMARM01.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM02.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM02.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM02 + +{0:X1=x; 0:X3=y; 1:X1=y; 1:X4=x; 1:X3=-1; 2:X1=y; 2:X4=x; 2:X3=-1;} + + P0 | P1 | P2 ; + MOV W0,#1 | LDR W0,[X1] | LDR W0,[X1] ; + STR W0,[X1] | CMP W0,#1 | CMP W0,#1 ; + MOV W2,#1 | B.NE Exit1 | B.NE Exit2 ; + STLR W2,[X3] | EOR W2,W0,W0 | EOR W2,W0,W0 ; + | LDR W3,[X4,W2,SXTW] | LDR W3,[X4,W2,SXTW] ; + | Exit1: | Exit2: ; + +~exists (1:X0=1 /\ 1:X3=0 \/ 2:X0=1 /\ 2:X3=0) +Generated assembler +EOF +cat ARMARM02.t +$QEMU ./ARMARM02.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM03.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM03.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM03 +"PodWWPL RfeLP DpAddrdR Fre" + +{y=z; z=-1; 0:X1=x; 0:X3=y; 1:X3=y; 1:X9=-1;} + + P0 | P1 ; + MOV W0,#1 | LDR X0,[X3] ; + STR W0,[X1] | LDR W9,[X0] ; + STLR X1,[X3] | ; + +~exists (1:X0=x /\ 1:X9=0) +Generated assembler +EOF +cat ARMARM03.t +$QEMU ./ARMARM03.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM04+BIS.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM04+BIS.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM04+BIS +"RfeLA PodRWAP Rfe DpAddrdRPA FreAL" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 2:X4=x; 2:X3=-1;} + + P0 | P1 | P2 ; + MOV W0,#1 | LDAR W0,[X1] | LDR W0,[X1] ; + STLR W0,[X1] | CMP W0,#1 | CMP W0,#1 ; + | B.NE Exit1 | B.NE Exit2 ; + | MOV W2,#1 | EOR W2,W0,W0 ; + | STR W2,[X3] | ADD X5,X4,W2,SXTW ; + | Exit1: | LDR W3,[X5] ; + | | Exit2: ; + +exists (1:X0=1 /\ 2:X0=1 /\ 2:X3=0) +Generated assembler +EOF +cat ARMARM04+BIS.t +$QEMU ./ARMARM04+BIS.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM04.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM04.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM04 +"RfeLA PodRWAP Rfe DpAddrdRPA FreAL" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 2:X4=x; 2:X3=-1;} + + P0 | P1 | P2 ; + MOV W0,#1 | LDAR W0,[X1] | LDR W0,[X1] ; + STLR W0,[X1] | CMP W0,#1 | CMP W0,#1 ; + | B.NE Exit1 | B.NE Exit2 ; + | MOV W2,#1 | EOR W2,W0,W0 ; + | STR W2,[X3] | ADD X5,X4,W2,SXTW ; + | Exit1: | LDAR W3,[X5] ; + | | Exit2: ; + +~exists (1:X0=1 /\ 2:X0=1 /\ 2:X3=0) +Generated assembler +EOF +cat ARMARM04.t +$QEMU ./ARMARM04.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM04+TER.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM04+TER.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM04+TER +"RfeLA PodRWAP Rfe PodRRPA FreAL" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 2:X3=x;} + + P0 | P1 | P2 ; + MOV W0,#1 | LDAR W0,[X1] | LDR W0,[X1] ; + STLR W0,[X1] | MOV W2,#1 | LDAR W2,[X3] ; + | STR W2,[X3] | ; + +exists (1:X0=1 /\ 2:X0=1 /\ 2:X2=0) +Generated assembler +EOF +cat ARMARM04+TER.t +$QEMU ./ARMARM04+TER.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM05.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM05.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM05 +"Rfe PodRWPL RfeLP DpAddrdR Fre" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 2:X4=x; 2:X3=-1;} + + P0 | P1 | P2 ; + MOV W0,#1 | LDR W0,[X1] | LDR W0,[X1] ; + STR W0,[X1] | CMP W0,#1 | CMP W0,#1 ; + | B.NE Exit1 | B.NE Exit2 ; + | MOV W2,#1 | EOR W2,W0,W0 ; + | STLR W2,[X3] | LDR W3,[X4,W2,SXTW] ; + | Exit1: | Exit2: ; + +~exists (1:X0=1 /\ 2:X0=1 /\ 2:X3=0) +Generated assembler +EOF +cat ARMARM05.t +$QEMU ./ARMARM05.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM06+AP+AA.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM06+AP+AA.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM06+AP+AA +"RfeLA PodRRAP FrePL RfeLA PodRRAA FreAL" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 3:X1=y; 3:X3=x;} + + P0 | P1 | P2 | P3 ; + MOV W0,#1 | LDAR W0,[X1] | MOV W0,#1 | LDAR W0,[X1] ; + STLR W0,[X1] | LDR W2,[X3] | STLR W0,[X1] | LDAR W2,[X3] ; + +exists (1:X0=1 /\ 1:X2=0 /\ 3:X0=1 /\ 3:X2=0) +Generated assembler +EOF +cat ARMARM06+AP+AA.t +$QEMU ./ARMARM06+AP+AA.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM06+AP+AP.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM06+AP+AP.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM06+AP+AP +"RfeLA PodRRAP FrePL RfeLA PodRRAP FrePL" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 3:X1=y; 3:X3=x;} + + P0 | P1 | P2 | P3 ; + MOV W0,#1 | LDAR W0,[X1] | MOV W0,#1 | LDAR W0,[X1] ; + STLR W0,[X1] | LDR W2,[X3] | STLR W0,[X1] | LDR W2,[X3] ; + +exists (1:X0=1 /\ 1:X2=0 /\ 3:X0=1 /\ 3:X2=0) +Generated assembler +EOF +cat ARMARM06+AP+AP.t +$QEMU ./ARMARM06+AP+AP.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM06.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM06.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 ARMARM06 +"RfeLA PodRRAA FreAL RfeLA PodRRAA FreAL" + +{0:X1=x; 1:X1=x; 1:X3=y; 2:X1=y; 3:X1=y; 3:X3=x;} + + P0 | P1 | P2 | P3 ; + MOV W0,#1 | LDAR W0,[X1] | MOV W0,#1 | LDAR W0,[X1] ; + STLR W0,[X1] | LDAR W2,[X3] | STLR W0,[X1] | LDAR W2,[X3] ; + +~exists (1:X0=1 /\ 1:X2=0 /\ 3:X0=1 /\ 3:X2=0) +Generated assembler +EOF +cat ARMARM06.t +$QEMU ./ARMARM06.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +if [ ! -f ARMARM07+SAL.no ]; then +cat <<'EOF' +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Results for aarch64.tests/HAND/ARMARM07+SAL.litmus % +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +AArch64 SAL + +{0:X1=x; 0:X2=y; 1:X1=x; 1:X2=y;} + + P0 | P1 ; + MOV W0,#1 | MOV W0,#1 ; + STR W0,[X1] | STR W0,[X2] ; + DMB SY | DMB SY ; + LDR X3,[X2] | LDR X3,[X1] ; + +~exists (0:X3=0 /\ 1:X3=0) +Generated assembler +EOF +cat ARMARM07+SAL.t +$QEMU ./ARMARM07+SAL.exe -q $LITMUSOPTS +ret=$? +if [ $ret -eq 1 ]; then + echo "FAILED"; + exit 1; +fi +fi +sleep $SLEEP + +cat <<'EOF' +Revision exported, version 7.22 +Command line: ./litmus -exit true -o run.armarm -mach overdrive01.cfg aarch64.tests/HAND/ARMARM00.litmus aarch64.tests/HAND/ARMARM01.litmus aarch64.tests/HAND/ARMARM02.litmus aarch64.tests/HAND/ARMARM03.litmus aarch64.tests/HAND/ARMARM04+BIS.litmus aarch64.tests/HAND/ARMARM04.litmus aarch64.tests/HAND/ARMARM04+TER.litmus aarch64.tests/HAND/ARMARM05.litmus aarch64.tests/HAND/ARMARM06+AP+AA.litmus aarch64.tests/HAND/ARMARM06+AP+AP.litmus aarch64.tests/HAND/ARMARM06.litmus aarch64.tests/HAND/ARMARM07+SAL.litmus +Parameters +#define SIZE_OF_TEST 100000 +#define NUMBER_OF_RUN 10 +#define AVAIL 0 +#define STRIDE 1 +#define MAX_LOOP 0 +/* gcc options: -D_GNU_SOURCE -DFORCE_AFFINITY -Wall -std=gnu99 -O2 -pthread */ +/* barrier: user */ +/* launch: changing */ +/* affinity: incr0 */ +/* alloc: dynamic */ +/* memory: direct */ +/* stride: 1 */ +/* safer: write */ +/* preload: random */ +/* speedcheck: no */ +/* proc used: 0 */ +EOF +head -1 comp.sh +echo "LITMUSOPTS=$LITMUSOPTS" +date diff --git a/tests/tcg/aarch64/litmus/show.awk b/tests/tcg/aarch64/litmus/show.awk new file mode 100644 index 0000000..c8ecf20 --- /dev/null +++ b/tests/tcg/aarch64/litmus/show.awk @@ -0,0 +1,2 @@ +/START _litmus_P/ { print $0 } +/_litmus_P[0-9]+_[0-9]+/ { getline; print $0 ; } diff --git a/tests/tcg/aarch64/litmus/utils.c b/tests/tcg/aarch64/litmus/utils.c new file mode 100644 index 0000000..cc989b0 --- /dev/null +++ b/tests/tcg/aarch64/litmus/utils.c @@ -0,0 +1,1148 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include +#include +#include "utils.h" + +/********/ +/* Misc */ +/********/ + +FILE *errlog ; + +static void checkerrlog(void) { + if (!errlog) errlog = stderr ; +} + +void seterrlog(FILE *chan) { + errlog = chan ; +} + +int log_error(const char *fmt, ...) { + int result; + va_list args; + va_start(args, fmt); + checkerrlog() ; + result = vfprintf(errlog, fmt, args); + fflush(errlog); + va_end(args); + return result; +} + +void fatal(char *msg) { + log_error("Failure: %s\n", msg) ; + fclose(errlog); + fprintf(stdout,"Failure: %s\n", msg) ; + exit(1) ; +} + +void errexit(char *msg,int err) { + log_error("%s: %s\n",msg,strerror(err)) ; + fclose(errlog); + exit(2) ; +} + +void *malloc_check(size_t sz) { + if (sz == 0) return NULL ; + void *p = malloc(sz) ; + if (!p) { + if (!errno) errno = ENOMEM ; + errexit("malloc",errno) ; + } + return p ; +} + +int max(int n, int m) { return n < m ? m : n ; } + +void pp_ints(FILE *fp,int *p,int n) { + if (n > 0) { + fprintf(fp,"%i",p[0]) ; + for (int k = 1 ; k < n ; k++) { + fprintf(fp,",%i",p[k]) ; + } + } +} + + +void *do_align(void *p,size_t sz) { + uintptr_t x = (uintptr_t)p ; + x += sz-1 ; + x /= sz ; + x *= sz ; + return (void *)x ; +} + +void *do_noalign(void *p,size_t sz) { + void *q = do_align(p,sz) ; + void *r = q - sz/2 ; + if (r < p) r = q + sz/2 ; + return r ; +} + +void cat_file(char *path, char *msg, FILE *out) { + FILE *fp = fopen(path,"r") ; + if (fp == NULL) return ; + fprintf(out,"%s\n",msg) ; + int c,nl=1 ; + while ((c = fgetc(fp)) != EOF) { + fputc(c,out) ; + nl = c == '\n' ; + } + fclose(fp) ; + if (!nl) fputc('\n',out) ; +} + +/************/ +/* CPU sets */ +/************/ + +cpus_t *cpus_create(int sz) { + cpus_t *r = malloc_check(sizeof(*r)) ; + r->sz = sz ; + r->cpu = malloc_check(sizeof(r->cpu[0])*sz) ; + return r ; +} + +cpus_t *cpus_create_init(int sz, int t[]) { + cpus_t *r = cpus_create(sz) ; + for (int k = 0 ; k < sz ; k++) r->cpu[k] = t[k] ; + return r ; +} + +void cpus_free(cpus_t *p) { + free(p->cpu) ; + free(p) ; +} + +void cpus_dump(FILE *fp, cpus_t *p) { + pp_ints(fp,p->cpu,p->sz) ; +} + +void cpus_dump_test(FILE *fp, int *p, int sz, cpus_t *cm,int nprocs) { + for (int k = 0 ; k < sz ; k += nprocs) { + fprintf(fp,"[") ; + pp_ints(fp,&p[k],nprocs) ; + fprintf(fp,"] {") ; + if (nprocs > 0) { + fprintf(fp,"%i",cm->cpu[p[k]]) ; + for (int i = 1 ; i < nprocs ; i++) { + fprintf(fp,",%i",cm->cpu[p[k+i]]) ; + } + } + fprintf(fp,"}\n") ; + } +} + +/*************/ +/* Int array */ +/*************/ + + +void ints_dump(FILE *fp, ints_t *p) { + if (p->sz > 0) { + fprintf(fp,"%i:%i",0,p->t[0]) ; + for (int k = 1 ; k < p->sz ; k++) { + fprintf(fp,",%i:%i",k,p->t[k]) ; + } + } +} + +/***********************/ +/* Prefetch directives */ +/***********************/ +void prefetch_dump(FILE *fp, prfdirs_t *p) { + prfproc_t *q = p->t ; + int some = 0 ; + for (int _p = 0 ; _p < p->nthreads ; _p++) { + int nvars = q[_p].nvars ; + prfone_t *r = q[_p].t ; + for (int _v = 0 ; _v < nvars ; _v++) { + prfdir_t dir = r[_v].dir ; + if (dir != none) { + char c = 'I' ; + if (dir == flush) c = 'F' ; + else if (dir == touch) c = 'T' ; + else if (dir == touch_store) c = 'W' ; + if (some) { + fprintf(fp,",") ; + } else { + some = 1 ; + } + fprintf(fp,"%i:%s=%c",_p,r[_v].name,c) ; + } + } + } +} + +static void set_prefetch(prfdirs_t *p, prfdir_t d) { + prfproc_t *q = p->t ; + for (int _p = 0 ; _p < p->nthreads ; _p++) { + int nvars = q[_p].nvars ; + prfone_t *r = q[_p].t ; + for (int _v = 0 ; _v < nvars ; _v++) { + r[_v].dir = d ; + } + } +} + +/* ??? */ + +int gcd(int a, int b) { + for ( ; ; ) { + if (a == 0) return b ; + int tmp = a ; + a = b % a ; + b = tmp ; + } +} + +/* SMT description */ + + +cpus_t *coremap_seq(int navail, int nways) { + cpus_t *r = cpus_create(navail) ; + int ncores = navail / nways ; + int i = 0 ; + for (int c = 0 ; c < ncores ; c++) { + for (int k = 0 ; k < nways ; k++) { + r->cpu[i++] = c ; + } + } + return r ; +} + +cpus_t *coremap_end(int navail, int nways) { + cpus_t *r = cpus_create(navail) ; + int ncores = navail / nways ; + int i = 0 ; + for (int k = 0 ; k < nways ; k++) { + for (int c = 0 ; c < ncores ; c++) { + r->cpu[i++] = c ; + } + } + return r ; +} + +typedef struct { + int ncores ; + cpus_t **core ; +} mapcore_t ; + + +static void mapcore_free(mapcore_t *p) { + for (int c = 0 ; c < p->ncores ; c++) cpus_free(p->core[c]) ; + free(p->core) ; + free(p) ; +} + +#if 0 +static mapcore_t *inverse_coremap(cpus_t *p, int nways) { + mapcore_t *r = malloc_check(sizeof(*r)) ; + r->ncores = p->sz / nways ; + r->core = malloc_check(r->ncores * sizeof(r->core[0])) ; + for (int k = 0 ; k < r->ncores ; k++) { + r->core[k] = cpus_create(nways) ; + r->core[k]->sz = 0 ; + } + for (int k = 0 ; k < p->sz ; k++) { + int c = p->cpu[k] ; + cpus_t *q = r->core[c] ; + q->cpu[q->sz++] = k ; + } + return r ; +} +#endif + +static int get_ncores(cpus_t *cm) { + int r = 0; + for (int k = 0 ; k < cm->sz ; k++) { + if (cm->cpu[k] > r) r = cm->cpu[k] ; + } + return r+1 ; +} + +cpus_t *get_core_procs(cpus_t *cm, cpus_t *p,int c) { + int sz = 0 ; + cpus_t *r ; + for (int k = 0 ; k < p->sz ; k++) { + if (cm->cpu[p->cpu[k]] == c) sz++ ; + } + r = cpus_create(sz) ; + int i = 0 ; + for (int k = 0 ; k < p->sz ; k++) { + int proc = p->cpu[k] ; + if (cm->cpu[proc] == c) r->cpu[i++] = proc ; + } + return r ; +} + +static mapcore_t *inverse_procs(cpus_t *cm, cpus_t *p) { + int ncores = get_ncores(cm) ; + mapcore_t *r = malloc_check(sizeof(*r)) ; + r->ncores = ncores ; + r->core = malloc_check(sizeof(r->core[0])*ncores) ; + for (int c = 0 ; c < ncores ; c++) { + r->core[c] = get_core_procs(cm,p,c) ; + } + return r ; +} + +static int get_node_sz(int *p) { + int r = 0 ; + while (*p++ >= 0) r++ ; + return r ; +} + +static int get_n(int **p) { + int r = 0 ; + while (*p) { + r += get_node_sz(*p) ; + p++ ; + } + return r ; +} + +static int ok_one_color(int *cm,int *d,int *a,int n, int p, int c) { + for (int k = 0 ; k < n ; k++) { + int op = a[k] ; + if (op >= 0) { + if (d[n*p+k]) { + int oc = cm[op] ; + if (oc == c) { + return 0 ; + } + } + } + } + return 1 ; +} + +static int ok_color(int *cm,int *d,int *a,int n, int *q, int c) { + for ( ; *q >= 0 ; q++) { + if (!ok_one_color(cm,d,a,n,*q,c)) return 0 ; + } + return 1 ; +} + +static int find_color_diff +(int prev,st_t *st,int *cm,mapcore_t *mc,int *d, int *a,int n, int *q) { + int sz = get_node_sz(q) ; + int k0 = prev >= 0 && rand_bit(st) ? prev : rand_k(st,mc->ncores) ; + int k = k0 ; + do { + cpus_t *p = mc->core[k] ; + if (p->sz >= sz && ok_color(cm,d,a,n,q,k)) return k ; + k++ ; k %= mc->ncores ; + } while (k != k0) ; + return -1 ; +} + + +static int find_one_proc +(int prev,st_t *st,int *cm,mapcore_t *mc,int *d,int *a,int n,int p) { + int found = -1 ; + int k0 = prev >= 0 && rand_bit(st) ? prev : rand_k(st,mc->ncores) ; + int k = k0 ; + do { + cpus_t *pk = mc->core[k] ; + if (pk->sz > 0) { + if (found < 0) found = k ; + if (ok_one_color(cm,d,a,n,p,k)) return k ; + } + k++ ; k %= mc->ncores ; + } while (k != k0) ; + if (found < 0) fatal("Cannot allocate threads") ; + return found ; +} + +void custom_affinity (st_t *st,cpus_t *cm,int **color,int *diff,cpus_t *aff_cpus,int n_exe, int *r) { + mapcore_t *mc = inverse_procs(cm,aff_cpus) ; + int n = get_n(color) ; + /* Diff relation as matrix */ + int d[n*n] ; + { + int *q = diff ; + for (int k = 0 ; k < n*n ; k++) d[k] = 0 ; + while (*q >= 0) { + int x = *q++, y = *q++ ; + d[n*x+y] = d[n*y+x] = 1 ; + } + } + for (int k = 0 ; k < n_exe ; k++) { + int *a = &r[k*n] ; + int prev_core = -1 ; + for (int i = 0 ; i < n ; i++) a[i] = -1 ; + for (int **q = color ; *q ; q++) { + int c = find_color_diff(prev_core,st,aff_cpus->cpu,mc,d,a,n,*q) ; + if (c >= 0) { + cpus_t *p = mc->core[c] ; + for (int *qq = *q ; *qq >= 0 ; qq++) { + p->sz-- ; + a[*qq] = p->cpu[p->sz] ; + } + prev_core = c ; + } else { + for (int *qq = *q ; *qq >= 0 ; qq++) { + int c = find_one_proc(prev_core,st,aff_cpus->cpu,mc,d,a,n,*qq) ; + cpus_t *p = mc->core[c] ; + p->sz-- ; + a[*qq] = p->cpu[p->sz] ; + prev_core = c ; + } + } + } + } + mapcore_free(mc) ; +} + +/****************/ +/* Command line */ +/****************/ + +/* usage */ + +static void usage(char *prog, cmd_t *d) { + log_error("usage: %s (options)*\n",prog) ; + log_error(" -v be verbose\n") ; + log_error(" -q be quiet\n") ; + log_error(" -a run maximal number of tests for n available processors (default %i)\n",d->avail) ; + log_error(" -n run n tests concurrently\n") ; + log_error(" -r perform n runs (default %i)\n",d->max_run) ; + log_error(" -fr multiply run number per f\n") ; + log_error(" -s outcomes per run (default %i)\n",d->size_of_test) ; + if (d->stride > 0) { + log_error(" -st stride (default %i)\n",d->stride) ; + } + log_error(" -fs multiply outcomes per f\n") ; + log_error(" -f multiply outcomes per f, divide run number by f\n") ; + if (d->aff_mode != aff_none) { + log_error(" -i increment for allocating logical processors, -i 0 disables affinity mode") ; + if (d->aff_mode == aff_incr) { + log_error(" (default %i)\n",d->aff_incr) ; + } else { + log_error("\n") ; + } + log_error(" -p specify logical processors (default '") ; + cpus_dump(errlog,d->aff_cpus) ; + log_error("')\n") ; + log_error(" +ra randomise affinity%s\n",d->aff_mode == aff_random ? " (default)" : "") ; + if (d->aff_custom_enabled) { + log_error(" +ca enable custom affinity%s\n",d->aff_mode == aff_custom ? " (default)" : "") ; + } else { + log_error(" +ca alias for +ra\n") ; + } + if (d->aff_scan_enabled) { + log_error(" +sa enable scanning affinity%s\n",d->aff_mode == aff_scan ? " (default)" : "") ; + log_error(" +ta set topology affinity\n") ; + } else { + log_error(" +sa alias for +ra\n") ; + } + } + if (d->shuffle >= 0) { + log_error(" +rm randomise memory accesses%s\n",d->shuffle ? " (default)" : "") ; + log_error(" -rm do not randomise memory accesses%s\n",!d->shuffle ? " (default)" : "") ; + } + if (d->speedcheck >= 0) { + log_error(" +sc stop as soon as possible%s\n",d->speedcheck ? " (default)" : "") ; + log_error(" -sc run test completly%s\n",!d->speedcheck ? " (default)" : "") ; + } + if (!d->fix) { + log_error(" +fix fix thread launch order\n") ; + } + if (d->delta_tb) { + log_error(" -tb set timebase delays, default '") ; + ints_dump(errlog,d->delta_tb) ; + log_error("'\n") ; + log_error(" List syntax is comma separated proc:delay\n") ; + log_error(" -ta set all timebase delays\n") ; + } + if (d->verbose_barrier >= 0) { + log_error(" +vb show iteration timings%s\n",d->verbose_barrier ? " (default)" : "") ; + log_error(" -vb do not show iteration timings%s\n",!d->verbose_barrier ? " (default)" : "") ; + } + if (d->prefetch) { + log_error(" -pra (I|F|T|W) set all prefetch\n") ; + log_error(" -prf set prefetch, default '") ; + prefetch_dump(errlog,d->prefetch) ; + log_error("'\n") ; + log_error(" List syntax is comma separated proc:name=(I|F|T|W)\n") ; + } + if (d->static_prefetch >= 0) { + log_error(" -prs prefetch probability is 1/n, -prs 0 disables feature, default %i\n",d->static_prefetch) ; + } + if (d->max_loop > 0) { + log_error(" -l measure time by running assembly in a loop of size (default %i)\n",d->max_loop) ; + } + if (d->prelude > 0) { + log_error(" -vp no verbose prelude\n") ; + } + if (d->sync_n > 0) { + log_error(" -k undocumented (default %i)\n",d->sync_n) ; + } + exit(2) ; +} + +static long my_add (long x, long y) { + long r = x+y ; + if (r < x || r < y) { errno = ERANGE ; fatal("overflow") ; } + return r ; +} + +static long my_pow10(int p,long x) { + long r = x ; + for ( ; p > 0 ; p--) { + long y2 = my_add(r,r) ; + long y4 = my_add(y2,y2) ; + long y8 = my_add(y4,y4) ; + r = my_add(y8,y2) ; + } + if (r >= INT_MAX || r <= 0) { errno = ERANGE ; fatal("overflow") ; } + return r ; +} + +static int do_argint(char *p, char **q) { + long r = strtol(p,q,10) ; + if (errno == ERANGE) { fatal("overflow") ; } + if (**q == 'k' || **q == 'K') { r = my_pow10(3,r) ; *q += 1; } + else if (**q == 'm' || **q == 'M') { r = my_pow10(6,r) ; *q +=1 ; } + return (int)r ; +} + +static int argint(char *prog,char *p,cmd_t *d) { + char *q ; + long r = do_argint(p,&q) ; + if (*p == '\0' || *q != '\0') { + usage(prog,d) ; + } + return (int)r ; +} + +static cpus_t *argcpus(char *prog,char *p0,cmd_t *d) { + int sz = 0 ; + char *p ; + + p = p0 ; + for ( ; ; ) { + char *q ; + int x = (int)strtol(p,&q,10) ; + if (x < 0 || *p == '\0' || (*q != '\0' && *q != ',')) usage(prog,d) ; + sz++ ; + if (*q == '\0') break ; + p = q+1 ; + } + cpus_t *r = cpus_create(sz) ; + p = p0 ; + for (int k = 0 ; k < sz ; k++) { + char *q ; + r->cpu[k] = (int)strtol(p,&q,10) ; + p = q+1 ; + } + return r ; +} + +static void argints(char *prog,cmd_t *d, char *p,ints_t *r) { + while (*p) { + char *q ; + int idx = (int)strtol(p,&q,10) ; + if (idx < 0 || idx >= r->sz || *p == '\0' || *q != ':') usage(prog,d) ; + p = q+1 ; + int v = do_argint(p,&q) ; + if (*p == '\0' || (*q != '\0' && *q != ',')) usage(prog,d) ; + r->t[idx] = v ; + if (*q == '\0') { + p = q ; + } else { + p = q+1 ; + } + } +} + +static prfone_t *get_name_slot(prfproc_t *p,char *name) { + int nvars = p->nvars ; + prfone_t *q = p->t ; + for (int _v = 0 ; _v < nvars ; _v++) { + if (strcmp(name,q[_v].name) == 0) return &q[_v] ; + } + return NULL ; /* Name not found */ +} + + +static void argoneprefetch(char *prog,cmd_t *d, char *p, prfdirs_t *r) { + prfdir_t dir = none ; + switch (*p) { + case 'F': + dir = flush ; + break ; + case 'T': + dir = touch ; + break ; + case 'W': + dir = touch_store ; + break ; + } + set_prefetch(r,dir) ; +} + +int parse_prefetch(char *p, prfdirs_t *r) { + if (!*p) return 1 ; + for ( ;; ) { + char *q ; + int proc = (int)strtol(p,&q,10) ; + if (proc < 0 || proc >= r->nthreads || *p == '\0' || *q != ':') + return 0 ; + p = q+1 ; + char *p0 = p ; + while (*p != '=') { + if (*p == '\0') return 0 ; + p++ ; + } + *p = '\0' ; + prfone_t *loc_slot = get_name_slot(&r->t[proc],p0) ; + if (loc_slot == NULL) { + log_error("Proc %i does not access variable %s\n",proc,p0) ; + *p = '=' ; + return 0 ; + } + *p = '=' ; + char c = *++p; + prfdir_t dir = none ; + switch (c) { + case 'F': + dir = flush ; + break ; + case 'T': + dir = touch ; + break ; + case 'W': + dir = touch_store ; + break ; + } + loc_slot->dir = dir ; + c = *++p ; + if (c == '\0') return 1 ; + else if (c == ',') p++ ; + else return 0 ; + } +} + +static void argprefetch(char *prog,cmd_t *d, char *p, prfdirs_t *r) { + if (!parse_prefetch(p,r)) usage(prog,d) ; +} + +static double argdouble(char *prog,char *p,cmd_t *d) { + char *q ; + double r = strtod(p,&q) ; + if (*p == '\0' || *q != '\0') { + usage(prog,d) ; + } + return r ; +} + +void parse_cmd(int argc, char **argv, cmd_t *d, cmd_t *p) { + char *prog = argv[0] ; + + /* Options */ + for ( ; ; ) { + --argc ; ++argv ; + if (!*argv) break ; + char fst = **argv ; + if (fst != '-' && fst != '+') break ; + if (strcmp(*argv,"-q") == 0) p->verbose=0 ; + else if (strcmp(*argv,"-v") == 0) p->verbose++ ; + else if (strcmp(*argv,"-r") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->max_run = argint(prog,argv[0],d) ; + } else if (strcmp(*argv,"-fr") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->max_run *= argdouble(prog,argv[0],d) ; + } else if (strcmp(*argv,"-s") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->size_of_test = argint(prog,argv[0],d) ; + } else if (d->stride > 0 && strcmp(*argv,"-st") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->stride = argint(prog,argv[0],d) ; + if (p->stride <= 0) p->stride = 1 ; + } else if (strcmp(*argv,"-fs") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->size_of_test *= argdouble(prog,argv[0],d) ; + } else if (strcmp(*argv,"-f") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + double f = argdouble(prog,argv[0],d) ; + p->size_of_test *= f ; + p->max_run /= f ; + } else if (strcmp(*argv,"-n") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->n_exe = argint(prog,argv[0],d) ; + if (p->n_exe < 1) p->n_exe = 1 ; + } else if (strcmp(*argv,"-a") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + int a = argint(prog,argv[0],d) ; + p->avail = a ; + } else if (d->sync_n > 0 && strcmp(*argv,"-k") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + int a = argint(prog,argv[0],d) ; + p->sync_n = a < 0 ? 0 : a ; + } else if (d->aff_mode != aff_none && strcmp(*argv,"-i") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + int i = argint(prog,argv[0],d) ; + p->aff_mode = aff_incr ; + p->aff_incr = i < 0 ? 0 : i ; + } else if (d->aff_mode != aff_none && strcmp(*argv,"-p") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + cpus_t *cpus = argcpus(prog,argv[0],d) ; + p->aff_cpus = cpus ; + } else if (d->aff_mode != aff_none && strcmp(*argv,"+ra") == 0) { + p->aff_mode = aff_random ; + } else if (d->aff_custom_enabled && strcmp(*argv,"+ca") == 0) { + p->aff_mode = aff_custom ; + } else if (d->aff_mode != aff_none && strcmp(*argv,"+ca") == 0) { + p->aff_mode = aff_random ; + } else if (d->aff_scan_enabled && strcmp(*argv,"+sa") == 0) { + p->aff_mode = aff_scan ; + } else if (d->aff_mode != aff_none && strcmp(*argv,"+sa") == 0) { + p->aff_mode = aff_random ; + } else if (d->aff_scan_enabled && strcmp(*argv,"+ta") == 0) { + p->aff_mode = aff_topo ; + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + p->aff_topo = argv[0] ; + } else if (d->aff_mode != aff_none && strcmp(*argv,"+sa") == 0) { + p->aff_mode = aff_random ; + } else if (d->shuffle >= 0 && strcmp(*argv,"+rm") == 0) { + p->shuffle = 1 ; + } else if (d->shuffle >= 0 && strcmp(*argv,"-rm") == 0) { + p->shuffle = 0 ; + } else if (d->speedcheck >= 0 && strcmp(*argv,"+sc") == 0) { + p->speedcheck = 1 ; + } else if (d->speedcheck >= 0 && strcmp(*argv,"-sc") == 0) { + p->speedcheck = 0 ; + } else if (!d->fix && strcmp(*argv,"+fix") == 0) { + p->fix = 1 ; + } else if (d->verbose_barrier >= 0 && strcmp(*argv,"+vb") == 0) { + p->verbose_barrier++ ; + } else if (d->verbose_barrier >= 0 && strcmp(*argv,"-vb") == 0) { + p->verbose_barrier = 0 ; + } else if (d->prelude > 0 && strcmp(*argv,"-vp") == 0) { + p->prelude = 0 ; + } else if (d->delta_tb && strcmp(*argv,"-tb") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + argints(prog,d,argv[0],p->delta_tb) ; + } else if (d->delta_tb && strcmp(*argv,"-ta") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + int da = argint(prog,argv[0],d) ; + for (int k = 0 ; k < p->delta_tb->sz ; k++) p->delta_tb->t[k] = da ; + } else if (d->prefetch && strcmp(*argv,"-prf") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + argprefetch(prog,d,argv[0],p->prefetch) ; + } else if (d->prefetch && strcmp(*argv,"-pra") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + argoneprefetch(prog,d,argv[0],p->prefetch) ; + } else if (d->static_prefetch >= 0 && strcmp(*argv,"-prs") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + int prs = argint(prog,argv[0],d) ; + p->static_prefetch = prs >= 0 ? prs : 0 ; + } else if (d->max_loop > 0 && strcmp(*argv,"-l") == 0) { + --argc ; ++argv ; + if (!*argv) usage(prog,d) ; + int i = argint(prog,argv[0],d) ; + p->max_loop = i < 1 ? 1 : i ; + } else usage(prog,d) ; + } + + /* Argument */ + if (argc == 0) return ; + usage(prog,d) ; +} + +/*************************/ +/* Concurrency utilities */ +/*************************/ + +/* phread based mutex */ + +pm_t *pm_create(void) { + pm_t *p = malloc_check(sizeof(*p)) ; + int ret = pthread_mutex_init(p,NULL) ; + if (ret) { errexit("mutex_init",ret) ; } + return p ; +} + +void pm_free(pm_t *p) { + free(p) ; +} + +void pm_lock(pm_t *m) { + int ret = pthread_mutex_lock(m) ; + if (ret) { errexit("mutex_lock",ret) ; } +} + +void pm_unlock(pm_t *m) { + int ret = pthread_mutex_unlock(m) ; + if (ret) { errexit("mutex_unlock",ret) ; } +} + +/* phread condition */ + +pc_t *pc_create(void) { + pc_t *p = malloc_check(sizeof(*p)) ; + p->c_mutex = pm_create() ; + p->c_cond = malloc_check(sizeof(*(p->c_cond))) ; + int e = pthread_cond_init(p->c_cond,NULL) ; + if (e) { errexit("cond_init",e); } + return p ; +} + +void pc_free(pc_t *p) { + pm_free(p->c_mutex) ; + free(p->c_cond) ; + free(p) ; +} + +static void pc_lock(pc_t *p) { + pm_lock(p->c_mutex) ; +} + +static void pc_unlock(pc_t *p) { + pm_unlock(p->c_mutex) ; +} + +void pc_wait(pc_t *p) { + int e = pthread_cond_wait(p->c_cond, p->c_mutex) ; + if (e) { errexit("cond_wait",e) ; } +} + +void pc_broadcast (pc_t *p) { + int e = pthread_cond_broadcast(p->c_cond) ; + if (e) { errexit("cond_broadcast",e) ; } +} + +static void pc_signal(pc_t *p) { + int e = pthread_cond_signal(p->c_cond); + if (e) errexit("cond_signal",e) ; +} + + +/* pthread based barrier, usable for nproc threads */ + + +pb_t *pb_create(int nprocs) { + pb_t *p = malloc_check(sizeof(*p)) ; + p->cond = pc_create() ; + p->count = p->nprocs = nprocs ; + p->turn = 0 ; + return p ; +} + +void pb_free(pb_t *p) { + pc_free(p->cond) ; + free(p) ; +} + +/* The following code should protect us against spurious wake ups */ +void pb_wait(pb_t *p) { + pc_lock(p->cond) ; + int t = p->turn ; + --p->count ; + if (p->count == 0) { + p->count = p->nprocs ; + p->turn = !t ; + pc_broadcast(p->cond) ; + } else { + do { + pc_wait(p->cond) ; + } while (p->turn == t) ; + } + pc_unlock(p->cond) ; +} + + +/* pthread based or flag */ + +po_t *po_create(int nprocs) { + po_t *p = malloc_check(sizeof(*p)) ; + p->cond = pc_create() ; + p->nprocs = p->count = nprocs ; + p->val = 0 ; + p->turn = 0 ; + return p ; +} + +void po_free(po_t *p) { + pc_free(p->cond) ; + free(p) ; +} + +void po_reinit(po_t *p) { + pc_lock(p->cond) ; + int t = p->turn ; + --p->count ; + if (p->count == 0) { + p->count = p->nprocs ; + p->val = 0 ; + p->turn = !t ; + pc_broadcast(p->cond) ; + } else { + do { + pc_wait(p->cond) ; + } while (p->turn == t) ; + } + pc_unlock(p->cond) ; +} + +int po_wait(po_t *p, int v) { + pc_lock(p->cond) ; + int t = p->turn ; + --p->count ; + p->val = p->val || v ; + if (p->count == 0) { + p->count = p->nprocs ; + p->turn = !t ; + pc_broadcast(p->cond) ; + } else { + do { + pc_wait(p->cond) ; + } while (p->turn == t) ; + } + int r = p->val ; + pc_unlock(p->cond) ; + return r ; +} + + +/* One place buffer */ + +op_t *op_create(void) { + op_t *p = malloc_check(sizeof(*p)) ; + p->cond = pc_create() ; + p->val = NULL ; + p->some = 0 ; + return p; +} + +void op_free(op_t *p) { + pc_free(p->cond) ; + free(p) ; +} + +void op_set(op_t *p, void *v) { + pc_lock(p->cond) ; + if (p->some) { fatal("op_set") ; } + p->val = v ; + p->some = 1 ; + pc_signal(p->cond) ; + pc_unlock(p->cond) ; +} + +void *op_get(op_t *p) { + void *v = NULL ; + pc_lock(p->cond) ; + while (!p->some) { + pc_wait(p->cond) ; + } + v = (void *) p->val ; + p->val = NULL ; + p->some = 0 ; + pc_unlock(p->cond) ; + return v ; +} + +/* Thread launch and join */ + +void launch(pthread_t *th, f_t *f, void *a) { + int e = pthread_create(th,NULL,f,a); + if (e) errexit("phread_create",e); +} + +void *join(pthread_t *th) { + void *r ; + int e = pthread_join(*th,&r) ; + if (e) errexit("pthread_join",e); + return r ; +} + +/* Detached */ + +typedef struct { + f_t *f; + void *a ; + op_t *op; +} detarg_t ; + +static void *zyva_det(void *_b) { + detarg_t *b = (detarg_t *)_b; + f_t *f = b->f ; + void *a = b->a ; + op_t *op = b->op ; + free(b) ; + int e = pthread_detach(pthread_self()); + if (e) errexit("pthread_detach",e) ; + void *r = f(a) ; + op_set(op,r) ; + return NULL ; +} + +op_t *launch_detached(f_t *f,void *a) { + op_t *op = op_create() ; + detarg_t *b = malloc_check(sizeof(*b)) ; + b->f = f ; b->a = a; b->op = op ; + pthread_t th ; + launch(&th,zyva_det,b) ; + return op ; +} + +void *join_detached(op_t *op) { + void *r = op_get(op) ; + op_free(op) ; + return r ; +} + +/* Thread cache */ + +void *start_thread(void *_a) { + sarg_t *_b = (sarg_t *)_a ; + for (int _k = _b->max_run ; _k > 0 ; _k--) { + void *_c = op_get(_b->op_arg) ; + f_t *f = (f_t *)_c ; + if (f == NULL) break ; + void *ret = f(_b->arg) ; + op_set(_b->op_ret,ret) ; + } + return NULL ; +} + +/*****************/ +/* Random things */ +/*****************/ + +void perm_prefix_ints(unsigned *st,int *_t, int m, int n) { + int k; + for (k = 0 ; k < m ; k++) { + int j = k+rand_k(st,n-k); + int x = _t[k]; _t[k] = _t[j]; _t[j] = x; + } +} + +void perm_ints(unsigned *st,int *_t, int n) { + perm_prefix_ints(st, _t,n-1,n) ; +} + +void perm_funs(unsigned *st,f_t *fun[], int n) { + int k; + for (k = 0 ; k < n-1 ; k++) { + int j = k+rand_k(st,n-k); + f_t *t = fun[j]; + fun[j] = fun[k]; fun[k] = t; + } +} + +void perm_ops(unsigned *st,op_t *op[], int n) { + int k; + for (k = 0 ; k < n-1 ; k++) { + int j = k+rand_k(st,n-k); + op_t *t = op[j]; + op[j] = op[k]; op[k] = t; + } +} + +void perm_threads(unsigned *st,pthread_t thread[], int n) { + int k; + for (k = 0 ; k < n-1 ; k++) { + int j = k+rand_k(st,n-k); + pthread_t t = thread[j]; + thread[j] = thread[k]; thread[k] = t; + } +} + +static int int_cmp(const void *_p, const void *_q) { + int x = *((int *)_p) ; + int y = *((int *)_q) ; + if (x < y) return -1 ; + else if (x > y) return 1 ; + else return 0 ; +} + +int check_shuffle(int **t, int *min, int sz) { + int *idx = malloc_check(sizeof(*idx)*sz) ; + for (int k=0 ; k < sz ; k++) { + idx[k] = (int)(t[k] - min) ; + // fprintf(stderr," %i",idx[k]) ; + } + // fprintf(stderr,"\n") ; + qsort(&idx[0],sz, sizeof(idx[0]), int_cmp) ; + for (int k=0 ; k < sz ; k++) { + if (idx[k] != k) { + free(idx) ; + return 0 ; + } + } + free(idx) ; + return 1 ; +} + +/****************/ +/* Time counter */ +/****************/ + +#include +#include + +tsc_t timeofday(void) { + struct timeval tv ; + if (gettimeofday(&tv,NULL)) errexit("gettimeoday",errno) ; + return tv.tv_sec * ((tsc_t)1000000) + tv.tv_usec ; +} + +double tsc_ratio(tsc_t t1, tsc_t t2) { + return ((double) t1) / ((double)t2) ; +} + + +double tsc_millions(tsc_t t) { + return t / 1000000.0 ; +} + +/*******************/ +/* String handling */ +/*******************/ + +int find_string(char *t[], int sz, char *s) { + for (int k = 0 ; k < sz ; k++) { + if (strcmp(t[k],s) == 0) return k ; + } + return -1 ; +} diff --git a/tests/tcg/aarch64/litmus/utils.h b/tests/tcg/aarch64/litmus/utils.h new file mode 100644 index 0000000..99e756e --- /dev/null +++ b/tests/tcg/aarch64/litmus/utils.h @@ -0,0 +1,275 @@ +/****************************************************************************/ +/* the diy toolsuite */ +/* */ +/* Jade Alglave, University College London, UK. */ +/* Luc Maranget, INRIA Paris-Rocquencourt, France. */ +/* */ +/* Copyright 2015-present Institut National de Recherche en Informatique et */ +/* en Automatique and the authors. All rights reserved. */ +/* */ +/* This software is governed by the CeCILL-B license under French law and */ +/* abiding by the rules of distribution of free software. You can use, */ +/* modify and/ or redistribute the software under the terms of the CeCILL-B */ +/* license as circulated by CEA, CNRS and INRIA at the following URL */ +/* "http://www.cecill.info". We also give a copy in LICENSE.txt. */ +/****************************************************************************/ +#ifndef _UTILS_H +#define _UTILS_H 1 + +#include +#include +#include +#include "litmus_rand.h" + + +/********/ +/* Misc */ +/********/ + +void seterrlog(FILE *chan) ; + +int log_error(const char *fmt,...) ; + +void fatal(char *msg) ; +/* e is errno */ +void errexit(char *msg,int e) ; + +void *malloc_check(size_t sz) ; + +int max(int n,int m) ; + +void pp_ints (FILE *fp,int *p,int n) ; + +void *do_align(void *p, size_t sz) ; + +void *do_noalign(void *p, size_t sz) ; + +void cat_file(char *path,char *msg,FILE *out) ; + +/***********/ +/* CPU set */ +/***********/ + +#define CPUS_DEFINED 1 +typedef struct { + int sz ; + int *cpu ; +} cpus_t ; + +cpus_t *cpus_create(int sz) ; +cpus_t *cpus_create_init(int sz, int t[]) ; +void cpus_free(cpus_t *p) ; +void cpus_dump(FILE *fp, cpus_t *p) ; +void cpus_dump_test(FILE *fp, int *p, int sz, cpus_t *cm,int nprocs) ; + +int gcd(int a, int b) ; + +cpus_t *coremap_seq(int navail, int nways) ; +cpus_t *coremap_end(int navail, int nways) ; + +void custom_affinity +(st_t *st,cpus_t *cm,int **color,int *diff,cpus_t *aff_cpus,int n_exe, int *r) ; + +/*************/ +/* Int array */ +/*************/ + +typedef struct { + int sz ; + int *t ; +} ints_t ; + +void ints_dump(FILE *fp, ints_t *p) ; + +/* Prefetch directives */ +typedef enum {none, flush, touch, touch_store} prfdir_t ; + +typedef struct { + char *name ; + prfdir_t dir ; +} prfone_t ; + +typedef struct { + int nvars ; + prfone_t *t ; +} prfproc_t ; + +typedef struct { + int nthreads ; + prfproc_t *t ; +} prfdirs_t ; + +void prefetch_dump(FILE *fp, prfdirs_t *p) ; +int parse_prefetch(char *p, prfdirs_t *r) ; + +/************************/ +/* Command line options */ +/************************/ +typedef enum + { aff_none, aff_incr, aff_random, aff_custom, + aff_scan, aff_topo} aff_mode_t ; + +typedef struct { + int verbose ; + /* Test parmeters */ + int max_run ; + int size_of_test ; + int stride ; + int avail ; + int n_exe ; + int sync_n ; + /* Affinity */ + aff_mode_t aff_mode ; + int aff_custom_enabled ; + int aff_scan_enabled ; + int aff_incr ; + cpus_t *aff_cpus ; + char *aff_topo ; + /* indirect mode */ + int shuffle ; + /* loop test */ + int max_loop ; + /* time base delays */ + ints_t * delta_tb ; + /* prefetch control */ + prfdirs_t *prefetch ; + int static_prefetch ; + /* show time of synchronisation */ + int verbose_barrier ; + /* Stop as soon as condition is settled */ + int speedcheck ; + /* Enforce fixed launch order (ie cancel change lauch) */ + int fix ; + /* Dump prelude to test output */ + int prelude ; +} cmd_t ; + +void parse_cmd(int argc, char **argv, cmd_t *def, cmd_t *p) ; + + +/********************/ +/* Thread utilities */ +/********************/ + +/* Mutex */ + +typedef pthread_mutex_t pm_t ; + +pm_t *pm_create(void) ; +void pm_free(pm_t *p) ; +void pm_lock(pm_t *m) ; +void pm_unlock(pm_t *m) ; + +/* Condition variable */ + +typedef struct { + pm_t *c_mutex ; + pthread_cond_t *c_cond ; +} pc_t ; + +pc_t *pc_create(void) ; +void pc_free(pc_t *p) ; +void pc_wait(pc_t *p) ; +void pc_broadcast (pc_t *p) ; + +/* Barrier */ + +/* Avoid pthread supplied barrier as they are not available in old versions */ + +typedef struct { + volatile unsigned int count ; + volatile int turn ; + pc_t *cond ; + unsigned int nprocs ; +} pb_t ; + + +pb_t *pb_create(int nprocs) ; +void pb_free(pb_t *p) ; +void pb_wait(pb_t *p) ; + + +/* Or flag */ + +typedef struct { + pc_t *cond ; + int nprocs ; + int count ; + volatile int val ; + volatile int turn ; +} po_t ; + +po_t *po_create(int nprocs) ; +void po_free(po_t *p) ; +/* Initialize flag, must be called by all participant */ +void po_reinit(po_t *p) ; +/* Return the 'or' of the v arguments of all participants */ +int po_wait(po_t *p, int v) ; + +/* One place buffer */ + +typedef struct { + pc_t *cond ; + int volatile some ; + void * volatile val ; +} op_t ; + +op_t *op_create(void) ; +void op_free(op_t *p) ; +void op_set(op_t *p, void *v) ; +void *op_get(op_t *p) ; + +/* Thread launch and join */ + +typedef void* f_t(void *); + +void launch(pthread_t *th, f_t *f, void *a) ; + +void *join(pthread_t *th) ; + +/* Detached lauch and join */ + +op_t *launch_detached(f_t *f,void *a) ; +void *join_detached(op_t *p) ; + +/* Thread cache */ + +typedef struct { + int max_run ; + op_t *op_arg,*op_ret ; + void *arg ; +} sarg_t ; + +f_t start_thread ; + +/*****************/ +/* Random things */ +/*****************/ + +/* permutations */ + +void perm_prefix_ints(st_t *st,int t[], int used, int sz) ; +void perm_ints(st_t *st,int t[], int sz) ; +void perm_funs(st_t *st,f_t *t[], int sz) ; +void perm_threads(st_t *st,pthread_t t[], int sz) ; +void perm_ops(st_t *st,op_t *t[], int sz) ; + +/* check permutation */ +int check_shuffle(int **t, int *min, int sz) ; + +/*********************/ +/* Real time counter */ +/*********************/ + +typedef unsigned long long tsc_t ; +#define PTSC "%llu" + +/* Result in micro-seconds */ +tsc_t timeofday(void) ; +double tsc_ratio(tsc_t t1, tsc_t t2) ; +double tsc_millions(tsc_t t) ; + +/* String utilities */ +int find_string(char *t[],int sz,char *s) ; + +#endif