From nobody Sat Feb 7 06:21:36 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3ADD3548E0 for ; Mon, 29 Jul 2024 16:10:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722269451; cv=none; b=lEF2cXz+eA4hHyrWghqkvnnq3Hb2gBODt+r2+vK/2yYz4tTZHa+h+tylDIXQZCbl2pyXPkcL26E1je0fvxinGnwalvFPR84UCQmQxhR20NAsrYZgz7otCfIEkoGYOmz+cjNmZ7KcBKVWjdhwC0BwlBRcRPP5+D9woxk2dy4SfVk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722269451; c=relaxed/simple; bh=ipiHST4SCIty4wj5yKMDhrD/wf5bD4cQT7ZVeP+MBUM=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=tmRH5v7sfONQ0NJ6nLbSKQyfLoyORK+1yNKayStg/SMQZdUFrMfAZfxx/eBULPwKIElZC4nLAdHOWrlqK88RAEPK8x7T+KXN13lff51okYH9x3LEfoa7MlqTBaMPzGutrdhUQ4QOmlEj6jcQb70Lmyxjw6vrlqrLOWtApkmHwME= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b=Wp3HYs8Y; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="Wp3HYs8Y" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 9A56AC32786; Mon, 29 Jul 2024 16:10:50 +0000 (UTC) Authentication-Results: smtp.kernel.org; dkim=pass (1024-bit key) header.d=zx2c4.com header.i=@zx2c4.com header.b="Wp3HYs8Y" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=zx2c4.com; s=20210105; t=1722269448; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=YivZziX9LWa/2uzd4bPvyJF25hcnFS/xwNWlvB9xMGI=; b=Wp3HYs8YSq/TjRUqEpVDKPUrjySVQBWa3zh126ysqPd3VzjTsmc5FFvNZh8BRqNduWdhKb jIHvEAxJkEevM6F1YOBTEwugcXwxaWRd1rrAbQFiQ0logeUvLnPIDuao2cJScuqig+Dc9H OptHSmfoq5+rN+VlQDlaQXsO1eiruFQ= Received: by mail.zx2c4.com (ZX2C4 Mail Server) with ESMTPSA id 5bf61c69 (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Mon, 29 Jul 2024 16:10:48 +0000 (UTC) From: "Jason A. Donenfeld" To: linux-kernel@vger.kernel.org Cc: "Jason A. Donenfeld" Subject: [PATCH] selftests/vDSO: simplify getrandom thread local storage and structs Date: Mon, 29 Jul 2024 18:10:36 +0200 Message-ID: <20240729161039.316016-1-Jason@zx2c4.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Rather than using pthread_get/set_specific, just use gcc's __thread annotation, which is noticeably faster and makes the code more obvious. Also, just have one simplified struct called vgrnd, instead of trying to split things up semantically. Those divisions were useful when this code was split across several commit *messages*, but doesn't make as much sense within a single file. This should make the code more clear and provide a better example for implementers. Signed-off-by: Jason A. Donenfeld --- .../selftests/vDSO/vdso_test_getrandom.c | 67 ++++++++----------- 1 file changed, 27 insertions(+), 40 deletions(-) diff --git a/tools/testing/selftests/vDSO/vdso_test_getrandom.c b/tools/tes= ting/selftests/vDSO/vdso_test_getrandom.c index 05122425a873..89c961175956 100644 --- a/tools/testing/selftests/vDSO/vdso_test_getrandom.c +++ b/tools/testing/selftests/vDSO/vdso_test_getrandom.c @@ -38,50 +38,43 @@ static struct { pthread_mutex_t lock; void **states; size_t len, cap; -} grnd_allocator =3D { - .lock =3D PTHREAD_MUTEX_INITIALIZER -}; - -static struct { ssize_t(*fn)(void *, size_t, unsigned long, void *, size_t); - pthread_key_t key; - pthread_once_t initialized; struct vgetrandom_opaque_params params; -} grnd_ctx =3D { - .initialized =3D PTHREAD_ONCE_INIT +} vgrnd =3D { + .lock =3D PTHREAD_MUTEX_INITIALIZER }; =20 static void *vgetrandom_get_state(void) { void *state =3D NULL; =20 - pthread_mutex_lock(&grnd_allocator.lock); - if (!grnd_allocator.len) { + pthread_mutex_lock(&vgrnd.lock); + if (!vgrnd.len) { size_t page_size =3D getpagesize(); size_t new_cap; size_t alloc_size, num =3D sysconf(_SC_NPROCESSORS_ONLN); /* Just a dece= nt heuristic. */ void *new_block, *new_states; =20 - alloc_size =3D (num * grnd_ctx.params.size_of_opaque_state + page_size -= 1) & (~(page_size - 1)); - num =3D (page_size / grnd_ctx.params.size_of_opaque_state) * (alloc_size= / page_size); - new_block =3D mmap(0, alloc_size, grnd_ctx.params.mmap_prot, grnd_ctx.pa= rams.mmap_flags, -1, 0); + alloc_size =3D (num * vgrnd.params.size_of_opaque_state + page_size - 1)= & (~(page_size - 1)); + num =3D (page_size / vgrnd.params.size_of_opaque_state) * (alloc_size / = page_size); + new_block =3D mmap(0, alloc_size, vgrnd.params.mmap_prot, vgrnd.params.m= map_flags, -1, 0); if (new_block =3D=3D MAP_FAILED) goto out; =20 - new_cap =3D grnd_allocator.cap + num; - new_states =3D reallocarray(grnd_allocator.states, new_cap, sizeof(*grnd= _allocator.states)); + new_cap =3D vgrnd.cap + num; + new_states =3D reallocarray(vgrnd.states, new_cap, sizeof(*vgrnd.states)= ); if (!new_states) goto unmap; - grnd_allocator.cap =3D new_cap; - grnd_allocator.states =3D new_states; + vgrnd.cap =3D new_cap; + vgrnd.states =3D new_states; =20 for (size_t i =3D 0; i < num; ++i) { - if (((uintptr_t)new_block & (page_size - 1)) + grnd_ctx.params.size_of_= opaque_state > page_size) + if (((uintptr_t)new_block & (page_size - 1)) + vgrnd.params.size_of_opa= que_state > page_size) new_block =3D (void *)(((uintptr_t)new_block + page_size - 1) & (~(pag= e_size - 1))); - grnd_allocator.states[i] =3D new_block; - new_block +=3D grnd_ctx.params.size_of_opaque_state; + vgrnd.states[i] =3D new_block; + new_block +=3D vgrnd.params.size_of_opaque_state; } - grnd_allocator.len =3D num; + vgrnd.len =3D num; goto success; =20 unmap: @@ -89,10 +82,10 @@ static void *vgetrandom_get_state(void) goto out; } success: - state =3D grnd_allocator.states[--grnd_allocator.len]; + state =3D vgrnd.states[--vgrnd.len]; =20 out: - pthread_mutex_unlock(&grnd_allocator.lock); + pthread_mutex_unlock(&vgrnd.lock); return state; } =20 @@ -100,27 +93,25 @@ static void vgetrandom_put_state(void *state) { if (!state) return; - pthread_mutex_lock(&grnd_allocator.lock); - grnd_allocator.states[grnd_allocator.len++] =3D state; - pthread_mutex_unlock(&grnd_allocator.lock); + pthread_mutex_lock(&vgrnd.lock); + vgrnd.states[vgrnd.len++] =3D state; + pthread_mutex_unlock(&vgrnd.lock); } =20 static void vgetrandom_init(void) { - if (pthread_key_create(&grnd_ctx.key, vgetrandom_put_state) !=3D 0) - return; unsigned long sysinfo_ehdr =3D getauxval(AT_SYSINFO_EHDR); if (!sysinfo_ehdr) { printf("AT_SYSINFO_EHDR is not present!\n"); exit(KSFT_SKIP); } vdso_init_from_sysinfo_ehdr(sysinfo_ehdr); - grnd_ctx.fn =3D (__typeof__(grnd_ctx.fn))vdso_sym("LINUX_2.6", "__vdso_ge= trandom"); - if (!grnd_ctx.fn) { + vgrnd.fn =3D (__typeof__(vgrnd.fn))vdso_sym("LINUX_2.6", "__vdso_getrando= m"); + if (!vgrnd.fn) { printf("__vdso_getrandom is missing!\n"); exit(KSFT_FAIL); } - if (grnd_ctx.fn(NULL, 0, 0, &grnd_ctx.params, ~0UL) !=3D 0) { + if (vgrnd.fn(NULL, 0, 0, &vgrnd.params, ~0UL) !=3D 0) { printf("failed to fetch vgetrandom params!\n"); exit(KSFT_FAIL); } @@ -128,22 +119,16 @@ static void vgetrandom_init(void) =20 static ssize_t vgetrandom(void *buf, size_t len, unsigned long flags) { - void *state; + static __thread void *state; =20 - pthread_once(&grnd_ctx.initialized, vgetrandom_init); - state =3D pthread_getspecific(grnd_ctx.key); if (!state) { state =3D vgetrandom_get_state(); - if (pthread_setspecific(grnd_ctx.key, state) !=3D 0) { - vgetrandom_put_state(state); - state =3D NULL; - } if (!state) { printf("vgetrandom_get_state failed!\n"); exit(KSFT_FAIL); } } - return grnd_ctx.fn(buf, len, flags, state, grnd_ctx.params.size_of_opaque= _state); + return vgrnd.fn(buf, len, flags, state, vgrnd.params.size_of_opaque_state= ); } =20 enum { TRIALS =3D 25000000, THREADS =3D 256 }; @@ -265,6 +250,8 @@ static void usage(const char *argv0) =20 int main(int argc, char *argv[]) { + vgetrandom_init(); + if (argc =3D=3D 1) { kselftest(); return 0; --=20 2.45.2