1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292
|
/* IMPL.C (c) Copyright Roger Bowler, 1999-2003 */
/* 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*/
UNREFERENCED(signo);
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 defined(_FEATURE_WAITSTATE_ASSIST)
&& !(sysblk.regs[i].sie_state && sysblk.regs[i].guestregs->psw.wait)
#endif
))
{
/* 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,
"HHCIN001S 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,
"HHCIN002E 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,
"HHCIN003S 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,
"HHCIN004S 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 (!sysblk.httproot)
{
#if defined(WIN32)
char process_dir[1024];
if (get_process_directory(process_dir,1024) > 0)
sysblk.httproot = strdup(process_dir);
else
#endif /*defined(WIN32)*/
sysblk.httproot = HTTP_ROOT;
}
#if defined(WIN32)
if (is_win32_directory(sysblk.httproot))
{
char posix_dir[1024];
convert_win32_directory_to_posix_directory(sysblk.httproot,posix_dir);
sysblk.httproot = strdup(posix_dir);
}
#endif /*defined(WIN32)*/
TRACE("HTTPROOT = %s\n",sysblk.httproot);
if ( create_thread (&sysblk.httptid, &sysblk.detattr,
http_server, NULL) )
{
fprintf (stderr,
"HHCIN005S 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,
"HHCIN006S Cannot create panel thread: %s\n",
strerror(errno));
exit(1);
}
cpu_thread(&sysblk.regs[0]);
#endif
return 0;
} /* end function main */
|