#include <err.h>
#include <stdlib.h>
#include <ucontext.h>
#include <limits.h>
#include <signal.h>
#include <thread.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include "xsave_util.h"
static xsu_fpu_t init_vals, signal_vals, found;
static volatile int exit_status = EXIT_SUCCESS;
static volatile int took_sig = 0;
static uint32_t sr_hwsup;
static void
signal_restore_siginfo(int sig, siginfo_t *sip, void *ucp)
{
struct timespec ts;
took_sig = 1;
ts.tv_sec = 0;
ts.tv_nsec = 10 * MILLISEC;
xsu_setfpu(&signal_vals, sr_hwsup);
yield();
yield();
(void) nanosleep(&ts, NULL);
xsu_getfpu(&found, sr_hwsup);
if (xsu_same(&signal_vals, &found, sr_hwsup)) {
(void) printf("TEST PASSED: FPU contents didn't change in "
"signal handler\n");
} else {
warnx("TEST FAILED: FPU contents changed in signal handler!");
exit_status = EXIT_FAILURE;
}
}
int
main(void)
{
int ret;
thread_t self = thr_self();
uint32_t start = arc4random();
uint32_t hwsup = xsu_hwsupport();
struct sigaction sa;
sr_hwsup = hwsup;
sa.sa_sigaction = signal_restore_siginfo;
sa.sa_flags = SA_RESETHAND;
if (sigaction(SIGINFO, &sa, NULL) != 0) {
errx(EXIT_FAILURE, "TEST FAILED: failed to set up signal "
"handler");
}
(void) printf("filling starting at 0x%x\n", start);
xsu_fill(&init_vals, hwsup, start);
xsu_fill(&signal_vals, hwsup, start + INT_MAX);
(void) memset(&sa, 0, sizeof (struct sigaction));
xsu_setfpu(&init_vals, hwsup);
ret = thr_kill(self, SIGINFO);
xsu_getfpu(&found, hwsup);
if (ret != 0) {
errc(EXIT_FAILURE, ret, "TEST FAILED: failed to deliver "
"signal");
}
if (took_sig == 0) {
errx(EXIT_FAILURE, "TEST FAILED: signal handler did not run");
}
(void) printf("TEST PASSED: SIGINFO successfully delivered\n");
if (xsu_same(&init_vals, &found, hwsup)) {
(void) printf("TEST PASSED: FPU contents successfully "
"restored\n");
} else {
warnx("TEST FAILED: FPU contents were not restored!");
exit_status = EXIT_FAILURE;
}
return (exit_status);
}