NetBSD Problem Report #59126
From www@netbsd.org Tue Mar 4 00:18:32 2025
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256
client-signature RSA-PSS (2048 bits) client-digest SHA256)
(Client CN "mail.NetBSD.org", Issuer "mail.NetBSD.org CA" (not verified))
by mollari.NetBSD.org (Postfix) with ESMTPS id D74781A923A
for <gnats-bugs@gnats.NetBSD.org>; Tue, 4 Mar 2025 00:18:32 +0000 (UTC)
Message-Id: <20250304001831.6161F1A923D@mollari.NetBSD.org>
Date: Tue, 4 Mar 2025 00:18:31 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: pthread_once(3): missing memory ordering
X-Send-Pr-Version: www-1.0
>Number: 59126
>Category: lib
>Synopsis: pthread_once(3): missing memory ordering
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: riastradh
>State: needs-pullups
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Mar 04 00:20:00 +0000 2025
>Closed-Date:
>Last-Modified: Tue Mar 04 02:25:05 +0000 2025
>Originator: Taylor R Campbell
>Release: current, 10, 9, ...
>Organization:
The NetBSD Oncelerbarrier
>Environment:
>Description:
The critical rule of pthread_once(O, I) is that any memory operations during I() in any thread happen-before all memory operations after pthread_once returns.
But the optimistic unlocked test in pthread_once does not guarantee this. It needs membar_release/acquire at least.
>How-To-Repeat:
The following test program probably exhibits the issue on multicore machines with relaxed memory ordering (link with -pthread, run with the number of parallel threads to try, hit ^T for progress or ^C if you get tired of waiting):
#include <err.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
unsigned long long nloop;
static void
onsig(int signo)
{
char buf[128];
snprintf_ss(buf, sizeof(buf), "signal %d after %llu trials\n", signo,
nloop);
(void)write(STDOUT_FILENO, buf, strlen(buf));
if (signo == SIGINFO)
return;
(void)signal(signo, SIG_DFL);
(void)raise(signo);
}
pthread_once_t once, once0 = PTHREAD_ONCE_INIT;
int done = 0;
static void
init(void)
{
done = 1;
}
static void *
thread(void *cookie)
{
pthread_barrier_t *bar = cookie;
(void)pthread_barrier_wait(bar);
pthread_once(&once, &init);
if (!done)
errx(1, "fail after %llu trials", nloop);
}
int
main(int argc, char **argv)
{
enum { N = 256 };
unsigned n = argc == 2 ? atoi(argv[1]) : 16;
if (n < 1)
errx(1, "not enough");
if (n > N)
errx(1, "too many");
if (signal(SIGINT, &onsig) == SIG_ERR)
err(1, "signal(SIGINT)");
if (signal(SIGINFO, &onsig) == SIG_ERR)
err(1, "signal(SIGINFO)");
for (;; nloop++) {
pthread_barrier_t bar;
pthread_t t[N];
unsigned i;
int error;
error = pthread_barrier_init(&bar, NULL, n);
if (error)
errc(1, error, "pthread_barrier_init");
for (i = 0; i < n - 1; i++) {
error = pthread_create(&t[i], NULL, &thread, &bar);
if (error)
errc(1, error, "pthread_create");
}
once = once0;
done = 0;
(void)pthread_barrier_wait(&bar);
pthread_once(&once, &init);
if (!done)
errx(1, "fail");
for (i = 0; i < n - 1; i++) {
error = pthread_join(t[i], NULL);
if (error)
errc(1, error, "pthread_join");
}
error = pthread_barrier_destroy(&bar);
if (error)
errc(1, error, "pthread_barrier_destroy");
}
}
>Fix:
membar_release/acquire
>Release-Note:
>Audit-Trail:
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59126 CVS commit: src/common/lib/libc/atomic
Date: Tue, 4 Mar 2025 00:40:42 +0000
Module Name: src
Committed By: riastradh
Date: Tue Mar 4 00:40:42 UTC 2025
Modified Files:
src/common/lib/libc/atomic: atomic_op_namespace.h
Log Message:
libc atomic_op_namespace.h: Add membar_release and membar_acquire.
These namespace macros will be needed so that libpthread can call
NetBSD's nonstandard membar_release/acquire functions even if linked
against an application that defines symbols of the same name.
Preparation for:
PR lib/59126: pthread_once(3): missing memory ordering
To generate a diff of this commit:
cvs rdiff -u -r1.7 -r1.8 src/common/lib/libc/atomic/atomic_op_namespace.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
From: "Taylor R Campbell" <riastradh@netbsd.org>
To: gnats-bugs@gnats.NetBSD.org
Cc:
Subject: PR/59126 CVS commit: src/lib/libpthread
Date: Tue, 4 Mar 2025 00:41:00 +0000
Module Name: src
Committed By: riastradh
Date: Tue Mar 4 00:41:00 UTC 2025
Modified Files:
src/lib/libpthread: pthread_once.c
Log Message:
pthread_once(3): Add missing memory barriers.
PR lib/59126: pthread_once(3): missing memory ordering
To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/lib/libpthread/pthread_once.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Responsible-Changed-From-To: lib-bug-people->riastradh
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Tue, 04 Mar 2025 02:25:05 +0000
Responsible-Changed-Why:
fixed in HEAD, needs pullup-9 and pullup-10
(confirmed reproducer fails on 4x arm cortex-a53 too)
State-Changed-From-To: open->needs-pullups
State-Changed-By: riastradh@NetBSD.org
State-Changed-When: Tue, 04 Mar 2025 02:25:05 +0000
State-Changed-Why:
mine
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD: gnats_config.sh,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2025
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.