From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.1 (2015-04-28) on dcvr.yhbt.net X-Spam-Level: X-Spam-ASN: X-Spam-Status: No, score=-2.6 required=3.0 tests=ALL_TRUSTED,AWL,BAYES_00, UNWANTED_LANGUAGE_BODY shortcircuit=no autolearn=ham autolearn_force=no version=3.4.1 Received: from localhost (dcvr.yhbt.net [127.0.0.1]) by dcvr.yhbt.net (Postfix) with ESMTP id 8B28A1F597; Tue, 31 Jul 2018 08:22:05 +0000 (UTC) Date: Tue, 31 Jul 2018 08:22:05 +0000 From: Eric Wong To: spew@80x24.org Subject: xthr.c Message-ID: <20180731082205.vykyunsm5xg7ml3e@dcvr> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Disposition: inline List-Id: /* * Cross-thread memory allocation test * Copyright (C) 2014-2018, Eric Wong * License: LGPLv2.1 or later (depends on URCU) * * gcc -o xthr xthr.c -O3 -pthread -lurcu-cds -lurcu * Usage: xthr [-a NALLOC] [-m BYTES] [-i ITERATIONS] * * -a number of threads doing allocation (default:1) * -m malloc size in bytes (default:1 word (4-8 bytes)) * -i total number of malloc/free pairs (default:1024) */ #include #include #include #include #include #include #include #include #include #include static int memzero; static size_t iter = 1024; static size_t alloc_bytes = sizeof(struct rcu_head); static void do_free(struct rcu_head *head) { free(head); } static void *do_alloc(void *arg) { const size_t max = (const size_t)arg; const size_t bytes = alloc_bytes; size_t i; rcu_register_thread(); if (memzero) { const size_t zbytes = bytes - CAA_CACHE_LINE_SIZE; for (i = 0; i < max; i++) { struct rcu_head *node = malloc(bytes); if (!node) errx(1, "malloc failed"); memset(node, 0, zbytes); call_rcu(node, do_free); } } else { for (i = 0; i < max; i++) { struct rcu_head *node = malloc(bytes); if (!node) errx(1, "malloc failed"); call_rcu(node, do_free); } } rcu_unregister_thread(); return NULL; } int main(int argc, char *argv[]) { size_t i; unsigned long nalloc = 1, nfree = 1; pthread_t *th_alloc; int err; int opt; unsigned long call_rcu_flags = 0; rcu_init(); rcu_register_thread(); while ((opt = getopt(argc, argv, "a:m:i:zr")) != -1) { char *end; size_t c = 0; switch (opt) { case 'a': c = nalloc = strtoul(optarg, &end, 10); break; case 'm': c = alloc_bytes = strtoul(optarg, &end, 10); break; case 'i': c = iter = strtoul(optarg, &end, 10); break; case 'r': call_rcu_flags = URCU_CALL_RCU_RT; continue; case 'z': memzero = 1; continue; default: errx(1, "bad arg: -%c", opt); } if (*end) errx(1, "trailing bytes: %s", end); if (c == 0) errx(1, "-%c must be non-zero", opt); } if (alloc_bytes < sizeof(struct rcu_head)) { alloc_bytes = sizeof(struct rcu_head); fprintf(stderr, "-m clamped to %zu bytes\n", alloc_bytes); } if (memzero && alloc_bytes <= CAA_CACHE_LINE_SIZE) memzero = 0; th_alloc = malloc(sizeof(pthread_t) * nalloc); if (!th_alloc) errx(1, "malloc fails"); for (i = 0; i < nalloc; i++) { size_t n = iter / nalloc; if (i == 0) n += iter % nalloc; err = pthread_create(&th_alloc[i], NULL, do_alloc, (void *)n); if (err != 0) errx(1, "failed to create thread: %s", strerror(err)); } for (i = 0; i < nalloc; i++) { err = pthread_join(th_alloc[i], NULL); if (err != 0) errx(1, "failed to join thread: %s", strerror(err)); } rcu_barrier(); rcu_unregister_thread(); return 0; }