Fixed bug under Asynch I/O where I/O completion did not delay the appropriate time before passing back device status to a simulator. Found by Sergey Oboguev.
This commit is contained in:
parent
6e6fdd02ae
commit
7ac3557524
8 changed files with 34 additions and 25 deletions
|
@ -89,7 +89,7 @@ example there now exists the routines:
|
|||
t_stat sim_tape_rdrecf_a (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max, TAPE_PCALLBACK callback);
|
||||
|
||||
The Purpose of the callback function is to record the I/O completion status
|
||||
and then to schedule the activation of the unit.
|
||||
and then to schedule the activation of the unit.
|
||||
|
||||
Considerations:
|
||||
Avoiding multiple concurrent users of the unit structure. While asynch
|
||||
|
@ -108,7 +108,13 @@ The callback routine must save the I/O completion status in a place
|
|||
which the next invocation of the unit service routine will reference
|
||||
and act on it. This allows device code to return error conditions
|
||||
back to scp in a consistent way without regard to how the callback
|
||||
routine (and the actual I/O) may have been executed.
|
||||
routine (and the actual I/O) may have been executed. When the callback
|
||||
routine is called, it will already be on the simulator event queue with
|
||||
an event time which was specified when the unit was attached or via a
|
||||
call to sim_disk_set_async. If no value has been specified then it
|
||||
will have been scheduled with a delay time of 0. If a different event
|
||||
firing time is desired, then the callback completion routine should
|
||||
call sim_activate_abs to schedule the event at the appropriate time.
|
||||
|
||||
Required change in device coding.
|
||||
Devices which wish to leverage the benefits of asynch I/O must rearrange
|
||||
|
|
|
@ -782,7 +782,6 @@ void rp_io_complete (UNIT *uptr, t_stat status)
|
|||
{
|
||||
uptr->io_status = status;
|
||||
uptr->io_complete = 1;
|
||||
sim_activate (uptr, 0);
|
||||
}
|
||||
|
||||
/* Service unit timeout
|
||||
|
@ -1030,7 +1029,7 @@ t_stat r;
|
|||
uptr->capac = drv_tab[GET_DTYPE (uptr->flags)].size;
|
||||
r = sim_disk_attach (uptr, cptr, RP_NUMWD * sizeof (uint16),
|
||||
sizeof (uint16), TRUE, 0,
|
||||
drv_tab[GET_DTYPE (uptr->flags)].name, drv_tab[GET_DTYPE (uptr->flags)].sect);
|
||||
drv_tab[GET_DTYPE (uptr->flags)].name, drv_tab[GET_DTYPE (uptr->flags)].sect, 0);
|
||||
if (r != SCPE_OK) /* error? */
|
||||
return r;
|
||||
drv = (int32) (uptr - rp_dev.units); /* get drv number */
|
||||
|
|
|
@ -1800,10 +1800,9 @@ sim_debug (DBG_TRC, rq_devmap[cp->cnum], "rq_io_complete(status=%d)\n", status);
|
|||
|
||||
uptr->io_status = status;
|
||||
uptr->io_complete = 1;
|
||||
if (elapsed > rq_xtime)
|
||||
sim_activate (uptr, 0);
|
||||
else
|
||||
sim_activate (uptr, rq_xtime-elapsed);
|
||||
/* Reschedule for the appropriate delay */
|
||||
if (elapsed <= rq_xtime)
|
||||
sim_activate_abs (uptr, rq_xtime-elapsed);
|
||||
}
|
||||
|
||||
/* Unit service for data transfer commands */
|
||||
|
@ -2487,7 +2486,7 @@ t_stat rq_attach (UNIT *uptr, char *cptr)
|
|||
MSC *cp = rq_ctxmap[uptr->cnum];
|
||||
t_stat r;
|
||||
|
||||
r = sim_disk_attach (uptr, cptr, RQ_NUMBY, sizeof (uint16), (uptr->flags & UNIT_NOAUTO), DBG_DSK, drv_tab[GET_DTYPE (uptr->flags)].name, 0);
|
||||
r = sim_disk_attach (uptr, cptr, RQ_NUMBY, sizeof (uint16), (uptr->flags & UNIT_NOAUTO), DBG_DSK, drv_tab[GET_DTYPE (uptr->flags)].name, 0, 0);
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
|
||||
|
|
|
@ -1286,10 +1286,9 @@ sim_debug(DBG_TRC, &tq_dev, "tq_io_complete(status=%d)\n", status);
|
|||
|
||||
res->io_status = status;
|
||||
res->io_complete = 1;
|
||||
if (elapsed > tq_xtime)
|
||||
sim_activate (uptr, 0);
|
||||
else
|
||||
sim_activate (uptr, tq_xtime-elapsed);
|
||||
/* Reschedule for the appropriate delay */
|
||||
if (elapsed <= tq_xtime)
|
||||
sim_activate_abs (uptr, tq_xtime-elapsed);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2025,7 +2024,7 @@ t_stat tq_attach (UNIT *uptr, char *cptr)
|
|||
{
|
||||
t_stat r;
|
||||
|
||||
r = sim_tape_attach_ex (uptr, cptr, DBG_TAP);
|
||||
r = sim_tape_attach_ex (uptr, cptr, DBG_TAP, 0);
|
||||
if (r != SCPE_OK)
|
||||
return r;
|
||||
if (tq_csta == CST_UP)
|
||||
|
|
13
sim_disk.c
13
sim_disk.c
|
@ -733,9 +733,11 @@ 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;
|
||||
|
||||
sim_disk_clr_async (uptr);
|
||||
if (sim_asynch_enabled)
|
||||
sim_disk_set_async (uptr, 0);
|
||||
sim_disk_set_async (uptr, ctx->asynch_io_latency);
|
||||
#endif
|
||||
switch (f) { /* case on format */
|
||||
case DKUF_F_STD: /* Simh */
|
||||
|
@ -760,7 +762,8 @@ return stat;
|
|||
}
|
||||
|
||||
|
||||
t_stat sim_disk_attach (UNIT *uptr, char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize, uint32 dbit, const char *dtype, uint32 pdp11tracksize)
|
||||
t_stat sim_disk_attach (UNIT *uptr, char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
uint32 dbit, const char *dtype, uint32 pdp11tracksize, int completion_delay)
|
||||
{
|
||||
struct disk_context *ctx;
|
||||
DEVICE *dptr;
|
||||
|
@ -797,7 +800,7 @@ if (sim_switches & SWMASK ('D')) { /* create difference dis
|
|||
vhd = sim_vhd_disk_create_diff (gbuf, cptr);
|
||||
if (vhd) {
|
||||
sim_vhd_disk_close (vhd);
|
||||
return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize);
|
||||
return sim_disk_attach (uptr, gbuf, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
}
|
||||
return SCPE_ARG;
|
||||
}
|
||||
|
@ -816,7 +819,7 @@ if (sim_switches & SWMASK ('C')) { /* create vhd disk & cop
|
|||
sim_switches |= SWMASK ('R') | SWMASK ('E');
|
||||
sim_quiet = TRUE;
|
||||
/* First open the source of the copy operation */
|
||||
r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize);
|
||||
r = sim_disk_attach (uptr, cptr, sector_size, xfer_element_size, dontautosize, dbit, dtype, pdp11tracksize, completion_delay);
|
||||
sim_quiet = saved_sim_quiet;
|
||||
if (r != SCPE_OK) {
|
||||
sim_switches = saved_sim_switches;
|
||||
|
@ -1013,7 +1016,7 @@ if (capac && (capac != (t_addr)-1))
|
|||
uptr->capac = capac/ctx->capac_factor;
|
||||
|
||||
#if defined (SIM_ASYNCH_IO)
|
||||
sim_disk_set_async (uptr, 0);
|
||||
sim_disk_set_async (uptr, completion_delay);
|
||||
#endif
|
||||
uptr->io_flush = _sim_disk_io_flush;
|
||||
|
||||
|
|
|
@ -64,7 +64,8 @@ typedef void (*DISK_PCALLBACK)(UNIT *unit, t_stat status);
|
|||
|
||||
/* Prototypes */
|
||||
|
||||
t_stat sim_disk_attach (UNIT *uptr, char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize, uint32 debugbit, const char *drivetype, uint32 pdp11_tracksize);
|
||||
t_stat sim_disk_attach (UNIT *uptr, char *cptr, size_t sector_size, size_t xfer_element_size, t_bool dontautosize,
|
||||
uint32 debugbit, const char *drivetype, uint32 pdp11_tracksize, int completion_delay);
|
||||
t_stat sim_disk_detach (UNIT *uptr);
|
||||
t_stat sim_disk_rdsect (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects);
|
||||
t_stat sim_disk_rdsect_a (UNIT *uptr, t_lba lba, uint8 *buf, t_seccnt *sectsread, t_seccnt sects, DISK_PCALLBACK callback);
|
||||
|
|
10
sim_tape.c
10
sim_tape.c
|
@ -367,9 +367,11 @@ return SCPE_OK;
|
|||
static void _sim_tape_io_flush (UNIT *uptr)
|
||||
{
|
||||
#if defined (SIM_ASYNCH_IO)
|
||||
struct tape_context *ctx = (struct tape_context *)uptr->tape_ctx;
|
||||
|
||||
sim_tape_clr_async (uptr);
|
||||
if (sim_asynch_enabled)
|
||||
sim_tape_set_async (uptr, 0);
|
||||
sim_tape_set_async (uptr, ctx->asynch_io_latency);
|
||||
#endif
|
||||
fflush (uptr->fileref);
|
||||
}
|
||||
|
@ -378,10 +380,10 @@ fflush (uptr->fileref);
|
|||
|
||||
t_stat sim_tape_attach (UNIT *uptr, char *cptr)
|
||||
{
|
||||
return sim_tape_attach_ex (uptr, cptr, 0);
|
||||
return sim_tape_attach_ex (uptr, cptr, 0, 0);
|
||||
}
|
||||
|
||||
t_stat sim_tape_attach_ex (UNIT *uptr, char *cptr, uint32 dbit)
|
||||
t_stat sim_tape_attach_ex (UNIT *uptr, char *cptr, uint32 dbit, int completion_delay)
|
||||
{
|
||||
struct tape_context *ctx;
|
||||
uint32 objc;
|
||||
|
@ -429,7 +431,7 @@ ctx->dbit = dbit; /* save debug bit */
|
|||
sim_tape_rewind (uptr);
|
||||
|
||||
#if defined (SIM_ASYNCH_IO)
|
||||
sim_tape_set_async (uptr, 0);
|
||||
sim_tape_set_async (uptr, completion_delay);
|
||||
#endif
|
||||
uptr->io_flush = _sim_tape_io_flush;
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ typedef void (*TAPE_PCALLBACK)(UNIT *unit, t_stat status);
|
|||
|
||||
/* Prototypes */
|
||||
|
||||
t_stat sim_tape_attach_ex (UNIT *uptr, char *cptr, uint32 dbit);
|
||||
t_stat sim_tape_attach_ex (UNIT *uptr, char *cptr, uint32 dbit, int completion_delay);
|
||||
t_stat sim_tape_attach (UNIT *uptr, char *cptr);
|
||||
t_stat sim_tape_detach (UNIT *uptr);
|
||||
t_stat sim_tape_rdrecf (UNIT *uptr, uint8 *buf, t_mtrlnt *bc, t_mtrlnt max);
|
||||
|
|
Loading…
Add table
Reference in a new issue