NetBSD Problem Report #57950

From  Mon Feb 19 23:10:33 2024
Return-Path: <>
Received: from ( [])
	(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits))
	(Client CN "", Issuer " CA" (not verified))
	by (Postfix) with ESMTPS id EF7EA1A9239
	for <>; Mon, 19 Feb 2024 23:10:32 +0000 (UTC)
Message-Id: <>
Date: Mon, 19 Feb 2024 23:10:31 +0000 (UTC)
Subject: ucontext should provide accessors for fenv(3)
X-Send-Pr-Version: www-1.0

>Number:         57950
>Category:       lib
>Synopsis:       ucontext should provide accessors for fenv(3)
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    lib-bug-people
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Feb 19 23:15:00 +0000 2024
>Originator:     Taylor R Campbell
>Release:        current, 10, 9, ...
Regents of the Ucontext of Califpudna
When floating-point exception trapping is enabled with feenableexcept(3), and the system delivers SIGFPE on a floating-point exception trap, the system disables traps and clears sticky exceptions on entry to the signal handler.

The information of which exception traps were enabled, and which sticky exception bits were set, is lost in this case in any MI API -- except for the one exception that triggered this particular trap, which is reported through siginfo si_code.

However, the information is available through MD ucontext bits.  For example, on x86, ((struct fxsave *)ucp->uc_mcontext.__fpregs)->fx_cw, ->fx_sw, and ->fx_mxcsr have this information.  And the set of exceptions with sticky bits set or trapping enabled can also be controlled by writing to the ucontext before the signal handler returns; this way, the signal handler can, for example, record diagnostic information about where the first exception happened, and then let the program pick up where it left off but with exception trapping disabled.

It would be nice if there were an MI analogue of the fenv(3) API functions -- like fetestexcept to query sticky bits, feclearexcept/feraiseexcept to set sticky bits, fegetexcept to query exception trapping, and feenableexcept/fedisableexcept to control exception trapping -- that operated on a ucontext for use by a SIGFPE handler.  We have _UC_MACHINE_SP, _UC_MACHINE_PC, and similar MI functions -- it shouldn't be too hard (beyond a SMOP to do it on all architectures) to create a similar API for ucontext fenv(3) access.
Try to adapt this example program to MI APIs:

#include <sys/ucontext.h>

#include <err.h>
#include <fenv.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>

#include <x86/cpu_extended_state.h>

on_sigfpe(int signo, siginfo_t *si, void *ctx)
	ucontext_t *ucp = ctx;
	struct fxsave *fx = (struct fxsave *)ucp->uc_mcontext.__fpregs;

	fprintf(stderr, "SIGFPE code=%d\n", si->si_code);
	fx->fx_cw |= FE_ALL_EXCEPT; /* mask all exception traps */
	fx->fx_mxcsr |= __SHIFTIN(FE_ALL_EXCEPT, __BITS(7,12));
	/* retry with exception traps masked */

volatile double one = 1;
volatile double zero = 0;
volatile double quot;

	return one/zero;

	struct sigaction sa;

	memset(&sa, 0, sizeof(sa));
	sa.sa_sigaction = &on_sigfpe;
	sa.sa_flags = SA_SIGINFO;
	if (sigaction(SIGFPE, &sa, NULL) == -1)
		err(1, "sigaction(SIGFPE)");

	fprintf(stderr, "dividing by zero 1, trap=0x%x\n", fegetexcept());
	fprintf(stderr, "result=%a\n", fpe_divbyzero());
	fprintf(stderr, "dividing by zero 2, trap=0x%x\n", fegetexcept());
	fprintf(stderr, "result=%a\n", fpe_divbyzero());

	return 0;

Yes, please!

NetBSD Home
NetBSD PR Database Search

(Contact us) $NetBSD: query-full-pr,v 1.47 2022/09/11 19:34:41 kim Exp $
$NetBSD:,v 1.9 2014/08/02 14:16:04 spz Exp $
Copyright © 1994-2024 The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.