xref: /onnv-gate/usr/src/cmd/fps/fpsd/fpsd_main.c (revision 7435:f05e6d8813dc)
16429Svs195195 /*
26429Svs195195  * CDDL HEADER START
36429Svs195195  *
46429Svs195195  * The contents of this file are subject to the terms of the
56429Svs195195  * Common Development and Distribution License (the "License").
66429Svs195195  * You may not use this file except in compliance with the License.
76429Svs195195  *
86429Svs195195  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96429Svs195195  * or http://www.opensolaris.org/os/licensing.
106429Svs195195  * See the License for the specific language governing permissions
116429Svs195195  * and limitations under the License.
126429Svs195195  *
136429Svs195195  * When distributing Covered Code, include this CDDL HEADER in each
146429Svs195195  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156429Svs195195  * If applicable, add the following below this CDDL HEADER, with the
166429Svs195195  * fields enclosed by brackets "[]" replaced with your own identifying
176429Svs195195  * information: Portions Copyright [yyyy] [name of copyright owner]
186429Svs195195  *
196429Svs195195  * CDDL HEADER END
206429Svs195195  */
216429Svs195195 
226429Svs195195 /*
236429Svs195195  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
246429Svs195195  * Use is subject to license terms.
256429Svs195195  */
266429Svs195195 
276429Svs195195 #include <stdio.h>
286429Svs195195 #include <string.h>
296429Svs195195 #include <sys/types.h>
306429Svs195195 #include <dirent.h>
316429Svs195195 #include <stdarg.h>
326429Svs195195 #include <stddef.h>
336429Svs195195 #include <stdlib.h>
346429Svs195195 #include <dlfcn.h>
356429Svs195195 #include <door.h>
366429Svs195195 #include <errno.h>
376429Svs195195 #include <fcntl.h>
386429Svs195195 #include <strings.h>
396429Svs195195 #include <unistd.h>
406429Svs195195 #include <synch.h>
416429Svs195195 #include <syslog.h>
426429Svs195195 #include <pthread.h>
436429Svs195195 #include <thread.h>
446429Svs195195 #include <signal.h>
456429Svs195195 #include <limits.h>
466429Svs195195 #include <locale.h>
476429Svs195195 #include <sys/stat.h>
486429Svs195195 #include <sys/systeminfo.h>
496429Svs195195 #include <sys/wait.h>
506429Svs195195 #include <sys/processor.h>
516429Svs195195 #include <ctype.h>
526429Svs195195 #include <poll.h>
536429Svs195195 #include <sys/wait.h>
546429Svs195195 #include <dirent.h>
556429Svs195195 #include <kstat.h>
566429Svs195195 #include <libscf.h>
576429Svs195195 #include <sys/pset.h>
586429Svs195195 #include <sys/param.h>
596429Svs195195 #include <sys/corectl.h>
606429Svs195195 #include <libgen.h>
616429Svs195195 #include <priv_utils.h>
626429Svs195195 #include <fpsapi.h>
636429Svs195195 
646429Svs195195 #include "fpsd.h"
656429Svs195195 #include "messages.h"
666429Svs195195 
677346SVaidehi.Rangan@Sun.COM #define	SMF_SNAPSHOT_RUNNING	"running"
687346SVaidehi.Rangan@Sun.COM 
696429Svs195195 /* Only messages of priority 'debug_level' and lower will be logged */
706429Svs195195 int debug_level = DFLT_DBG_LVL;
716429Svs195195 
726429Svs195195 fpsd_t  fpsd;
736429Svs195195 mach_conf_t fpsd_conf;
746429Svs195195 char  fps_tst_path[MAXPATHLEN + MAXNAMELEN];
756429Svs195195 
766429Svs195195 void terminate_process();
776429Svs195195 
786429Svs195195 /* Local Static Variables */
796429Svs195195 
806429Svs195195 static int  door_id = -1;
816429Svs195195 static char *str_fps_fmri = NULL;
826429Svs195195 
836429Svs195195 /* Local static functions */
846429Svs195195 
856429Svs195195 static int check_if_supported_CPU(char *cpu_brand, char *arch);
866429Svs195195 static int read_conf_props();
876429Svs195195 static  void fpsd_fini();
886429Svs195195 static int reprobe_and_reread_config();
896429Svs195195 static int fpsd_probe_config();
906429Svs195195 static int fpsd_probe(mach_conf_t *m_stat);
916429Svs195195 
926429Svs195195 
936429Svs195195 /* ARGSUSED */
946429Svs195195 void
sig_hup_handler(int sig,siginfo_t * siginfo,void * sigctx)956429Svs195195 sig_hup_handler(int sig, siginfo_t *siginfo, void *sigctx)
966429Svs195195 {
976429Svs195195 	fpsd_message(FPSD_NO_EXIT, FPS_INFO,
986429Svs195195 	    SIGNAL_INFO, "HUP", SIGHUP);
997346SVaidehi.Rangan@Sun.COM 	fpsd.d_conf->m_reprobe = 1;
1006429Svs195195 }
1016429Svs195195 
1026429Svs195195 void
fpsd_read_config()1036429Svs195195 fpsd_read_config()
1046429Svs195195 {
1056429Svs195195 	int ret;
1066429Svs195195 
1076429Svs195195 	ret = reprobe_and_reread_config();
1086429Svs195195 	if (NO_CPUS_2_TEST == ret) {
1096429Svs195195 		while (NO_CPUS_2_TEST == ret) {
1107346SVaidehi.Rangan@Sun.COM 			if (!fpsd.d_conf->m_reprobe) {
1117346SVaidehi.Rangan@Sun.COM 				(void) sleep(600);
1127346SVaidehi.Rangan@Sun.COM 			}
1136429Svs195195 			ret = reprobe_and_reread_config();
1146429Svs195195 		}
1156429Svs195195 	}
1166429Svs195195 }
1176429Svs195195 
1186429Svs195195 static int
reprobe_and_reread_config()1196429Svs195195 reprobe_and_reread_config()
1206429Svs195195 {
1216429Svs195195 	int ret;
1227346SVaidehi.Rangan@Sun.COM 	static int first_time = 1;
1236429Svs195195 
1247346SVaidehi.Rangan@Sun.COM 	if (!first_time) {
1257346SVaidehi.Rangan@Sun.COM 		fpsd.d_conf->m_reprobe = 1;
1267346SVaidehi.Rangan@Sun.COM 		if (fpsd_probe(fpsd.d_conf) != 0) {
1277346SVaidehi.Rangan@Sun.COM 			(void) fpsd_message(FPSD_EXIT_ERROR,
128*7435SVaidehi.Rangan@Sun.COM 			    FPS_WARNING, REPROBE_FAILURE);
1297346SVaidehi.Rangan@Sun.COM 		}
1307346SVaidehi.Rangan@Sun.COM 	} else {
1317346SVaidehi.Rangan@Sun.COM 		first_time = 0;
1326429Svs195195 	}
1336429Svs195195 	ret = fpsd_probe_config();
1346429Svs195195 	if (ZERO_INTERVAL == ret) {
135*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_EXIT_ERROR, FPS_WARNING,
1366429Svs195195 		    FPSD_ZERO_INTVL, fpsd.d_interval);
1376429Svs195195 	}
1386429Svs195195 	return (ret);
1396429Svs195195 
1406429Svs195195 }
1416429Svs195195 
1426429Svs195195 static int
daemon_exists()1436429Svs195195 daemon_exists()
1446429Svs195195 {
1456429Svs195195 	int door_fd;
1466429Svs195195 	struct door_info dinfo;
1476429Svs195195 
1486429Svs195195 	door_fd = open(FPS_DOOR_FILE, O_RDONLY);
1496429Svs195195 	if (door_fd < 0)
1506429Svs195195 		return (NO_DAEMON);
1516429Svs195195 	if (door_info(door_fd, &dinfo) < 0) {
1526429Svs195195 		(void) close(door_fd);
1536429Svs195195 		return (NO_DAEMON);
1546429Svs195195 	}
1556429Svs195195 	if ((dinfo.di_attributes & DOOR_REVOKED) ||
1566429Svs195195 	    (dinfo.di_data != (uintptr_t)FPS_DOOR_COOKIE)) {
1576429Svs195195 		(void) close(door_fd);
1586429Svs195195 		return (NO_DAEMON);
1596429Svs195195 	}
1606429Svs195195 	if (dinfo.di_target != getpid()) {
1616429Svs195195 		/* Daemon exists; different process */
1626429Svs195195 		(void) close(door_fd);
1636429Svs195195 		return (DAEMON_EXISTS);
1646429Svs195195 	} else {
1656429Svs195195 		(void) close(door_fd);
1666429Svs195195 		return (DAEMON_EXISTS_AND_SAME_PROC); /* Same process */
1676429Svs195195 	}
1686429Svs195195 
1696429Svs195195 }
1706429Svs195195 
1716429Svs195195 static  int
fps_setup_door(void)1726429Svs195195 fps_setup_door(void)
1736429Svs195195 {
1746429Svs195195 
1756429Svs195195 	struct stat	stbuf;
1766429Svs195195 	int newfd;
1776429Svs195195 
1786429Svs195195 	/*  Create the door */
1796429Svs195195 	door_id = door_create(fps_door_handler, FPS_DOOR_COOKIE, 0);
1806429Svs195195 
1816429Svs195195 	if (door_id < 0) {
182*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_NO_EXIT, FPS_WARNING, DAEMON_DOOR_FAIL,
1836429Svs195195 		    strerror(errno));
1846429Svs195195 		return (-1);
1856429Svs195195 	}
1866429Svs195195 
1876429Svs195195 	if (stat(FPS_DOOR_FILE, &stbuf) < 0) {
1886429Svs195195 		if ((newfd = creat(FPS_DOOR_FILE, 0600)) < 0) {
1896429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_ERROR,
1906429Svs195195 			    DAEMON_DOOR_FILE_FAIL, strerror(errno));
1916429Svs195195 			return (-1);
1926429Svs195195 		}
1936429Svs195195 		(void) close(newfd);
1946429Svs195195 	}
1956429Svs195195 
1966429Svs195195 	if (fattach(door_id, FPS_DOOR_FILE) < 0) {
1976429Svs195195 		if ((errno != EBUSY) || (fdetach(FPS_DOOR_FILE) < 0) ||
1986429Svs195195 		    (fattach(door_id, FPS_DOOR_FILE) < 0)) {
1996429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_ERROR,
2006429Svs195195 			    DAEMON_DOOR_FATTACH_FAIL,
2016429Svs195195 			    strerror(errno));
2026429Svs195195 			return (-1);
2036429Svs195195 		}
2046429Svs195195 	}
2056429Svs195195 
2066429Svs195195 	return (0);
2076429Svs195195 }
2086429Svs195195 
2096429Svs195195 void
terminate_process()2106429Svs195195 terminate_process()
2116429Svs195195 {
2126429Svs195195 	fpsd_fini();
2136429Svs195195 	if (door_id >= 0) {
2146429Svs195195 		(void) door_revoke(door_id);
2156429Svs195195 		(void) unlink(FPS_DOOR_FILE);
2166429Svs195195 	}
2176429Svs195195 }
2186429Svs195195 
2196429Svs195195 static int
become_daemon_init()2206429Svs195195 become_daemon_init()
2216429Svs195195 {
2226429Svs195195 	int pfds[2];
2236429Svs195195 	pid_t pid;
2246429Svs195195 	int status;
2256429Svs195195 	sigset_t set, oset;
2266429Svs195195 
2276429Svs195195 	/*
2286429Svs195195 	 * Block all signals prior to the fork and leave them blocked in
2296429Svs195195 	 * the parent so we don't get in a situation where the parent gets
2306429Svs195195 	 * SIGINT and returns non-zero exit status and the child is
2316429Svs195195 	 * actually running. In the child, restore the signal mask once
2326429Svs195195 	 * we've done our setsid().
2336429Svs195195 	 */
2346429Svs195195 	(void) sigfillset(&set);
2356429Svs195195 	(void) sigdelset(&set, SIGABRT);
2366429Svs195195 	(void) sigdelset(&set, SIGHUP);
2376429Svs195195 	(void) sigprocmask(SIG_BLOCK, &set, &oset);
2386429Svs195195 
2396429Svs195195 
2406429Svs195195 	if (pipe(pfds) == -1)
2416429Svs195195 		fpsd_message(FPSD_EXIT_ERROR, FPS_ERROR, DAEMON_PIPE_FAIL,
2426429Svs195195 		    strerror(errno));
2436429Svs195195 
2446429Svs195195 	if ((pid = fork()) == -1)
2456429Svs195195 		fpsd_message(FPSD_EXIT_ERROR, FPS_ERROR, DAEMON_FORK_FAIL,
2466429Svs195195 		    strerror(errno));
2476429Svs195195 
2486429Svs195195 	/*
2496429Svs195195 	 * If we're the parent process, wait for either the child to send
2506429Svs195195 	 * us the appropriate exit status over the pipe or for the read to
2516429Svs195195 	 * fail (presumably with 0 for EOF if our child terminated
2526429Svs195195 	 * abnormally). If the read fails, exit with either the child's
2536429Svs195195 	 * exit status if it exited or with FPSD_EXIT_ERROR if it died
2546429Svs195195 	 * from a fatal signal.
2556429Svs195195 	 */
2566429Svs195195 	if (pid != 0) { /* Parent */
2576429Svs195195 		(void) close(pfds[1]);
2586429Svs195195 
2596429Svs195195 		if (read(pfds[0], &status, sizeof (status)) == sizeof (status))
2606429Svs195195 			_exit(status);
2616429Svs195195 
2626429Svs195195 		if (waitpid(pid, &status, 0) == pid && WIFEXITED(status))
2636429Svs195195 			_exit(WEXITSTATUS(status));
2646429Svs195195 
2656429Svs195195 		_exit(FPSD_EXIT_ERROR);
2666429Svs195195 	}
2676429Svs195195 
2686429Svs195195 	fpsd.d_pid = getpid();
2696429Svs195195 	(void) sigprocmask(SIG_SETMASK, &oset, NULL); /* Restore signal mask */
2706429Svs195195 	(void) setsid();
2716429Svs195195 	(void) chdir("/");
2726429Svs195195 	(void) umask(022);
2736429Svs195195 	(void) close(pfds[0]);
2746429Svs195195 	return (pfds[1]);
2756429Svs195195 }
2766429Svs195195 
2776429Svs195195 
2786429Svs195195 static void
become_daemon_fini(int fd)2796429Svs195195 become_daemon_fini(int fd)
2806429Svs195195 {
2816429Svs195195 	(void) close(fd);
2826429Svs195195 	if ((fd = open("/dev/null", O_RDWR)) >= 0) {
2836429Svs195195 		(void) fcntl(fd, F_DUP2FD, STDIN_FILENO);
2846429Svs195195 		(void) fcntl(fd, F_DUP2FD, STDOUT_FILENO);
2856429Svs195195 		(void) fcntl(fd, F_DUP2FD, STDERR_FILENO);
2866429Svs195195 		(void) close(fd);
2876429Svs195195 	}
2886429Svs195195 
2896429Svs195195 }
2906429Svs195195 
2916429Svs195195 /*
2926429Svs195195  * Calculates the number of iterations needed for each testable cpu
2936429Svs195195  * based on the frequency and using the following table. This table
2946429Svs195195  * tells how much time it takes for the matrix sizes on a processor
2956429Svs195195  * with frequencies upto 1000MHz/1500 MHz/ 2000 MHz. This data is
2966429Svs195195  * based on profiling done earlier.
2976429Svs195195  *
2986429Svs195195  * f\p\t| 100  200   300   400    500     600     700     800     900 ms
2996429Svs195195  * ======================================================================
3006429Svs195195  * 1000  1-28 29-50 51-62 63-72  73-81   82-90   91-98   99-105  106-112
3016429Svs195195  * 1500  1-36 37-64 65-80 81-93  94-106  107-115 116-126 127-134 135-144
3026429Svs195195  * 2000  1-39 40-70 71-87 88-102 103-113 114-126 127-137 138-148 149-157
3036429Svs195195  *
3046429Svs195195  * If asc is 0, these iterations will be executed in the descending of
3056429Svs195195  * of matrix size; else the iterations will be executed in the increasing
3066429Svs195195  * order of matrix sizes. This is done to average out the execution time
3076429Svs195195  * as large matrices mean more time to complete the test.
3086429Svs195195  */
3096429Svs195195 
3106429Svs195195 static void
calculateTotalIterations(mach_conf_t * m_stat)3116429Svs195195 calculateTotalIterations(mach_conf_t *m_stat)
3126429Svs195195 {
3136429Svs195195 	const int num_iterations_1K = 112;
3146429Svs195195 	const int num_iterations_1500 = 144;
3156429Svs195195 	const int num_iterations_2K = 157;
3166429Svs195195 
3176429Svs195195 	int total_iterations = 0;
3186429Svs195195 	int asc = 1;
3196429Svs195195 	int i;
3206429Svs195195 	int freq;
3216429Svs195195 
3226429Svs195195 	if (m_stat->m_cpuids_size <= 0) {
323*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_EXIT_ERROR, FPS_WARNING,
324*7435SVaidehi.Rangan@Sun.COM 		    ZERO_CPUS_2_TST);
3256429Svs195195 	}
3266429Svs195195 	m_stat->m_num_cpus_to_test = 0;
3276429Svs195195 	for (i = 0; i < m_stat->m_cpuids_size; i++) {
3286429Svs195195 		if (m_stat->m_cpus[i].disable_test)
3296429Svs195195 			continue;
3306429Svs195195 		freq = m_stat->m_cpus[i].frequency;
3316429Svs195195 		m_stat->m_cpus[i].asc = asc;
3326429Svs195195 		if (freq < 1500) {
3336429Svs195195 			total_iterations += num_iterations_1K;
3346429Svs195195 			m_stat->m_cpus[i].total_iterations = num_iterations_1K;
3356429Svs195195 		} else if (freq < 2000) {
3366429Svs195195 			total_iterations += num_iterations_1500;
3376429Svs195195 			m_stat->m_cpus[i].total_iterations =
3386429Svs195195 			    num_iterations_1500;
3396429Svs195195 		} else {
3406429Svs195195 			total_iterations += num_iterations_2K;
3416429Svs195195 			m_stat->m_cpus[i].total_iterations = num_iterations_2K;
3426429Svs195195 		}
3436429Svs195195 		if (asc) {
3446429Svs195195 			m_stat->m_cpus[i].previous_iteration = 0;
3456429Svs195195 			asc = 0;
3466429Svs195195 		} else {
3476429Svs195195 			m_stat->m_cpus[i].previous_iteration =
3486429Svs195195 			    m_stat->m_cpus[i].total_iterations + 1;
3496429Svs195195 			asc = 1;
3506429Svs195195 		}
3516429Svs195195 		m_stat->m_num_cpus_to_test++;
3526429Svs195195 	}
3536429Svs195195 	fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, TOT_ITERS,
3546429Svs195195 	    total_iterations, m_stat->m_num_cpus_to_test);
3556429Svs195195 	fpsd.d_conf->total_iter = total_iterations;
3566429Svs195195 }
3576429Svs195195 
3586429Svs195195 /*
3596429Svs195195  * Calculates the time interval between the tests invocation in seconds.
3606429Svs195195  * The goal is to complete once all iterations for all cpus in a 24hr
3616429Svs195195  * period.
3626429Svs195195  */
3636429Svs195195 
3646429Svs195195 static int
calculateTimeInterval()3656429Svs195195 calculateTimeInterval()
3666429Svs195195 {
3676429Svs195195 	int total_iterations = fpsd.d_conf->total_iter;
3686429Svs195195 	int intvl;
3696429Svs195195 
3706429Svs195195 	if (total_iterations <= 0) {
371*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_EXIT_ERROR, FPS_WARNING,
372*7435SVaidehi.Rangan@Sun.COM 		    FPSD_MIS_CALCULATIONS, total_iterations);
3736429Svs195195 	}
3746429Svs195195 	intvl = (24*60*60) / (total_iterations);
3756429Svs195195 	fpsd.d_interval = intvl;
3766429Svs195195 	return (1);
3776429Svs195195 }
3786429Svs195195 
3796429Svs195195 /*
3806429Svs195195  * Checks if a platform is supported by looking for the corresponding
3816429Svs195195  * binary under /usr/lib/fps/ARCH/CPU_BRAND/fptest; (e.g) ARCH = sun4u,
3826429Svs195195  * CPU_BRAND = UltraSPARC-III;
3836429Svs195195  */
3846429Svs195195 
3856429Svs195195 static int
check_if_supported_CPU(char * cpu_brand,char * arch)3866429Svs195195 check_if_supported_CPU(char *cpu_brand, char *arch)
3876429Svs195195 {
388*7435SVaidehi.Rangan@Sun.COM 	if ((NULL == cpu_brand) || (NULL == arch)) {
389*7435SVaidehi.Rangan@Sun.COM 		return (0);
390*7435SVaidehi.Rangan@Sun.COM 	}
3916429Svs195195 	(void) snprintf(fps_tst_path, sizeof (fps_tst_path), "%s/%s/%s/%s",
3926429Svs195195 	    FPS_DIR, arch, cpu_brand, FPS_FPUTST_NAME);
3936429Svs195195 	fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, FPTST_BIN_PTH, fps_tst_path);
3946429Svs195195 	if (access(fps_tst_path, X_OK) == 0)
3956429Svs195195 		return (1);
3966429Svs195195 	else
3976429Svs195195 		return (0);
3986429Svs195195 }
3996429Svs195195 
4006429Svs195195 /*
4016429Svs195195  * fpsd_probe(): probes system configuration and
4026429Svs195195  * sets up the fpsd_t structure.
4036429Svs195195  * Returns 0 on success, non-zero on failure.
4046429Svs195195  *
4056429Svs195195  */
4066429Svs195195 static int
fpsd_probe(mach_conf_t * m_stat)4076429Svs195195 fpsd_probe(mach_conf_t *m_stat)
4086429Svs195195 {
4096429Svs195195 	kstat_ctl_t *kstat_ctl;
4106429Svs195195 	kstat_t *fps_kstat;
4116429Svs195195 	kstat_named_t *kstat_cpu_name;
4126429Svs195195 	kstat_named_t *kstat_cpu_freq;
4136429Svs195195 	char *cpu_brand = NULL;
4146429Svs195195 	int cpu_freq;
4156429Svs195195 	int supported;
4166429Svs195195 	int i;
4176429Svs195195 	int cpuid_index;
4186429Svs195195 
4197346SVaidehi.Rangan@Sun.COM 	processorid_t *cpuid_list = NULL;
4206429Svs195195 	kid_t ret;
4217101Svs195195 	int total_onln = sysconf(_SC_NPROCESSORS_ONLN);
4226429Svs195195 
4236429Svs195195 	/* probe the system and fill in mach_conf_t elements */
4246429Svs195195 
4256429Svs195195 	(void) sysinfo(SI_MACHINE, m_stat->m_machine,
4266429Svs195195 	    sizeof (m_stat->m_machine) - 1);
4276429Svs195195 
4286429Svs195195 	if (1 == m_stat->m_reprobe) {
4296429Svs195195 		/* Reprobe request */
4306429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, REPRBE_REQ);
4316429Svs195195 		fpsd.d_iteration = 0;
4326429Svs195195 		fpsd.d_interval = 0;
4336429Svs195195 		fpsd.d_fpuid_index = 0;
4346429Svs195195 		m_stat->m_num_on_fpuids = 0;
4356429Svs195195 		m_stat->m_cpuids_size = 0;
4366429Svs195195 		m_stat->total_iter = 0;
4376429Svs195195 		m_stat->m_reprobe = 0;
4386429Svs195195 		m_stat->m_num_cpus_to_test = 0;
4396429Svs195195 
4406429Svs195195 		if (NULL != fpsd.d_ignore_cpuid) {
4416429Svs195195 			free(fpsd.d_ignore_cpuid);
4426429Svs195195 		}
4436429Svs195195 	}
4446429Svs195195 
4456429Svs195195 	/*
4466429Svs195195 	 * Find number of online FPUs, and initialize
4476429Svs195195 	 * m_stat->m_num_on_fpuids. Then collect kstat
4486429Svs195195 	 * cpu_info for each.
4496429Svs195195 	 */
4506429Svs195195 
4517101Svs195195 	cpuid_list = (processorid_t *)malloc(m_stat->m_num_fpus *
4526429Svs195195 	    sizeof (processorid_t));
4536429Svs195195 	if (NULL == cpuid_list) {
4546429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_INFO, LIBRARY_CALL_FAIL,
4556429Svs195195 		    "malloc", strerror(errno));
4566429Svs195195 		return (-1);
4576429Svs195195 	}
4587346SVaidehi.Rangan@Sun.COM 	/* Initialize cpuid_list */
4597346SVaidehi.Rangan@Sun.COM 	for (i = 0; i < m_stat->m_num_fpus; i++) {
4607346SVaidehi.Rangan@Sun.COM 		cpuid_list[i] = -1;
4617346SVaidehi.Rangan@Sun.COM 	}
4626429Svs195195 
4636429Svs195195 	cpuid_index = 0;
4647101Svs195195 	for (i = 0; i < m_stat->m_max_cpuid; i++) {
4656429Svs195195 		if (p_online(i, P_STATUS) == P_ONLINE) {
4666429Svs195195 			cpuid_list[cpuid_index++] = i;
4676429Svs195195 		}
4687101Svs195195 		if (cpuid_index == total_onln) {
4696429Svs195195 			/* Break after all onln cpuids found */
4706429Svs195195 			break;
4716429Svs195195 		}
4726429Svs195195 	}
4737101Svs195195 	m_stat->m_num_on_fpuids = (uint_t)cpuid_index;
4747101Svs195195 	fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, NUM_ONLN_CPUS,
4757101Svs195195 	    m_stat->m_num_on_fpuids);
4766429Svs195195 
4776429Svs195195 	/*
4786429Svs195195 	 * Get cpu-brand info all valid cpuids using kstat.
4796429Svs195195 	 * This is needed to take care
4806429Svs195195 	 * of mixed cpu scenario
4816429Svs195195 	 */
4826429Svs195195 
4836429Svs195195 	kstat_ctl = kstat_open();
4846429Svs195195 	if (NULL == kstat_ctl) {
485*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_NO_EXIT, FPS_WARNING, LIBRARY_CALL_FAIL,
4866429Svs195195 		    "kstat_open", strerror(errno));
4876429Svs195195 		free(cpuid_list);
4886429Svs195195 		return (-1);
4896429Svs195195 	}
4906429Svs195195 
4916429Svs195195 
4926429Svs195195 	for (i = 0; i < m_stat->m_num_on_fpuids; i++) {
4936429Svs195195 
4946429Svs195195 		supported = 0;
4956429Svs195195 		fps_kstat = NULL;
4966429Svs195195 
4977346SVaidehi.Rangan@Sun.COM 		if ((cpuid_list[i] < 0) ||
4987346SVaidehi.Rangan@Sun.COM 		    (cpuid_list[i] >= m_stat->m_max_cpuid)) {
4997346SVaidehi.Rangan@Sun.COM 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
5007346SVaidehi.Rangan@Sun.COM 			    INVALID_CPUID, cpuid_list[i]);
5017346SVaidehi.Rangan@Sun.COM 			free(cpuid_list);
5027346SVaidehi.Rangan@Sun.COM 			return (-1);
5037346SVaidehi.Rangan@Sun.COM 		}
5046429Svs195195 		fps_kstat = kstat_lookup(kstat_ctl, "cpu_info",
5056429Svs195195 		    cpuid_list[i], NULL);
5066429Svs195195 		if (NULL == fps_kstat) {
5076429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
5086429Svs195195 			    LIBRARY_CALL_FAIL, "kstat_lookup",
5096429Svs195195 			    strerror(errno));
5107186Skk158166 			(void) kstat_close(kstat_ctl);
5116429Svs195195 			free(cpuid_list);
5126429Svs195195 			return (-1);
5136429Svs195195 		}
5146429Svs195195 		ret = kstat_read(kstat_ctl, fps_kstat, NULL);
5156429Svs195195 		if (ret != -1) {
5166429Svs195195 			kstat_cpu_name = kstat_data_lookup(fps_kstat,
5176429Svs195195 			    "brand");
5186429Svs195195 			if (NULL != kstat_cpu_name) {
5196429Svs195195 				cpu_brand = KSTAT_NAMED_STR_PTR(
5206429Svs195195 				    kstat_cpu_name);
5216429Svs195195 
5226429Svs195195 				supported = check_if_supported_CPU(
5236429Svs195195 				    cpu_brand, m_stat->m_machine);
5246429Svs195195 			}
5256429Svs195195 		} else {
5266429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
5276429Svs195195 			    CPU_BRAND_PROBE_FAIL, cpuid_list[i]);
5286429Svs195195 			(void) kstat_close(kstat_ctl);
5296429Svs195195 			free(cpuid_list);
5306429Svs195195 			return (-1);
5316429Svs195195 		}
5326429Svs195195 		if (!supported) {
5336429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
5346429Svs195195 			    CPU_NOT_SUPPORTED, cpu_brand,
5356429Svs195195 			    cpuid_list[i]);
5366429Svs195195 			m_stat->m_cpus[i].disable_test = 1;
5376429Svs195195 			(void) strcpy(m_stat->m_cpus[i].fptest_path, "");
5386429Svs195195 		} else {
5396429Svs195195 			m_stat->m_cpus[i].disable_test = 0;
5406429Svs195195 			m_stat->m_num_cpus_to_test++;
5416429Svs195195 			(void) strlcpy(m_stat->m_cpus[i].fptest_path,
5426429Svs195195 			    fps_tst_path,
5436429Svs195195 			    sizeof (m_stat->m_cpus[i].fptest_path));
5446429Svs195195 		}
5456429Svs195195 
5466429Svs195195 		/* Get frequency */
5476429Svs195195 
5486429Svs195195 		kstat_cpu_freq = kstat_data_lookup(fps_kstat,
5496429Svs195195 		    "clock_MHz");
5506429Svs195195 		if (NULL != kstat_cpu_freq) {
5516429Svs195195 			cpu_freq = (int)kstat_cpu_freq->value.l;
5526429Svs195195 		} else {
5536429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
5546429Svs195195 			    FREQ_PROBE_FAIL, cpuid_list[i]);
5557186Skk158166 			(void) kstat_close(kstat_ctl);
5566429Svs195195 			free(cpuid_list);
5576429Svs195195 			return (-1);
5586429Svs195195 		}
5596429Svs195195 
5606429Svs195195 		m_stat->m_cpus[i].cpuid = cpuid_list[i];
5616429Svs195195 		m_stat->m_cpus[i].frequency = cpu_freq;
5626429Svs195195 		(void) strncpy(m_stat->m_cpus[i].brand, cpu_brand,
5636429Svs195195 		    sizeof (m_stat->m_cpus[i].brand));
5646429Svs195195 		m_stat->m_cpus[i].num_failures = 0;
5656429Svs195195 
5666429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, CPU_INFO,
5676429Svs195195 		    cpuid_list[i], m_stat->m_cpus[i].brand,
5686429Svs195195 		    cpu_freq);
5696429Svs195195 	}
5706429Svs195195 	m_stat->m_cpuids_size = (int)m_stat->m_num_on_fpuids;
5716429Svs195195 	fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
5726429Svs195195 	    NUM_CPUS_2_TST, m_stat->m_cpuids_size);
5736429Svs195195 	free(cpuid_list);
5747186Skk158166 	(void) kstat_close(kstat_ctl);
5756429Svs195195 	if (m_stat->m_num_cpus_to_test <= 0) {
576*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
5776429Svs195195 		    FPSD_NO_CPUS_TO_TEST);
5786429Svs195195 		return (-1);
5796429Svs195195 	}
5806429Svs195195 	return (0);
5816429Svs195195 }
5826429Svs195195 
5836429Svs195195 /*
5846429Svs195195  * returns 1 if cpuid is found in the list of cpus to be
5856429Svs195195  * excluded from testing.
5866429Svs195195  */
5876429Svs195195 static int
ignore_cpu(int cpuid)5886429Svs195195 ignore_cpu(int cpuid)
5896429Svs195195 {
5906429Svs195195 	int found = 0;
5916429Svs195195 	int i;
5926429Svs195195 	processorid_t   *ignore_cpus = fpsd.d_ignore_cpuid;
5936429Svs195195 	for (i = 0; (i < fpsd.num_ignore_cpus) && (!found); i++) {
5946429Svs195195 		if (ignore_cpus[i] == cpuid) {
5956429Svs195195 			found = 1;
5966429Svs195195 		}
5976429Svs195195 	}
5986429Svs195195 	return (found);
5996429Svs195195 }
6006429Svs195195 
6016429Svs195195 /*
6027346SVaidehi.Rangan@Sun.COM  * This function checks if the string has contiguous valid
6037346SVaidehi.Rangan@Sun.COM  * digits. Leading and trailing blanks are O.K. Returns 0
6047346SVaidehi.Rangan@Sun.COM  * if string is not a valid integer and 1 if valid.
6057346SVaidehi.Rangan@Sun.COM  */
6067346SVaidehi.Rangan@Sun.COM 
6077346SVaidehi.Rangan@Sun.COM static int
valid_integer(char * cpu_str)6087346SVaidehi.Rangan@Sun.COM valid_integer(char *cpu_str)
6097346SVaidehi.Rangan@Sun.COM {
6107346SVaidehi.Rangan@Sun.COM 	char *tmp_str = cpu_str;
6117346SVaidehi.Rangan@Sun.COM 
6127346SVaidehi.Rangan@Sun.COM 	if ((NULL == cpu_str) || (strlen(cpu_str) == 0)) {
6137346SVaidehi.Rangan@Sun.COM 		return (0);
6147346SVaidehi.Rangan@Sun.COM 	}
6157346SVaidehi.Rangan@Sun.COM 	while (*tmp_str) {
6167346SVaidehi.Rangan@Sun.COM 		if (isblank(*tmp_str)) {
6177346SVaidehi.Rangan@Sun.COM 			tmp_str++;
6187346SVaidehi.Rangan@Sun.COM 		} else if (isdigit(*tmp_str)) {
6197346SVaidehi.Rangan@Sun.COM 			break;
6207346SVaidehi.Rangan@Sun.COM 		} else {
6217346SVaidehi.Rangan@Sun.COM 			return (0);
6227346SVaidehi.Rangan@Sun.COM 		}
6237346SVaidehi.Rangan@Sun.COM 	}
6247346SVaidehi.Rangan@Sun.COM 	if (!(*tmp_str)) {
6257346SVaidehi.Rangan@Sun.COM 		return (0);
6267346SVaidehi.Rangan@Sun.COM 	}
6277346SVaidehi.Rangan@Sun.COM 	while (*tmp_str) {
6287346SVaidehi.Rangan@Sun.COM 		if (isdigit(*tmp_str)) {
6297346SVaidehi.Rangan@Sun.COM 			tmp_str++;
6307346SVaidehi.Rangan@Sun.COM 		} else if (isblank(*tmp_str)) {
6317346SVaidehi.Rangan@Sun.COM 			break;
6327346SVaidehi.Rangan@Sun.COM 		} else
6337346SVaidehi.Rangan@Sun.COM 			return (0);
6347346SVaidehi.Rangan@Sun.COM 	}
6357346SVaidehi.Rangan@Sun.COM 	if (*tmp_str) {
6367346SVaidehi.Rangan@Sun.COM 		while (*tmp_str) {
6377346SVaidehi.Rangan@Sun.COM 			if (isblank(*tmp_str)) {
6387346SVaidehi.Rangan@Sun.COM 				tmp_str++;
6397346SVaidehi.Rangan@Sun.COM 			}
6407346SVaidehi.Rangan@Sun.COM 			else
6417346SVaidehi.Rangan@Sun.COM 				return (0);
6427346SVaidehi.Rangan@Sun.COM 		}
6437346SVaidehi.Rangan@Sun.COM 	}
6447346SVaidehi.Rangan@Sun.COM 	return (1);
6457346SVaidehi.Rangan@Sun.COM }
6467346SVaidehi.Rangan@Sun.COM 
6477346SVaidehi.Rangan@Sun.COM /*
6486429Svs195195  * This function parses the string of cpu-ids separated by
6496429Svs195195  * "," , constructs the list and disables testing on those
6506429Svs195195  * cpus. This function assumes fpsd_probe has been called and all
6516429Svs195195  * the machine config info is available in structure fpsd.
6526429Svs195195  */
6536429Svs195195 
6546429Svs195195 static int
parse_and_set_cpu_id_list(char * strCPUs)6556429Svs195195 parse_and_set_cpu_id_list(char *strCPUs)
6566429Svs195195 {
6576429Svs195195 	char *last;
6586429Svs195195 	int num_cpus = 0, invalid = 0;
6596429Svs195195 	int *tmp_cpus;
6606429Svs195195 	int num_cpus_to_test = 0;
6616429Svs195195 	int i;
6626429Svs195195 	int t_cpuid;
6636429Svs195195 	char *cpu_id;
6646429Svs195195 	static int first_time = 1;
6656429Svs195195 
6666429Svs195195 	tmp_cpus = (int *)malloc((int)fpsd.d_conf->m_num_fpus * sizeof (int));
6676429Svs195195 	if (NULL == tmp_cpus)
6686429Svs195195 		return (-1);
6696429Svs195195 	cpu_id = strtok_r(strCPUs, ",", &last);
6706429Svs195195 
6716429Svs195195 	while ((NULL != cpu_id) && (!invalid)) {
6727346SVaidehi.Rangan@Sun.COM 		if (valid_integer(cpu_id)) {
6736429Svs195195 			tmp_cpus[num_cpus++] =
6746429Svs195195 			    (int)strtol(cpu_id, (char **)NULL, 10);
6756429Svs195195 			cpu_id = strtok_r(NULL, ",", &last);
6766429Svs195195 		} else {
677*7435SVaidehi.Rangan@Sun.COM 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
6787346SVaidehi.Rangan@Sun.COM 			    INVAL_PROP_VALUE, cpu_id);
6796429Svs195195 			invalid = 1;
6806429Svs195195 		}
6817346SVaidehi.Rangan@Sun.COM 		if (num_cpus > fpsd.d_conf->m_num_fpus) {
6827101Svs195195 			/* More than max supported cpus */
683*7435SVaidehi.Rangan@Sun.COM 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
6846429Svs195195 			    INVAL_PROP_VALUE, strCPUs);
6856429Svs195195 			invalid = 1;
6866429Svs195195 		}
6876429Svs195195 	}
6887346SVaidehi.Rangan@Sun.COM 	if ((!invalid) && (num_cpus > 0)) {
6896429Svs195195 		fpsd.d_ignore_cpuid = (processorid_t *)malloc(
6906429Svs195195 		    sizeof (processorid_t) * (int) num_cpus);
6916429Svs195195 		if (NULL != fpsd.d_ignore_cpuid) {
6926429Svs195195 			for (i = 0; i < num_cpus; i++) {
6936429Svs195195 				fpsd.d_ignore_cpuid[i] = tmp_cpus[i];
6946429Svs195195 			}
6956429Svs195195 			fpsd.num_ignore_cpus = num_cpus;
6966429Svs195195 		} else {
6976429Svs195195 			fpsd.num_ignore_cpus = 0;
6986429Svs195195 		}
6997346SVaidehi.Rangan@Sun.COM 	} else {
7006429Svs195195 		fpsd.d_ignore_cpuid = NULL;
7016429Svs195195 		fpsd.num_ignore_cpus = 0;
7026429Svs195195 	}
7036429Svs195195 	free(tmp_cpus);
7046429Svs195195 	fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, NUM_IGN_CPUS,
7056429Svs195195 	    fpsd.num_ignore_cpus);
7066429Svs195195 	if ((fpsd.num_ignore_cpus > 0) && (fpsd.d_conf->m_cpuids_size > 0)) {
7076429Svs195195 		for (i = 0; i < fpsd.d_conf->m_cpuids_size; i++) {
7086429Svs195195 			t_cpuid = fpsd.d_conf->m_cpus[i].cpuid;
7096429Svs195195 			if (ignore_cpu(t_cpuid)) {
7106429Svs195195 				fpsd.d_conf->m_cpus[i].disable_test = 1;
7116429Svs195195 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
7126429Svs195195 				    IGN_CPUS, t_cpuid);
7136429Svs195195 			} else {
7146429Svs195195 				num_cpus_to_test++;
7156429Svs195195 			}
7166429Svs195195 		}
7176429Svs195195 		fpsd.d_conf->m_num_cpus_to_test = num_cpus_to_test;
7186429Svs195195 		if (num_cpus_to_test <= 0)  {
7196429Svs195195 			if (1 == first_time) {
720*7435SVaidehi.Rangan@Sun.COM 				fpsd_message(FPSD_NO_EXIT, FPS_INFO,
7216429Svs195195 				    ALL_CPUS_EXCLDED);
7226429Svs195195 				first_time = 0;
7236429Svs195195 			} else {
724*7435SVaidehi.Rangan@Sun.COM 				fpsd_message(FPSD_NO_EXIT, FPS_INFO,
7256429Svs195195 				    ALL_CPUS_EXCLDED);
7266429Svs195195 			}
7276429Svs195195 			return (NO_CPUS_2_TEST);
7286429Svs195195 		}
7296429Svs195195 	}
7306429Svs195195 	first_time = 1;
7316429Svs195195 	return (0);
7326429Svs195195 }
7336429Svs195195 
7346429Svs195195 #define	CLEAN_UP_SCF_STUFF	{	\
7356429Svs195195 	if (scf_handle_p) {	\
7367186Skk158166 		(void) scf_handle_unbind(scf_handle_p);	\
7376429Svs195195 		scf_handle_destroy(scf_handle_p);	\
7386429Svs195195 	}	\
7396429Svs195195 	if (inst)	\
7406429Svs195195 		scf_instance_destroy(inst);	\
7416429Svs195195 	if (pg)	\
7426429Svs195195 		scf_pg_destroy(pg);	\
7436429Svs195195 	if (scf_prop_p)	\
7446429Svs195195 		scf_property_destroy(scf_prop_p);	\
7456429Svs195195 	if (value)	\
7466429Svs195195 		scf_value_destroy(value);	\
7477346SVaidehi.Rangan@Sun.COM 	if (scf_snapshot_p)	\
7487346SVaidehi.Rangan@Sun.COM 		scf_snapshot_destroy(scf_snapshot_p);	\
7496429Svs195195 }
7506429Svs195195 
7516429Svs195195 /* Read properties from SMF configuration repository using libscf APIs */
7526429Svs195195 
7536429Svs195195 static int
read_conf_props()7546429Svs195195 read_conf_props()
7556429Svs195195 {
7566429Svs195195 	scf_handle_t *scf_handle_p;
7576429Svs195195 	scf_property_t *scf_prop_p = NULL;
7586429Svs195195 	scf_instance_t *inst = NULL;
7596429Svs195195 	scf_propertygroup_t *pg = NULL;
7606429Svs195195 	scf_value_t	*value = NULL;
7616429Svs195195 	int ret_val = -1;
7626429Svs195195 	int val;
7636429Svs195195 	int64_t intvl;
7646429Svs195195 	int name_len;
7656429Svs195195 	char *strCPUs;
7667346SVaidehi.Rangan@Sun.COM 	scf_snapshot_t *scf_snapshot_p = NULL;
7676429Svs195195 
7686429Svs195195 	scf_handle_p = scf_handle_create(SCF_VERSION);
7696429Svs195195 	if ((NULL != scf_handle_p) && (NULL != str_fps_fmri)) {
7706429Svs195195 		if (scf_handle_bind(scf_handle_p) != -1) {
7716429Svs195195 			inst = scf_instance_create(scf_handle_p);
7726429Svs195195 			pg = scf_pg_create(scf_handle_p);
7736429Svs195195 			scf_prop_p = scf_property_create(scf_handle_p);
7746429Svs195195 			if ((NULL == inst) || (NULL == pg) ||
7756429Svs195195 			    (NULL == scf_prop_p)) {
7766429Svs195195 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
7776429Svs195195 				    CREATE_FAIL,
7786429Svs195195 				    scf_strerror(scf_error()));
7796429Svs195195 				CLEAN_UP_SCF_STUFF
7806429Svs195195 				return (-1);
7816429Svs195195 			}
7826429Svs195195 			val = scf_handle_decode_fmri(scf_handle_p,
7836429Svs195195 			    str_fps_fmri,
7846429Svs195195 			    NULL, NULL, inst, pg, scf_prop_p, 0);
7856429Svs195195 			if (val != 0) {
7866429Svs195195 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
7876429Svs195195 				    HANDLE_DECODE_FAIL,
7886429Svs195195 				    scf_strerror(scf_error()));
7896429Svs195195 				CLEAN_UP_SCF_STUFF
7906429Svs195195 				return (-1);
7916429Svs195195 			}
7927346SVaidehi.Rangan@Sun.COM 			scf_snapshot_p = scf_snapshot_create(scf_handle_p);
7937346SVaidehi.Rangan@Sun.COM 			if (NULL == scf_snapshot_p) {
7947346SVaidehi.Rangan@Sun.COM 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
7957346SVaidehi.Rangan@Sun.COM 				    SNAPSHOT_CREAT_FAIL,
7967346SVaidehi.Rangan@Sun.COM 				    scf_strerror(scf_error()));
7977346SVaidehi.Rangan@Sun.COM 				CLEAN_UP_SCF_STUFF
7987346SVaidehi.Rangan@Sun.COM 				return (-1);
7997346SVaidehi.Rangan@Sun.COM 			}
8007346SVaidehi.Rangan@Sun.COM 			val = scf_instance_get_snapshot(inst,
8017346SVaidehi.Rangan@Sun.COM 			    SMF_SNAPSHOT_RUNNING, scf_snapshot_p);
8027346SVaidehi.Rangan@Sun.COM 			if (val == -1) {
8037346SVaidehi.Rangan@Sun.COM 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
8047346SVaidehi.Rangan@Sun.COM 				    INST_SNAPSHOT_GET_FAIL,
8057346SVaidehi.Rangan@Sun.COM 				    scf_strerror(scf_error()));
8067346SVaidehi.Rangan@Sun.COM 				CLEAN_UP_SCF_STUFF
8077346SVaidehi.Rangan@Sun.COM 				return (-1);
8087346SVaidehi.Rangan@Sun.COM 			}
8097346SVaidehi.Rangan@Sun.COM 			val = scf_instance_get_pg_composed(inst, scf_snapshot_p,
8106429Svs195195 			    SMF_FPS_PROP_GRP_NAME, pg);
8116429Svs195195 			if (val != 0) {
8126429Svs195195 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
8136429Svs195195 				    INSTANCE_PG_GET_FAIL,
8146429Svs195195 				    scf_strerror(scf_error()));
8156429Svs195195 				CLEAN_UP_SCF_STUFF
8166429Svs195195 				return (-1);
8176429Svs195195 			}
8186429Svs195195 			val = scf_pg_get_property(pg, SMF_PROP_INTVL,
8196429Svs195195 			    scf_prop_p);
8206429Svs195195 			/* Read interval property if defined */
8216429Svs195195 			if (val == 0) {
8226429Svs195195 				value = scf_value_create(scf_handle_p);
8237346SVaidehi.Rangan@Sun.COM 				if (NULL != value) {
8247346SVaidehi.Rangan@Sun.COM 					val = scf_property_get_value(scf_prop_p,
8257346SVaidehi.Rangan@Sun.COM 					    value);
8267346SVaidehi.Rangan@Sun.COM 					if (0 == val) {
8277346SVaidehi.Rangan@Sun.COM 						val =
8287346SVaidehi.Rangan@Sun.COM 						    scf_value_get_integer(value,
8297346SVaidehi.Rangan@Sun.COM 						    &intvl);
8307346SVaidehi.Rangan@Sun.COM 						if ((0 == val) && (intvl > 0)) {
8317346SVaidehi.Rangan@Sun.COM 							fpsd.d_interval =
8327346SVaidehi.Rangan@Sun.COM 							    (int)intvl;
8337346SVaidehi.Rangan@Sun.COM 							fpsd_message(
8347346SVaidehi.Rangan@Sun.COM 							    FPSD_NO_EXIT,
8357346SVaidehi.Rangan@Sun.COM 							    FPS_DEBUG,
8367346SVaidehi.Rangan@Sun.COM 							    INTVL_VAL, intvl);
8377346SVaidehi.Rangan@Sun.COM 							ret_val = 0;
8387346SVaidehi.Rangan@Sun.COM 						}
8397346SVaidehi.Rangan@Sun.COM 					}
8406429Svs195195 				}
8416429Svs195195 			} else {
8426429Svs195195 				fpsd_message(FPSD_NO_EXIT, FPS_INFO,
8436429Svs195195 				    PROP_UNDEFINED, SMF_PROP_INTVL,
8446429Svs195195 				    scf_strerror(scf_error()));
8456429Svs195195 			}
8466429Svs195195 			/*
8476429Svs195195 			 * Read property "exclude_cpus" if defined - this is
8486429Svs195195 			 * the array of cpu-ids to be excluded from testing.
8496429Svs195195 			 */
8506429Svs195195 			val = scf_pg_get_property(pg, SMF_PROP_EXCLD_CPUS,
8516429Svs195195 			    scf_prop_p);
8526429Svs195195 			if (val == 0) {
8536429Svs195195 				val = scf_property_get_value(scf_prop_p, value);
8547346SVaidehi.Rangan@Sun.COM 				if (0 == val) {
8557346SVaidehi.Rangan@Sun.COM 					name_len =
8567346SVaidehi.Rangan@Sun.COM 					    scf_limit(
8577346SVaidehi.Rangan@Sun.COM 					    SCF_LIMIT_MAX_NAME_LENGTH);
8587346SVaidehi.Rangan@Sun.COM 					strCPUs = malloc(name_len +1);
8597346SVaidehi.Rangan@Sun.COM 					if (NULL == strCPUs) {
8607346SVaidehi.Rangan@Sun.COM 						fpsd_message(FPSD_NO_EXIT,
8617346SVaidehi.Rangan@Sun.COM 						    FPS_DEBUG,
8627346SVaidehi.Rangan@Sun.COM 						    LIBRARY_CALL_FAIL,
8637346SVaidehi.Rangan@Sun.COM 						    "malloc");
8647346SVaidehi.Rangan@Sun.COM 						CLEAN_UP_SCF_STUFF
8657346SVaidehi.Rangan@Sun.COM 						return (-1);
8667346SVaidehi.Rangan@Sun.COM 					}
8677346SVaidehi.Rangan@Sun.COM 					val = scf_value_get_astring(value,
8687346SVaidehi.Rangan@Sun.COM 					    strCPUs, name_len+1);
8697346SVaidehi.Rangan@Sun.COM 					if ((val != -1) &&
8707346SVaidehi.Rangan@Sun.COM 					    (strlen(strCPUs) > 0)) {
8717346SVaidehi.Rangan@Sun.COM 						fpsd_message(FPSD_NO_EXIT,
8727346SVaidehi.Rangan@Sun.COM 						    FPS_DEBUG,
8737346SVaidehi.Rangan@Sun.COM 						    EXCL_CPUS, strCPUs);
8747346SVaidehi.Rangan@Sun.COM 						ret_val =
8757346SVaidehi.Rangan@Sun.COM 						    parse_and_set_cpu_id_list(
8767346SVaidehi.Rangan@Sun.COM 						    strCPUs);
8777346SVaidehi.Rangan@Sun.COM 					}
8787346SVaidehi.Rangan@Sun.COM 					free(strCPUs);
8796429Svs195195 				}
8806429Svs195195 			} else {
8816429Svs195195 				fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
8826429Svs195195 				    PROP_UNDEFINED,
8836429Svs195195 				    SMF_PROP_EXCLD_CPUS,
8846429Svs195195 				    scf_strerror(scf_error()));
8856429Svs195195 			}
8866429Svs195195 		}
8876429Svs195195 	}
8886429Svs195195 
8896429Svs195195 	/* Clean up */
8906429Svs195195 
8916429Svs195195 	CLEAN_UP_SCF_STUFF
8926429Svs195195 	return (ret_val);
8936429Svs195195 }
8946429Svs195195 
8957346SVaidehi.Rangan@Sun.COM static int
fpsd_init()8967346SVaidehi.Rangan@Sun.COM fpsd_init()
8977346SVaidehi.Rangan@Sun.COM {
8986429Svs195195 	mach_conf_t *m_conf_p;
8996429Svs195195 
9006429Svs195195 	debug_level = DFLT_DBG_LVL;
9016429Svs195195 	fpsd.d_fg = 0;
9026429Svs195195 	fpsd.d_daemon = 0;
9036429Svs195195 	fpsd.d_ignore_cpuid = NULL;
9046429Svs195195 	fpsd.d_iteration = 0;
9056429Svs195195 	fpsd.d_interval = 0;
9066429Svs195195 	fpsd.d_fpuid_index = 0;
9076429Svs195195 	fpsd.d_rootdir = "/";
9086429Svs195195 	fpsd.d_pid = getpid();
9096429Svs195195 	fpsd.d_conf = &fpsd_conf;
9106429Svs195195 	fpsd.d_ts_hup = 0;
9116429Svs195195 
9126429Svs195195 	m_conf_p = fpsd.d_conf;
9136429Svs195195 	m_conf_p->m_machine[0] = '\0';
9146429Svs195195 	m_conf_p->m_num_on_fpuids = 0;
9156429Svs195195 	m_conf_p->m_cpuids_size = 0;
9166429Svs195195 	m_conf_p->total_iter = 0;
9176429Svs195195 	m_conf_p->m_reprobe = 0;
9186429Svs195195 	m_conf_p->m_num_cpus_to_test = 0;
9197101Svs195195 	m_conf_p->m_num_fpus = (uint_t)sysconf(_SC_NPROCESSORS_MAX);
9206429Svs195195 
9217346SVaidehi.Rangan@Sun.COM 	(void) pthread_mutex_init(&log_mutex, NULL);
9226429Svs195195 
9237101Svs195195 	m_conf_p->m_max_cpuid = (int)sysconf(_SC_CPUID_MAX) + 1;
9246429Svs195195 
9256429Svs195195 	/*
9266429Svs195195 	 * Allocate enough memory to accomodate maximum number of CPUs
9276429Svs195195 	 * supported by this platform.
9286429Svs195195 	 */
9296429Svs195195 	m_conf_p->m_cpus = malloc(sizeof (fps_cpu_t) *
9307346SVaidehi.Rangan@Sun.COM 	    m_conf_p->m_num_fpus);
9316429Svs195195 	if (NULL == m_conf_p->m_cpus)
9326429Svs195195 		return (1);
9336429Svs195195 	else
9346429Svs195195 		return (0);
9356429Svs195195 
9366429Svs195195 }
9376429Svs195195 
9386429Svs195195 static void
fpsd_fini()9397346SVaidehi.Rangan@Sun.COM fpsd_fini()
9407346SVaidehi.Rangan@Sun.COM {
9416429Svs195195 	if (fpsd.d_ignore_cpuid)
9426429Svs195195 		free(fpsd.d_ignore_cpuid);
9436429Svs195195 	if (fpsd.d_conf->m_cpus)
9446429Svs195195 		free(fpsd.d_conf->m_cpus);
9456429Svs195195 }
9466429Svs195195 
9476429Svs195195 static int
fpsd_probe_config()9486429Svs195195 fpsd_probe_config()
9496429Svs195195 {
9506429Svs195195 	int smf_invoked = 0;
9516429Svs195195 	int ret = 0;
9526429Svs195195 
9536429Svs195195 	/*
9546429Svs195195 	 * Use smf_get_state to get the status of the service to see
9556429Svs195195 	 * if the status is "online" by now. If so, read the proper-
9566429Svs195195 	 * ties defined using SCF.
9576429Svs195195 	 */
9586429Svs195195 
9596429Svs195195 	if (NULL != str_fps_fmri) {
9607346SVaidehi.Rangan@Sun.COM 		smf_invoked = 1;
9616429Svs195195 
9627346SVaidehi.Rangan@Sun.COM 		/* Read SMF properties if invoked thro' SMF */
9637346SVaidehi.Rangan@Sun.COM 		ret = read_conf_props();
9647346SVaidehi.Rangan@Sun.COM 		if (ret == NO_CPUS_2_TEST) {
9657346SVaidehi.Rangan@Sun.COM 			return (ret);
9666429Svs195195 		}
9676429Svs195195 	}
9686429Svs195195 	calculateTotalIterations(fpsd.d_conf);
9696429Svs195195 	if ((ret == -1) || (!smf_invoked) || (fpsd.d_interval <= 0)) {
9706429Svs195195 		ret = calculateTimeInterval();
9716429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
9726429Svs195195 		    PRINT_INTVL, fpsd.d_interval);
9736429Svs195195 		if ((ret != 1) || (fpsd.d_interval <= 0)) {
9746429Svs195195 			return (ZERO_INTERVAL);
9756429Svs195195 		}
9766429Svs195195 	}
9776429Svs195195 	return (0);
9786429Svs195195 }
9796429Svs195195 
9806429Svs195195 int
main(int argc,char ** argv)9816429Svs195195 main(int argc, char **argv)
9826429Svs195195 {
9836429Svs195195 
9846429Svs195195 	int sig;
9856429Svs195195 	sigset_t  sigs;
9866429Svs195195 	/* Pipe fd to write the status back to parent after becoming daemon */
9876429Svs195195 	int pfd = -1;
9886429Svs195195 	int status = FPSD_INIT_SUCCESS;
9896429Svs195195 	char rcvsigstr[32];
9906429Svs195195 	int c;
9916429Svs195195 	int ret;
9926429Svs195195 	struct rlimit rlim;
9936429Svs195195 	char path[MAXPATHLEN];
9946429Svs195195 	int probe_status = -1;
9956429Svs195195 	const char *progname;
9966429Svs195195 	struct	sigaction	act;
9976429Svs195195 
9986429Svs195195 	progname = strrchr(argv[0], '/');
9996429Svs195195 	if (NULL != progname)
10006429Svs195195 		progname++;
10016429Svs195195 	else
10026429Svs195195 		progname = argv[0];
10036429Svs195195 
10046429Svs195195 #ifndef TEXT_DOMAIN		/* Should be defined via Makefile */
10056429Svs195195 #define	TEXT_DOMAIN  "SUNW_FPS"
10066429Svs195195 #endif
10076429Svs195195 
10086429Svs195195 	(void) setlocale(LC_ALL, "");
10096429Svs195195 	(void) textdomain(TEXT_DOMAIN);
10106429Svs195195 
10116429Svs195195 	openlog(FPS_DAEMON_NAME, LOG_PID, LOG_DAEMON);
10126429Svs195195 
10136429Svs195195 	if (fpsd_init()) {
10146429Svs195195 		fpsd_message(FPSD_EXIT_ERROR, FPS_ERROR, DAEMON_INIT_FAIL);
10156429Svs195195 	}
10166429Svs195195 
10176429Svs195195 	/*
10186429Svs195195 	 * Set our per-process core file path to leave core files in
10196429Svs195195 	 * var/fps/core directory, named after the PID to aid in
10206429Svs195195 	 * debugging, and make sure that there is no restriction on core
10216429Svs195195 	 * file size.
10226429Svs195195 	 */
10236429Svs195195 
10246429Svs195195 	if ((ret = access(FPS_CORE_DIR, W_OK)) != 0) {
10256429Svs195195 		if ((ret = mkdirp(FPS_CORE_DIR, 0755)) != 0) {
10266429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_ERROR,
10276429Svs195195 			    CORE_DIR_CREATION_FAILED,
10286429Svs195195 			    FPS_CORE_DIR, strerror(errno));
10296429Svs195195 		}
10306429Svs195195 	}
10316429Svs195195 
10326429Svs195195 	if (ret == 0) {
10336429Svs195195 		(void) snprintf(path, sizeof (path), "%s/core.%s.%%p",
10346429Svs195195 		    FPS_CORE_DIR, progname);
10356429Svs195195 		(void) core_set_process_path(path, strlen(path) + 1,
10366429Svs195195 		    fpsd.d_pid);
10376429Svs195195 		rlim.rlim_cur = RLIM_INFINITY;
10386429Svs195195 		rlim.rlim_max = RLIM_INFINITY;
10396429Svs195195 
10406429Svs195195 		(void) setrlimit(RLIMIT_CORE, &rlim);
10416429Svs195195 	}
10426429Svs195195 
10436429Svs195195 
10446429Svs195195 	/*  parse arguments */
10456429Svs195195 	while ((c = getopt(argc, argv, "dl:")) != EOF) {
10466429Svs195195 		switch (c) {
10476429Svs195195 		case 'd':
10486429Svs195195 			fpsd.d_fg = 1;
10496429Svs195195 			break;
10506429Svs195195 
10516429Svs195195 		case 'l':
10526429Svs195195 			debug_level = atoi(optarg);
10536429Svs195195 			if (debug_level < 0)
10546429Svs195195 				debug_level = DFLT_DBG_LVL;
10556429Svs195195 			break;
10566429Svs195195 
10576429Svs195195 		default:
10586429Svs195195 			fpsd_message(FPSD_EXIT_USAGE, FPS_ERROR, USAGE_MSG,
10596429Svs195195 			    progname);
10606429Svs195195 			break;
10616429Svs195195 		}
10626429Svs195195 	}
10636429Svs195195 
10646429Svs195195 
10656429Svs195195 	/*
10666429Svs195195 	 * Reset all of our privilege sets to the minimum set of required
10676429Svs195195 	 * privileges.  We continue to run as root so that files we create
10686429Svs195195 	 * such as logs and checkpoints are secured in the /var
10696429Svs195195 	 * filesystem.
10706429Svs195195 	 */
10716429Svs195195 	if (__init_daemon_priv(PU_RESETGROUPS | PU_LIMITPRIVS | PU_INHERITPRIVS,
10726429Svs195195 	    0, 0, /* run as uid 0 and gid 0 */
10736429Svs195195 	    PRIV_FILE_DAC_EXECUTE, PRIV_FILE_DAC_READ, PRIV_FILE_DAC_SEARCH,
10746429Svs195195 	    PRIV_FILE_DAC_WRITE, PRIV_FILE_OWNER, PRIV_PROC_OWNER,
10756429Svs195195 	    PRIV_PROC_PRIOCNTL, PRIV_SYS_ADMIN, PRIV_SYS_CONFIG,
10766429Svs195195 	    PRIV_SYS_DEVICES, PRIV_SYS_RES_CONFIG,
10776429Svs195195 	    PRIV_NET_PRIVADDR, NULL) != 0) {
10786429Svs195195 
10796429Svs195195 		(void) fpsd_message(FPSD_EXIT_ERROR, FPS_ERROR,
10806429Svs195195 		    INSUFFICIENT_PRIVS, progname);
10816429Svs195195 	}
10826429Svs195195 
10836429Svs195195 
10846429Svs195195 	if (!fpsd.d_fg) {   /* Now become daemon */
10856429Svs195195 		pfd = become_daemon_init();
10866429Svs195195 	} else {
10876429Svs195195 		(void) chdir(FPS_DIR);
10886429Svs195195 	}
10896429Svs195195 
10906429Svs195195 	if (daemon_exists()) {
10916429Svs195195 		/*
10926429Svs195195 		 * If another instance of fpsd daemon is already running;
10936429Svs195195 		 * exit. Should not clean up door file
10946429Svs195195 		 */
10956429Svs195195 		fpsd_message(FPSD_EXIT_ERROR, FPS_ERROR,
10966429Svs195195 		    DAEMON_ALREADY_RUNNING);
10976429Svs195195 	}
10986429Svs195195 
10996429Svs195195 	/*
11006429Svs195195 	 * Setup door prevents any more instances of fpsd from running.
11016429Svs195195 	 */
11026429Svs195195 	if (fps_setup_door() == -1) {
11036429Svs195195 		fpsd_message(FPSD_EXIT_ERROR, FPS_ERROR, DOOR_SETUP_FAIL);
11046429Svs195195 	}
11056429Svs195195 
11066429Svs195195 	/*
11076429Svs195195 	 * Some desktop platforms satisfy E* guidelines. Here CPU power
11086429Svs195195 	 * management is enabled by default. The scheduling algorithms
11096429Svs195195 	 * change on these platforms to not to do testing on idle system
11106429Svs195195 	 * to save power.
11116429Svs195195 	 */
11126429Svs195195 	init_estar_db();    /* Initialize Estar config data base */
11136429Svs195195 	/* Print message on CPU E* enabled system */
11146429Svs195195 	if (is_estar_system)
11156429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, ESTAR_INFO);
11166429Svs195195 
11176429Svs195195 	if ((probe_status = fpsd_probe(fpsd.d_conf)) != 0) {
1118*7435SVaidehi.Rangan@Sun.COM 		(void) fpsd_message(FPSD_NO_EXIT, FPS_DEBUG,
11196429Svs195195 		    UNSUPPORTED_SYSTEM);
11206429Svs195195 	}
11216429Svs195195 
11226429Svs195195 	if (!fpsd.d_fg) {   /* Complete daemonize proces */
11236429Svs195195 
11246429Svs195195 		fpsd.d_daemon = 1;
11256429Svs195195 		/*
11266429Svs195195 		 * Now that we're running, if a pipe fd was specified, write an
11276429Svs195195 		 * exit status to it to indicate that our parent process can
11286429Svs195195 		 * safely detach.
11296429Svs195195 		 */
11306429Svs195195 		if (pfd >= 0) {
11316429Svs195195 			(void) write(pfd, &status, sizeof (status));
11326429Svs195195 		}
11336429Svs195195 		become_daemon_fini(pfd);
11346429Svs195195 
11356429Svs195195 	} else {
11366429Svs195195 		/*
11376429Svs195195 		 * Mask all signals before creating sched thread. We will
11386429Svs195195 		 * unmask selective siganls from main thread. This ensures
11396429Svs195195 		 * that only main thread handles signals. This is done in
11406429Svs195195 		 * become_daemon() if we had to daemonize.
11416429Svs195195 		 */
11426429Svs195195 
11436429Svs195195 		(void) sigfillset(&sigs);
11446429Svs195195 		(void) sigprocmask(SIG_BLOCK, &sigs, NULL);
11456429Svs195195 	}
11466429Svs195195 
11476429Svs195195 	/*
11486429Svs195195 	 * Give some time for SMF to read the exit status
11496429Svs195195 	 * of parent and update fpsd fmri state
11506429Svs195195 	 */
11516429Svs195195 	(void) poll(NULL, 0, 3*1000);
11526429Svs195195 
11536429Svs195195 	str_fps_fmri = getenv("SMF_FMRI");
11546429Svs195195 	if (NULL != str_fps_fmri) {
11556429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, SMF_INVKD, str_fps_fmri);
11566429Svs195195 	} else {
11576429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, CLI_INVKD);
11586429Svs195195 	}
11596429Svs195195 
11606429Svs195195 	if (probe_status != 0) {
11616429Svs195195 		/* Exit child proces too */
11626429Svs195195 
11636429Svs195195 		if (NULL != str_fps_fmri) {
11647346SVaidehi.Rangan@Sun.COM 			const char *smf_state;
11657346SVaidehi.Rangan@Sun.COM 			ret =  smf_disable_instance(str_fps_fmri,
11667346SVaidehi.Rangan@Sun.COM 			    SMF_TEMPORARY);
11677346SVaidehi.Rangan@Sun.COM 			if (0 == ret) {
11687346SVaidehi.Rangan@Sun.COM 				(void) fpsd_message(FPSD_NO_EXIT,
1169*7435SVaidehi.Rangan@Sun.COM 				    FPS_DEBUG, FPSD_STATE);
11707346SVaidehi.Rangan@Sun.COM 			} else {
11717346SVaidehi.Rangan@Sun.COM 				/* Unable to disable the service. */
11727346SVaidehi.Rangan@Sun.COM 				smf_state = smf_get_state(str_fps_fmri);
11737346SVaidehi.Rangan@Sun.COM 				if (NULL == smf_state) {
11747346SVaidehi.Rangan@Sun.COM 					smf_state = " ";
11757346SVaidehi.Rangan@Sun.COM 					(void) fpsd_message(FPSD_NO_EXIT,
11767346SVaidehi.Rangan@Sun.COM 					    FPS_ERROR, DISABLE_SVC_FAILED,
11777346SVaidehi.Rangan@Sun.COM 					    smf_state);
11787346SVaidehi.Rangan@Sun.COM 				}
11796429Svs195195 				(void) poll(NULL, 0, 3*1000);
11806429Svs195195 			}
11816429Svs195195 		}
11826429Svs195195 		terminate_process();
11836429Svs195195 		_exit(FPSD_EXIT_ERROR);
11846429Svs195195 	}
11856429Svs195195 
11866429Svs195195 	act.sa_sigaction = sig_hup_handler;
11876429Svs195195 	(void) sigemptyset(&act.sa_mask);
11886429Svs195195 	act.sa_flags = SA_SIGINFO;
11896429Svs195195 	(void) sigaction(SIGHUP, &act, NULL);
11906429Svs195195 	fpsd_read_config();
11917346SVaidehi.Rangan@Sun.COM 	(void) sigfillset(&sigs);
11927346SVaidehi.Rangan@Sun.COM 	(void) sigprocmask(SIG_BLOCK, &sigs, NULL);
11936429Svs195195 
11946429Svs195195 	/*
11956429Svs195195 	 * On estar-systems, if interval < MIN_INTERVAL, scheduling tests will
11966429Svs195195 	 * reset the idle counter and prevent system from going to sleep.
11976429Svs195195 	 * To  avoid this, setting interval to MIN_INTERVAL.
11986429Svs195195 	 */
11996429Svs195195 
12006429Svs195195 	if ((is_estar_system) && (fpsd.d_interval < MIN_INTERVAL)) {
12016429Svs195195 		fpsd.d_interval = MIN_INTERVAL;
12026429Svs195195 		fpsd_message(FPSD_NO_EXIT, FPS_DEBUG, MIN_INTERVAL_MSG,
12036429Svs195195 		    fpsd.d_interval, MIN_INTERVAL);
12046429Svs195195 	}
12056429Svs195195 
12066429Svs195195 	/* Run scheduling thread */
12076429Svs195195 	if ((ret == 0) && thr_create(NULL, 0,
12086429Svs195195 	    test_fpu_thr, (void *) NULL, THR_BOUND, NULL) != 0) {
1209*7435SVaidehi.Rangan@Sun.COM 		fpsd_message(FPSD_EXIT_ERROR, FPS_WARNING, THR_CREATION_FAIL);
12106429Svs195195 	}
12116429Svs195195 
12126429Svs195195 	/*
12136429Svs195195 	 * We unmask selective signals here. Besides terminating on
12146429Svs195195 	 * SIGINT & SIGTERM, we handle SIGHUP that is used to cause
12156429Svs195195 	 * daemon to re-read the SMF properties.
12166429Svs195195 	 */
12176429Svs195195 	(void) sigemptyset(&sigs);
12186429Svs195195 	(void) sigaddset(&sigs, SIGINT);
12196429Svs195195 	(void) sigaddset(&sigs, SIGTERM);
12206429Svs195195 	(void) sigaddset(&sigs, SIGHUP);
12216429Svs195195 	(void) sigprocmask(SIG_UNBLOCK, &sigs, NULL);
12226429Svs195195 
12236429Svs195195 	for (;;) {
12246429Svs195195 		(void) sigwait(&sigs, &sig);
12256429Svs195195 		(void) sig2str(sig, rcvsigstr);
12266429Svs195195 
12276429Svs195195 		if (sig != -1) {
12286429Svs195195 			fpsd_message(FPSD_NO_EXIT, FPS_INFO,
12296429Svs195195 			    SIGNAL_INFO, rcvsigstr, sig);
12306429Svs195195 			switch (sig) {
12316429Svs195195 				case SIGINT:
12326429Svs195195 				case SIGTERM:
12336429Svs195195 					terminate_process();
12346429Svs195195 					_exit(FPSD_EXIT_ERROR);
12356429Svs195195 					break;
12366429Svs195195 				case SIGHUP:
12376429Svs195195 					fpsd.d_ts_hup = gethrtime();
12386429Svs195195 					break;
12396429Svs195195 				default: break;
12406429Svs195195 			}
12416429Svs195195 		}
12426429Svs195195 	}
12436429Svs195195 #pragma error_messages(off, E_STATEMENT_NOT_REACHED)
12446429Svs195195 	/* NOTREACHED */
12456429Svs195195 	return (0);
12466429Svs195195 }
1247