- Fixed asynchronous i/o hangs introduced when asynchronous cancel support was added

- Added event debug support to scp and the vax simulator
- Moved external declarations into include files related to modules which define them and removed random externs from modules which referenced them
- Fixed typos in sim_ether
- Fixed sim_disk and sim_tape to properly manage asynchronous threads on an i/o flush
This commit is contained in:
Mark Pizzolato 2013-01-09 17:02:58 -08:00
parent 960866a92a
commit 784ae24324
11 changed files with 114 additions and 95 deletions

View file

@ -480,9 +480,12 @@ MTAB cpu_mod[] = {
};
DEBTAB cpu_deb[] = {
{ "INTEXC", LOG_CPU_I },
{ "REI", LOG_CPU_R },
{ "CONTEXT", LOG_CPU_P },
{ "INTEXC", LOG_CPU_I },
{ "REI", LOG_CPU_R },
{ "CONTEXT", LOG_CPU_P },
{ "EVENT", SIM_DBG_EVENT },
{ "ACTIVATE", SIM_DBG_ACTIVATE },
{ "QUEUE", SIM_DBG_AIO_QUEUE },
{ NULL, 0 }
};

86
scp.c
View file

@ -256,9 +256,24 @@
#define SRBSIZ 1024 /* save/restore buffer */
#define SIM_BRK_INILNT 4096 /* bpt tbl length */
#define SIM_BRK_ALLTYP 0xFFFFFFFF
#define UPDATE_SIM_TIME(x) sim_time = sim_time + (x - sim_interval); \
sim_rtime = sim_rtime + ((uint32) (x - sim_interval)); \
x = sim_interval
#define UPDATE_SIM_TIME \
if (1) { \
int32 _x; \
AIO_LOCK; \
if (sim_clock_queue == QUEUE_LIST_END) \
_x = noqueue_time; \
else \
_x = sim_clock_queue->time; \
sim_time = sim_time + (_x - sim_interval); \
sim_rtime = sim_rtime + ((uint32) (_x - sim_interval)); \
if (sim_clock_queue == QUEUE_LIST_END) \
noqueue_time = sim_interval; \
else \
sim_clock_queue->time = sim_interval; \
AIO_UNLOCK; \
} \
else \
(void)0 \
#define SZ_D(dp) (size_map[((dp)->dwidth + CHAR_BIT - 1) / CHAR_BIT])
#define SZ_R(rp) \
@ -304,20 +319,6 @@ int32 sim_asynch_latency = 4000; /* 4 usec interrupt latency */
int32 sim_asynch_inst_latency = 20; /* assume 5 mip simulator */
#endif
/* VM interface */
extern char sim_name[];
extern DEVICE *sim_devices[];
extern REG *sim_PC;
extern const char *sim_stop_messages[];
extern t_stat sim_instr (void);
extern t_stat sim_load (FILE *ptr, char *cptr, char *fnam, int32 flag);
extern int32 sim_emax;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
extern t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val,
int32 sw);
/* The per-simulator init routine is a weak global that defaults to NULL
The other per-simulator pointers can be overrriden by the init routine */
@ -3867,12 +3868,7 @@ for (i = 1; (dptr = sim_devices[i]) != NULL; i++) { /* flush attached files
sim_cancel (&sim_step_unit); /* cancel step timer */
sim_throt_cancel (); /* cancel throttle */
AIO_UPDATE_QUEUE;
if (sim_clock_queue != QUEUE_LIST_END) { /* update sim time */
UPDATE_SIM_TIME (sim_clock_queue->time);
}
else {
UPDATE_SIM_TIME (noqueue_time);
}
UPDATE_SIM_TIME; /* update sim time */
return r;
}
@ -5441,12 +5437,12 @@ t_stat reason;
if (stop_cpu) /* stop CPU? */
return SCPE_STOP;
AIO_UPDATE_QUEUE;
UPDATE_SIM_TIME; /* update sim time */
if (sim_clock_queue == QUEUE_LIST_END) { /* queue empty? */
UPDATE_SIM_TIME (noqueue_time); /* update sim time */
sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Queue Emptry New Interval = %d\n", sim_interval);
return SCPE_OK;
}
UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */
do {
uptr = sim_clock_queue; /* get first */
sim_clock_queue = uptr->next; /* remove first */
@ -5455,12 +5451,21 @@ do {
if (sim_clock_queue != QUEUE_LIST_END)
sim_interval = sim_clock_queue->time;
else sim_interval = noqueue_time = NOQUEUE_WAIT;
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Event for %s\n", sim_uname (uptr));
if (uptr->action != NULL)
reason = uptr->action (uptr);
else reason = SCPE_OK;
} while ((reason == SCPE_OK) && (sim_interval == 0));
else
reason = SCPE_OK;
} while ((reason == SCPE_OK) &&
(sim_interval <= 0) &&
(sim_clock_queue != QUEUE_LIST_END));
/* Empty queue forces sim_interval != 0 */
if (sim_clock_queue == QUEUE_LIST_END) { /* queue empty? */
sim_interval = noqueue_time = NOQUEUE_WAIT; /* flag queue empty */
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Queue Complete New Interval = %d\n", sim_interval);
}
else
sim_debug (SIM_DBG_EVENT, sim_dflt_dev, "Processing Queue Complete New Interval = %d(%s)\n", sim_interval, sim_uname(sim_clock_queue));
return reason;
}
@ -5487,12 +5492,9 @@ int32 accum;
AIO_ACTIVATE (_sim_activate, uptr, event_time);
if (sim_is_active (uptr)) /* already active? */
return SCPE_OK;
if (sim_clock_queue == QUEUE_LIST_END) {
UPDATE_SIM_TIME (noqueue_time);
}
else { /* update sim time */
UPDATE_SIM_TIME (sim_clock_queue->time);
}
UPDATE_SIM_TIME; /* update sim time */
sim_debug (SIM_DBG_ACTIVATE, sim_dflt_dev, "Activating %s delay=%d\n", sim_uname (uptr), event_time);
prvptr = NULL;
accum = 0;
@ -5597,7 +5599,7 @@ AIO_CANCEL(uptr);
AIO_UPDATE_QUEUE;
if (sim_clock_queue == QUEUE_LIST_END)
return SCPE_OK;
UPDATE_SIM_TIME (sim_clock_queue->time); /* update sim time */
UPDATE_SIM_TIME; /* update sim time */
if (!sim_is_active (uptr))
return SCPE_OK;
nptr = QUEUE_LIST_END;
@ -5701,23 +5703,13 @@ return 0;
double sim_gtime (void)
{
if (sim_clock_queue == QUEUE_LIST_END) {
UPDATE_SIM_TIME (noqueue_time);
}
else {
UPDATE_SIM_TIME (sim_clock_queue->time);
}
UPDATE_SIM_TIME;
return sim_time;
}
uint32 sim_grtime (void)
{
if (sim_clock_queue == QUEUE_LIST_END) {
UPDATE_SIM_TIME (noqueue_time);
}
else {
UPDATE_SIM_TIME (sim_clock_queue->time);
}
UPDATE_SIM_TIME;
return sim_rtime;
}

28
scp.h
View file

@ -142,9 +142,35 @@ void sim_debug_bits (uint32 dbits, DEVICE* dptr, BITFIELD* bitdefs,
void sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...);
#else
void _sim_debug (uint32 dbits, DEVICE* dptr, const char* fmt, ...);
extern FILE *sim_deb; /* debug file */
#define sim_debug(dbits, dptr, ...) if (sim_deb && ((dptr)->dctrl & dbits)) _sim_debug (dbits, dptr, __VA_ARGS__); else (void)0
#endif
void fprint_stopped_gen (FILE *st, t_stat v, REG *pc, DEVICE *dptr);
/* Global data */
extern DEVICE *sim_dflt_dev;
extern int32 sim_interval;
extern int32 sim_switches;
extern int32 sim_quiet;
extern FILE *sim_log; /* log file */
extern FILEREF *sim_log_ref; /* log file file reference */
extern FILE *sim_deb; /* debug file */
extern FILEREF *sim_deb_ref; /* debug file file reference */
extern UNIT *sim_clock_queue;
extern volatile int32 stop_cpu;
/* VM interface */
extern char sim_name[];
extern DEVICE *sim_devices[];
extern REG *sim_PC;
extern const char *sim_stop_messages[];
extern t_stat sim_instr (void);
extern t_stat sim_load (FILE *ptr, char *cptr, char *fnam, int32 flag);
extern int32 sim_emax;
extern t_stat fprint_sym (FILE *ofile, t_addr addr, t_value *val,
UNIT *uptr, int32 sw);
extern t_stat parse_sym (char *cptr, t_addr addr, UNIT *uptr, t_value *val,
int32 sw);
#endif

View file

@ -195,11 +195,6 @@ t_stat sim_con_reset (DEVICE *dptr)
return sim_con_poll_svc (&dptr->units[0]); /* establish polling as needed */
}
extern volatile int32 stop_cpu;
extern int32 sim_quiet;
extern FILE *sim_log, *sim_deb;
extern FILEREF *sim_log_ref, *sim_deb_ref;
extern DEVICE *sim_devices[];
/* Set/show data structures */
@ -1428,7 +1423,6 @@ void SIOUXUpdateScrollbar(void);
int ps_kbhit(void);
int ps_getch(void);
extern char sim_name[];
extern pSIOUXWin SIOUXTextWindow;
static CursHandle iBeamCursorH = NULL; /* contains the iBeamCursor */

View file

@ -530,6 +530,10 @@ struct sim_debtab {
#define DEBUG_PRI(d,m) (sim_deb && (d.dctrl & (m)))
#define DEBUG_PRJ(d,m) (sim_deb && (d->dctrl & (m)))
#define SIM_DBG_EVENT 0x10000
#define SIM_DBG_ACTIVATE 0x20000
#define SIM_DBG_AIO_QUEUE 0x40000
struct sim_bitfield {
char *name; /* field name */
uint32 offset; /* starting bit */
@ -691,6 +695,7 @@ extern int32 sim_asynch_inst_latency;
do \
q = AIO_QUEUE_VAL; \
while (q != AIO_QUEUE_SET(QUEUE_LIST_END, q)); \
sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "found asynch event for %s after %d instructions\n", sim_uname(q), q->a_event_time);\
while (q != QUEUE_LIST_END) { /* List !Empty */ \
uptr = q; \
q = q->a_next; \
@ -709,24 +714,26 @@ extern int32 sim_asynch_inst_latency;
} else (void)0
#define AIO_ACTIVATE(caller, uptr, event_time) \
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
if (uptr->a_next) { \
uptr->a_activate_call = sim_activate_abs; \
UNIT *ouptr = (uptr); \
sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "queueing asynch event for %s after %d instructions\n", sim_uname(ouptr), event_time);\
if (ouptr->a_next) { \
ouptr->a_activate_call = sim_activate_abs; \
} else { \
UNIT *q, *qe; \
uptr->a_event_time = event_time; \
uptr->a_activate_call = sim_activate; \
uptr->a_next = QUEUE_LIST_END; /* Mark as on list */ \
ouptr->a_event_time = event_time; \
ouptr->a_activate_call = sim_activate; \
ouptr->a_next = QUEUE_LIST_END; /* Mark as on list */ \
do { \
do \
q = AIO_QUEUE_VAL; \
while (q != AIO_QUEUE_SET(QUEUE_LIST_END, q));/* Grab current list */\
for (qe = uptr; qe->a_next != QUEUE_LIST_END; qe = qe->a_next); \
for (qe = ouptr; qe->a_next != QUEUE_LIST_END; qe = qe->a_next); \
qe->a_next = q; /* append current list */\
do \
q = AIO_QUEUE_VAL; \
while (q != AIO_QUEUE_SET(uptr, q)); \
uptr = q; \
} while (uptr != QUEUE_LIST_END); \
while (q != AIO_QUEUE_SET(ouptr, q)); \
ouptr = q; \
} while (ouptr != QUEUE_LIST_END); \
} \
if (sim_idle_wait) \
pthread_cond_signal (&sim_asynch_wake); \
@ -743,6 +750,7 @@ extern int32 sim_asynch_inst_latency;
while (sim_asynch_queue != QUEUE_LIST_END) { /* List !Empty */ \
int32 a_event_time; \
uptr = sim_asynch_queue; \
sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "found asynch event for %s after %d instructions\n", sim_uname(uptr), uptr->a_event_time);\
sim_asynch_queue = uptr->a_next; \
uptr->a_next = NULL; \
if (uptr->a_activate_call != &sim_activate_notbefore) { \
@ -763,6 +771,7 @@ extern int32 sim_asynch_inst_latency;
} else (void)0
#define AIO_ACTIVATE(caller, uptr, event_time) \
if (!pthread_equal ( pthread_self(), sim_asynch_main_threadid )) { \
sim_debug (SIM_DBG_AIO_QUEUE, sim_dflt_dev, "queueing asynch event for %s after %d instructions\n", sim_uname(uptr), event_time);\
pthread_mutex_lock (&sim_asynch_lock); \
if (uptr->a_next) { \
uptr->a_activate_call = sim_activate_abs; \

View file

@ -84,12 +84,6 @@ Internal routines:
#include <pthread.h>
#endif
extern FILE *sim_log; /* log file */
extern int32 sim_switches;
extern int32 sim_quiet;
extern uint32 sim_taddr_64;
extern int32 sim_end;
struct disk_context {
DEVICE *dptr; /* Device for unit (access to debug flags) */
uint32 dbit; /* debugging bit */
@ -772,16 +766,19 @@ switch (DK_GET_FMT (uptr)) { /* case on format */
}
}
/*
This routine is called when the simulator stops and any time
the asynch mode is changed (enabled or disabled)
*/
static void _sim_disk_io_flush (UNIT *uptr)
{
uint32 f = DK_GET_FMT (uptr);
#if defined (SIM_ASYNCH_IO)
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
int was_asynch = ctx ? ctx->asynch_io : 0;
sim_disk_clr_async (uptr);
if (was_asynch)
if (sim_asynch_enabled)
sim_disk_set_async (uptr, ctx->asynch_io_latency);
#endif
switch (f) { /* case on format */
@ -1196,8 +1193,13 @@ return SCPE_OK;
t_stat sim_disk_reset (UNIT *uptr)
{
struct disk_context *ctx = (struct disk_context *)uptr->disk_ctx;
if (!(uptr->flags & UNIT_ATT)) /* attached? */
return SCPE_OK;
sim_debug (ctx->dbit, ctx->dptr, "sim_disk_reset(unit=%d)\n", (int)(uptr-ctx->dptr->units));
_sim_disk_io_flush(uptr);
AIO_VALIDATE;
AIO_UPDATE_QUEUE;

View file

@ -366,8 +366,6 @@
#include "sim_ether.h"
#include "sim_sock.h"
extern FILE *sim_log;
/*============================================================================*/
/* OS-independant ethernet routines */
@ -1978,8 +1976,8 @@ fprintf (st, " sim> show ethernet\n");
fprintf (st, " libpcap version 1.0.0\n");
fprintf (st, " ETH devices:\n");
fprintf (st, " eth0 en0 (No description available)\n");
fprintf (st, " eth1 tap:tapN (Integrated Tun/Tap support)\n");
fprintf (st, " sim> attach %a eth0\n\n", dptr->name);
fprintf (st, " eth1 tap:tapN (Integrated Tun/Tap support)\n");
fprintf (st, " sim> attach %s eth0\n\n", dptr->name);
fprintf (st, "or equivalently:\n\n");
fprintf (st, " sim> attach %s en0\n\n", dptr->name);
return SCPE_OK;

View file

@ -49,5 +49,7 @@ t_addr sim_fsize_name_ex (char *fname);
void sim_buf_swap_data (void *bptr, size_t size, size_t count);
void sim_buf_copy_swapped (void *dptr, void *bptr, size_t size, size_t count);
extern uint32 sim_taddr_64;
extern int32 sim_end;
#endif

View file

@ -109,8 +109,6 @@ static struct sim_tape_fmt fmts[MTUF_N_FMT] = {
{ NULL, 0, 0 }
};
extern int32 sim_switches;
t_stat sim_tape_ioerr (UNIT *uptr);
t_stat sim_tape_wrdata (UNIT *uptr, uint32 dat);
uint32 sim_tape_tpc_map (UNIT *uptr, t_addr *map);
@ -348,7 +346,6 @@ if (ctx) {
t_stat sim_tape_set_async (UNIT *uptr, int latency)
{
#if !defined(SIM_ASYNCH_IO)
extern FILE *sim_log; /* log file */
char *msg = "Tape: can't operate asynchronously\r\n";
printf ("%s", msg);
if (sim_log) fprintf (sim_log, "%s", msg);
@ -406,14 +403,17 @@ return SCPE_OK;
#endif
}
/*
This routine is called when the simulator stops and any time
the asynch mode is changed (enabled or disabled)
*/
static void _sim_tape_io_flush (UNIT *uptr)
{
#if defined (SIM_ASYNCH_IO)
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
int was_asynch = ctx ? ctx->asynch_io : 0;
sim_tape_clr_async (uptr);
if (was_asynch)
if (sim_asynch_enabled)
sim_tape_set_async (uptr, ctx->asynch_io_latency);
#endif
fflush (uptr->fileref);
@ -1785,9 +1785,14 @@ return r;
t_stat sim_tape_reset (UNIT *uptr)
{
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
MT_CLR_PNU (uptr);
if (!(uptr->flags & UNIT_ATT)) /* attached? */
return SCPE_OK;
sim_debug (ctx->dbit, ctx->dptr, "sim_tape_reset(unit=%d)\n", (int)(uptr-ctx->dptr->units));
_sim_tape_io_flush(uptr);
AIO_VALIDATE;
AIO_UPDATE_QUEUE;
@ -1910,7 +1915,6 @@ return ((p == 0)? map[p]: map[p - 1]);
t_stat sim_tape_set_capac (UNIT *uptr, int32 val, char *cptr, void *desc)
{
extern uint32 sim_taddr_64;
t_addr cap;
t_stat r;

View file

@ -94,9 +94,6 @@ static uint32 sim_throt_val = 0;
static uint32 sim_throt_state = 0;
static uint32 sim_throt_sleep_time = 0;
static int32 sim_throt_wait = 0;
extern int32 sim_interval, sim_switches;
extern FILE *sim_log;
extern UNIT *sim_clock_queue;
t_stat sim_throt_svc (UNIT *uptr);

View file

@ -345,14 +345,6 @@
/* External variables */
extern int32 sim_switches;
extern char sim_name[];
extern FILE *sim_log;
/* Local routines */