Added SET ASYNCH and SET NOASYNCH commands to dynamically enable or disable Asynchronous I/O support
This commit is contained in:
parent
6e098021c2
commit
034e749fce
6 changed files with 102 additions and 17 deletions
|
@ -5,6 +5,9 @@ Theory of operation.
|
||||||
Features.
|
Features.
|
||||||
- Optional Use. Build with or without SIM_ASYNCH_IO defined and
|
- Optional Use. Build with or without SIM_ASYNCH_IO defined and
|
||||||
simulators will still build and perform correctly when run.
|
simulators will still build and perform correctly when run.
|
||||||
|
Additionmally, a simulator built with SIM_ASYNCH_IO defined can
|
||||||
|
dynamically disable and reenable asynchronous operation with
|
||||||
|
the scp commands SET NOASYNCH and SET ASYNCH respectively.
|
||||||
- Consistent Save/Restore state. The state of a simulator saved
|
- Consistent Save/Restore state. The state of a simulator saved
|
||||||
on a simulator with (or without) Asynch support can be restored
|
on a simulator with (or without) Asynch support can be restored
|
||||||
on any simulator of the same version with or without Asynch
|
on any simulator of the same version with or without Asynch
|
||||||
|
|
|
@ -180,6 +180,7 @@ REG clk_reg[] = {
|
||||||
{ DRDATA (POLL, tmr_poll, 24), REG_NZ + PV_LEFT + REG_HRO },
|
{ DRDATA (POLL, tmr_poll, 24), REG_NZ + PV_LEFT + REG_HRO },
|
||||||
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
{ DRDATA (TPS, clk_tps, 8), REG_NZ + PV_LEFT },
|
||||||
#if defined (SIM_ASYNCH_IO)
|
#if defined (SIM_ASYNCH_IO)
|
||||||
|
{ DRDATA (ASYNCH, sim_asynch_enabled, 1), PV_LEFT },
|
||||||
{ DRDATA (LATENCY, sim_asynch_latency, 32), PV_LEFT },
|
{ DRDATA (LATENCY, sim_asynch_latency, 32), PV_LEFT },
|
||||||
{ DRDATA (INST_LATENCY, sim_asynch_inst_latency, 32), PV_LEFT },
|
{ DRDATA (INST_LATENCY, sim_asynch_inst_latency, 32), PV_LEFT },
|
||||||
#endif
|
#endif
|
||||||
|
|
74
scp.c
74
scp.c
|
@ -23,6 +23,17 @@
|
||||||
used in advertising or otherwise to promote the sale, use or other dealings
|
used in advertising or otherwise to promote the sale, use or other dealings
|
||||||
in this Software without prior written authorization from Robert M Supnik.
|
in this Software without prior written authorization from Robert M Supnik.
|
||||||
|
|
||||||
|
25-Sep-11 MP Added the ability for a simulator built with
|
||||||
|
SIM_ASYNCH_IO to change whether I/O is actually done
|
||||||
|
asynchronously by the new scp command SET ASYNCH and
|
||||||
|
SET NOASYNCH
|
||||||
|
22-Sep-11 MP Added signal catching of SIGHUP and SIGTERM to cause
|
||||||
|
simulator STOP. This allows an externally signalled
|
||||||
|
event (i.e. system shutdown, or logoff) to signal a
|
||||||
|
running simulator of these events and to allow
|
||||||
|
reasonable actions to be taken. This will facilitate
|
||||||
|
running a simulator as a 'service' on *nix platforms,
|
||||||
|
given a sufficiently flexible simulator .ini file.
|
||||||
20-Apr-11 MP Added expansion of %STATUS% and %TSTATUS% in do command
|
20-Apr-11 MP Added expansion of %STATUS% and %TSTATUS% in do command
|
||||||
arguments. STATUS is the numeric value of the last
|
arguments. STATUS is the numeric value of the last
|
||||||
command error status and TSTATUS is the text message
|
command error status and TSTATUS is the text message
|
||||||
|
@ -271,6 +282,7 @@ pthread_mutex_t sim_asynch_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||||
pthread_cond_t sim_asynch_wake = PTHREAD_COND_INITIALIZER;
|
pthread_cond_t sim_asynch_wake = PTHREAD_COND_INITIALIZER;
|
||||||
pthread_t sim_asynch_main_threadid;
|
pthread_t sim_asynch_main_threadid;
|
||||||
struct sim_unit *sim_asynch_queue = NULL;
|
struct sim_unit *sim_asynch_queue = NULL;
|
||||||
|
t_bool sim_asynch_enabled = TRUE;
|
||||||
int32 sim_asynch_check;
|
int32 sim_asynch_check;
|
||||||
int32 sim_asynch_latency = 4000; /* 4 usec interrupt latency */
|
int32 sim_asynch_latency = 4000; /* 4 usec interrupt latency */
|
||||||
int32 sim_asynch_inst_latency = 20; /* assume 5 mip simulator */
|
int32 sim_asynch_inst_latency = 20; /* assume 5 mip simulator */
|
||||||
|
@ -387,6 +399,7 @@ t_stat dep_addr (int32 flag, char *cptr, t_addr addr, DEVICE *dptr,
|
||||||
t_stat step_svc (UNIT *ptr);
|
t_stat step_svc (UNIT *ptr);
|
||||||
void sub_args (char *instr, char *tmpbuf, int32 maxstr, char *do_arg[]);
|
void sub_args (char *instr, char *tmpbuf, int32 maxstr, char *do_arg[]);
|
||||||
t_stat set_on (int32 flag, char *cptr);
|
t_stat set_on (int32 flag, char *cptr);
|
||||||
|
t_stat set_asynch (int32 flag, char *cptr);
|
||||||
|
|
||||||
|
|
||||||
/* Global data */
|
/* Global data */
|
||||||
|
@ -605,6 +618,8 @@ static CTAB cmd_table[] = {
|
||||||
"set nobreak <list> clear breakpoints\n"
|
"set nobreak <list> clear breakpoints\n"
|
||||||
"set throttle x{M|K|%%} set simulation rate\n"
|
"set throttle x{M|K|%%} set simulation rate\n"
|
||||||
"set nothrottle set simulation rate to maximum\n"
|
"set nothrottle set simulation rate to maximum\n"
|
||||||
|
"set asynch enable asynchronous I/O\n"
|
||||||
|
"set noasynch disable asynchronous I/O\n"
|
||||||
"set <dev> OCT|DEC|HEX set device display radix\n"
|
"set <dev> OCT|DEC|HEX set device display radix\n"
|
||||||
"set <dev> ENABLED enable device\n"
|
"set <dev> ENABLED enable device\n"
|
||||||
"set <dev> DISABLED disable device\n"
|
"set <dev> DISABLED disable device\n"
|
||||||
|
@ -628,6 +643,7 @@ static CTAB cmd_table[] = {
|
||||||
"sh{ow} q{ueue} show event queue\n"
|
"sh{ow} q{ueue} show event queue\n"
|
||||||
"sh{ow} ti{me} show simulated time\n"
|
"sh{ow} ti{me} show simulated time\n"
|
||||||
"sh{ow} th{rottle} show simulation rate\n"
|
"sh{ow} th{rottle} show simulation rate\n"
|
||||||
|
"sh{ow} a{synch} show asynchronouse I/O state\n"
|
||||||
"sh{ow} ve{rsion} show simulator version\n"
|
"sh{ow} ve{rsion} show simulator version\n"
|
||||||
"sh{ow} <dev> RADIX show device display radix\n"
|
"sh{ow} <dev> RADIX show device display radix\n"
|
||||||
"sh{ow} <dev> DEBUG show device debug flags\n"
|
"sh{ow} <dev> DEBUG show device debug flags\n"
|
||||||
|
@ -1281,6 +1297,61 @@ if ((sim_do_depth != 0) &&
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set asynch/noasynch routine */
|
||||||
|
|
||||||
|
t_stat sim_set_asynch (int32 flag, char *cptr)
|
||||||
|
{
|
||||||
|
if (cptr && (*cptr != 0)) /* now eol? */
|
||||||
|
return SCPE_2MARG;
|
||||||
|
#ifdef SIM_ASYNCH_IO
|
||||||
|
if (flag == sim_asynch_enabled) /* already set correctly? */
|
||||||
|
return SCPE_OK;
|
||||||
|
sim_asynch_enabled = flag;
|
||||||
|
if (1) {
|
||||||
|
uint32 i, j;
|
||||||
|
DEVICE *dptr;
|
||||||
|
UNIT *uptr;
|
||||||
|
|
||||||
|
/* Call unit flush routines to report asynch status change to device layer */
|
||||||
|
for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files */
|
||||||
|
for (j = 0; j < dptr->numunits; j++) { /* if not buffered in mem */
|
||||||
|
uptr = dptr->units + j;
|
||||||
|
if ((uptr->flags & UNIT_ATT) && /* attached, */
|
||||||
|
!(uptr->flags & UNIT_BUF) && /* not buffered, */
|
||||||
|
(uptr->fileref)) /* real file, */
|
||||||
|
if (uptr->io_flush) /* unit specific flush routine */
|
||||||
|
uptr->io_flush (uptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!sim_quiet)
|
||||||
|
printf ("Asynchronous I/O %sabled\n", sim_asynch_enabled ? "en" : "dis");
|
||||||
|
if (sim_log)
|
||||||
|
fprintf (sim_log, "Asynchronous I/O %sabled\n", sim_asynch_enabled ? "en" : "dis");
|
||||||
|
return SCPE_OK;
|
||||||
|
#else
|
||||||
|
if (!sim_quiet)
|
||||||
|
printf ("Asynchronous I/O is not available in this simulator\n");
|
||||||
|
if (sim_log)
|
||||||
|
fprintf (sim_log, "Asynchronous I/O is not available in this simulator\n");
|
||||||
|
return SCPE_NOFNC;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Show asynch routine */
|
||||||
|
|
||||||
|
t_stat sim_show_asynch (FILE *st, DEVICE *dptr, UNIT *uptr, int32 flag, char *cptr)
|
||||||
|
{
|
||||||
|
if (cptr && (*cptr != 0))
|
||||||
|
return SCPE_2MARG;
|
||||||
|
#ifdef SIM_ASYNCH_IO
|
||||||
|
fprintf (st, "Asynchronous I/O is %sabled\n", (sim_asynch_enabled) ? "en" : "dis");
|
||||||
|
#else
|
||||||
|
fprintf (st, "Asynchronous I/O is not available in this simulator\n");
|
||||||
|
#endif
|
||||||
|
return SCPE_OK;
|
||||||
|
}
|
||||||
|
|
||||||
/* Set command */
|
/* Set command */
|
||||||
|
|
||||||
t_stat set_cmd (int32 flag, char *cptr)
|
t_stat set_cmd (int32 flag, char *cptr)
|
||||||
|
@ -1305,6 +1376,8 @@ static CTAB set_glob_tab[] = {
|
||||||
{ "NODEBUG", &sim_set_deboff, 0 }, /* deprecated */
|
{ "NODEBUG", &sim_set_deboff, 0 }, /* deprecated */
|
||||||
{ "THROTTLE", &sim_set_throt, 1 },
|
{ "THROTTLE", &sim_set_throt, 1 },
|
||||||
{ "NOTHROTTLE", &sim_set_throt, 0 },
|
{ "NOTHROTTLE", &sim_set_throt, 0 },
|
||||||
|
{ "ASYNCH", &sim_set_asynch, 1 },
|
||||||
|
{ "NOASYNCH", &sim_set_asynch, 0 },
|
||||||
{ "ON", &set_on, 1 },
|
{ "ON", &set_on, 1 },
|
||||||
{ "NOON", &set_on, 0 },
|
{ "NOON", &set_on, 0 },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
|
@ -1570,6 +1643,7 @@ static SHTAB show_glob_tab[] = {
|
||||||
{ "TELNET", &sim_show_telnet, 0 }, /* deprecated */
|
{ "TELNET", &sim_show_telnet, 0 }, /* deprecated */
|
||||||
{ "DEBUG", &sim_show_debug, 0 }, /* deprecated */
|
{ "DEBUG", &sim_show_debug, 0 }, /* deprecated */
|
||||||
{ "THROTTLE", &sim_show_throt, 0 },
|
{ "THROTTLE", &sim_show_throt, 0 },
|
||||||
|
{ "ASYNCH", &sim_show_asynch, 0 },
|
||||||
{ "ON", &show_on, 0 },
|
{ "ON", &show_on, 0 },
|
||||||
{ NULL, NULL, 0 }
|
{ NULL, NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
|
@ -565,6 +565,7 @@ extern pthread_cond_t sim_asynch_wake;
|
||||||
extern pthread_t sim_asynch_main_threadid;
|
extern pthread_t sim_asynch_main_threadid;
|
||||||
extern struct sim_unit *sim_asynch_queue;
|
extern struct sim_unit *sim_asynch_queue;
|
||||||
extern t_bool sim_idle_wait;
|
extern t_bool sim_idle_wait;
|
||||||
|
extern t_bool sim_asynch_enabled;
|
||||||
extern int32 sim_asynch_check;
|
extern int32 sim_asynch_check;
|
||||||
extern int32 sim_asynch_latency;
|
extern int32 sim_asynch_latency;
|
||||||
extern int32 sim_asynch_inst_latency;
|
extern int32 sim_asynch_inst_latency;
|
||||||
|
|
21
sim_disk.c
21
sim_disk.c
|
@ -408,15 +408,17 @@ return SCPE_NOFNC;
|
||||||
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
|
||||||
ctx->asynch_io = 1;
|
ctx->asynch_io = sim_asynch_enabled;
|
||||||
ctx->asynch_io_latency = latency;
|
ctx->asynch_io_latency = latency;
|
||||||
pthread_mutex_init (&ctx->io_lock, NULL);
|
if (ctx->asynch_io) {
|
||||||
pthread_cond_init (&ctx->io_cond, NULL);
|
pthread_mutex_init (&ctx->io_lock, NULL);
|
||||||
pthread_attr_init(&attr);
|
pthread_cond_init (&ctx->io_cond, NULL);
|
||||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
pthread_attr_init(&attr);
|
||||||
pthread_create (&ctx->io_thread, &attr, _disk_io, (void *)uptr);
|
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||||
pthread_attr_destroy(&attr);
|
pthread_create (&ctx->io_thread, &attr, _disk_io, (void *)uptr);
|
||||||
uptr->a_check_completion = _disk_completion_dispatch;
|
pthread_attr_destroy(&attr);
|
||||||
|
uptr->a_check_completion = _disk_completion_dispatch;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
}
|
}
|
||||||
|
@ -723,7 +725,8 @@ uint32 f = DK_GET_FMT (uptr);
|
||||||
|
|
||||||
#if defined (SIM_ASYNCH_IO)
|
#if defined (SIM_ASYNCH_IO)
|
||||||
sim_disk_clr_async (uptr);
|
sim_disk_clr_async (uptr);
|
||||||
sim_disk_set_async (uptr, 0);
|
if (sim_asynch_enabled)
|
||||||
|
sim_disk_set_async (uptr, 0);
|
||||||
#endif
|
#endif
|
||||||
switch (f) { /* case on format */
|
switch (f) { /* case on format */
|
||||||
case DKUF_F_STD: /* Simh */
|
case DKUF_F_STD: /* Simh */
|
||||||
|
|
19
sim_tape.c
19
sim_tape.c
|
@ -320,14 +320,16 @@ return SCPE_NOFNC;
|
||||||
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
||||||
pthread_attr_t attr;
|
pthread_attr_t attr;
|
||||||
|
|
||||||
ctx->asynch_io = 1;
|
ctx->asynch_io = sim_asynch_enabled;
|
||||||
ctx->asynch_io_latency = latency;
|
ctx->asynch_io_latency = latency;
|
||||||
pthread_mutex_init (&ctx->io_lock, NULL);
|
if (ctx->asynch_io) {
|
||||||
pthread_cond_init (&ctx->io_cond, NULL);
|
pthread_mutex_init (&ctx->io_lock, NULL);
|
||||||
pthread_attr_init(&attr);
|
pthread_cond_init (&ctx->io_cond, NULL);
|
||||||
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
pthread_attr_init(&attr);
|
||||||
pthread_create (&ctx->io_thread, &attr, _tape_io, (void *)uptr);
|
pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM);
|
||||||
pthread_attr_destroy(&attr);
|
pthread_create (&ctx->io_thread, &attr, _tape_io, (void *)uptr);
|
||||||
|
pthread_attr_destroy(&attr);
|
||||||
|
}
|
||||||
uptr->a_check_completion = _tape_completion_dispatch;
|
uptr->a_check_completion = _tape_completion_dispatch;
|
||||||
#endif
|
#endif
|
||||||
return SCPE_OK;
|
return SCPE_OK;
|
||||||
|
@ -362,7 +364,8 @@ static void _sim_tape_io_flush (UNIT *uptr)
|
||||||
{
|
{
|
||||||
#if defined (SIM_ASYNCH_IO)
|
#if defined (SIM_ASYNCH_IO)
|
||||||
sim_tape_clr_async (uptr);
|
sim_tape_clr_async (uptr);
|
||||||
sim_tape_set_async (uptr, 0);
|
if (sim_asynch_enabled)
|
||||||
|
sim_tape_set_async (uptr, 0);
|
||||||
#endif
|
#endif
|
||||||
fflush (uptr->fileref);
|
fflush (uptr->fileref);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue