Files
org-hyperion-cules/impl.c
Matt Zimmerman 5c5cb3e702 Don't try to set SA_NODEFER if it doesn't exist on the target architecture.
git-svn-id: file:///home/jj/hercules.svn/trunk@912 956126f8-22a0-4046-8f4a-272fa8102e63
2002-06-14 14:23:42 +00:00

267 lines
7.9 KiB
C

/* IMPL.C (c) Copyright Roger Bowler, 1999-2002 */
/* Hercules Initialization Module */
/*-------------------------------------------------------------------*/
/* This module initializes the Hercules S/370 or ESA/390 emulator. */
/* It builds the system configuration blocks, creates threads for */
/* central processors, HTTP server */
/* and activates the control panel which runs under the main thread. */
/*-------------------------------------------------------------------*/
#include "hercules.h"
#include "opcode.h"
#include "httpmisc.h"
#include "hostinfo.h"
#if defined(FISH_HANG)
extern int bFishHangAtExit; // (set to true when shutting down)
extern void FishHangInit(char* pszFileCreated, int nLineCreated);
extern void FishHangReport();
extern void FishHangAtExit();
#endif // defined(FISH_HANG)
/*-------------------------------------------------------------------*/
/* Signal handler for SIGINT signal */
/*-------------------------------------------------------------------*/
static void sigint_handler (int signo)
{
// logmsg ("config: sigint handler entered for thread %lu\n",/*debug*/
// thread_id()); /*debug*/
signal(SIGINT, sigint_handler);
/* Ignore signal unless presented on console thread */
if (thread_id() != sysblk.cnsltid)
return;
/* Exit if previous SIGINT request was not actioned */
if (sysblk.sigintreq)
{
/* Release the configuration */
release_config();
exit(1);
}
/* Set SIGINT request pending flag */
sysblk.sigintreq = 1;
/* Activate instruction stepping */
sysblk.inststep = 1;
ON_IC_TRACE;
return;
} /* end function sigint_handler */
#if !defined(NO_SIGABEND_HANDLER)
static void watchdog_thread()
{
S64 savecount[MAX_CPU_ENGINES];
int i;
#ifndef WIN32
/* Set watchdog priority just below cpu priority
such that it will not invalidly detect an
inoperable cpu */
if(sysblk.cpuprio >= 0)
setpriority(PRIO_PROCESS, 0, sysblk.cpuprio+1);
#endif
while(1)
{
#ifdef FEATURE_CPU_RECONFIG
for (i = 0; i < MAX_CPU_ENGINES; i++)
#else /*!FEATURE_CPU_RECONFIG*/
for (i = 0; i < sysblk.numcpu; i++)
#endif /*!FEATURE_CPU_RECONFIG*/
{
if(sysblk.regs[i].cpustate == CPUSTATE_STARTED
&& !sysblk.regs[i].psw.wait)
{
/* If the cpu is running but not executing
instructions then it must be malfunctioning */
if(sysblk.regs[i].instcount == savecount[i])
{
if(!try_obtain_lock(&sysblk.intlock))
{
/* Send signal to looping CPU */
signal_thread(sysblk.regs[i].cputid, SIGUSR1);
savecount[i] = -1;
release_lock(&sysblk.intlock);
}
}
else
/* Save current instcount */
savecount[i] = sysblk.regs[i].instcount;
}
else
/* mark savecount invalid as CPU not in running state */
savecount[i] = -1;
}
/* Sleep for 20 seconds */
sleep(20);
}
}
#endif /*!defined(NO_SIGABEND_HANDLER)*/
/*-------------------------------------------------------------------*/
/* IMPL main entry point */
/*-------------------------------------------------------------------*/
int main (int argc, char *argv[])
{
BYTE *cfgfile; /* -> Configuration filename */
int c; /* Work area for getopt */
int arg_error = 0; /* 1=Invalid arguments */
#ifdef PROFILE_CPU
TID paneltid;
#endif
#if defined(ENABLE_NLS)
setlocale(LC_ALL, "");
bindtextdomain(PACKAGE, LOCALEDIR);
textdomain(PACKAGE);
#endif
#ifdef EXTERNALGUI
/* Set GUI flag if specified as final argument */
if (argc >= 1 && strncmp(argv[argc-1],"EXTERNALGUI",11) == 0)
{
extgui = 1;
argc--;
}
#endif /*EXTERNALGUI*/
#if defined(FISH_HANG)
FishHangInit(__FILE__,__LINE__);
#endif // defined(FISH_HANG)
init_hostinfo();
/* Get name of configuration file or default to hercules.cnf */
if(!(cfgfile = getenv("HERCULES_CNF")))
cfgfile = "hercules.cnf";
/* Display the version identifier */
display_version (stderr, "Hercules ");
/* Process the command line options */
while ((c = getopt(argc, argv, "f:")) != EOF)
{
switch (c) {
case 'f':
cfgfile = optarg;
break;
default:
arg_error = 1;
} /* end switch(c) */
} /* end while */
/* The getopt function sets the external variable optind
to the index in argv of the first non-option argument.
There should not be any non-option arguments */
if (optind < argc)
arg_error = 1;
/* Terminate if invalid arguments were detected */
if (arg_error)
{
fprintf (stderr,
"usage: %s [-f config-filename]\n",
argv[0]);
exit(1);
}
/* Build system configuration */
build_config (cfgfile);
/* Register the SIGINT handler */
if ( signal (SIGINT, sigint_handler) == SIG_ERR )
{
fprintf (stderr,
"HHC131I Cannot register SIGINT handler: %s\n",
strerror(errno));
exit(1);
}
/* Ignore the SIGPIPE signal, otherwise Hercules may terminate with
Broken Pipe error if the printer driver writes to a closed pipe */
if ( signal (SIGPIPE, SIG_IGN) == SIG_ERR )
{
fprintf (stderr,
"HHC132I Cannot suppress SIGPIPE signal: %s\n",
strerror(errno));
}
#if !defined(NO_SIGABEND_HANDLER)
{
struct sigaction sa;
sa.sa_sigaction = (void*)&sigabend_handler;
#ifdef SA_NODEFER
sa.sa_flags = SA_NODEFER;
#else
sa.sa_flags = 0
#endif
if( sigaction(SIGILL, &sa, NULL)
|| sigaction(SIGFPE, &sa, NULL)
|| sigaction(SIGSEGV, &sa, NULL)
|| sigaction(SIGBUS, &sa, NULL)
|| sigaction(SIGUSR1, &sa, NULL)
|| sigaction(SIGUSR2, &sa, NULL) )
{
fprintf (stderr,
"HHC133I Cannot register SIGILL/FPE/SEGV/BUS/USR handler: %s\n",
strerror(errno));
exit(1);
}
}
/* Start the watchdog */
if ( create_thread (&sysblk.wdtid, &sysblk.detattr,
watchdog_thread, NULL) )
{
fprintf (stderr,
"HHC134I Cannot create watchdog thread: %s\n",
strerror(errno));
exit(1);
}
#endif /*!defined(NO_SIGABEND_HANDLER)*/
#if defined(OPTION_HTTP_SERVER)
if(sysblk.httpport) {
/* Start the http server connection thread */
if ( create_thread (&sysblk.httptid, &sysblk.detattr,
http_server, NULL) )
{
fprintf (stderr,
"HHS001E Cannot create http_server thread: %s\n",
strerror(errno));
exit(1);
}
}
#endif /*defined(OPTION_HTTP_SERVER)*/
#ifndef PROFILE_CPU
/* Activate the control panel */
panel_display ();
#else
if(sysblk.regs[0].cpuonline)
return -1;
sysblk.regs[0].cpuonline = 1;
sysblk.regs[0].cpustate = CPUSTATE_STARTING;
sysblk.regs[0].cputid = thread_id();
sysblk.regs[0].arch_mode = sysblk.arch_mode;
if ( create_thread (&paneltid, &sysblk.detattr,
panel_display, NULL) )
{
fprintf (stderr,
"HHC137I Cannot create panel thread: %s\n",
strerror(errno));
exit(1);
}
cpu_thread(&sysblk.regs[0]);
#endif
return 0;
} /* end function main */