Re: [hatari-devel] Fforce() fails with GEMDOS drive emulation |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
Hi,
On torstai 14 maaliskuu 2013, Eero Tamminen wrote:
> I was thinking that I could track program startup and termination,
> keep counter for current program [1] and use that to identify which
> file handles belong to which program & are valid for it.
>
> However, reliably detecting progam startup and termination so
> that they don't get out of sync, is quite tricky, so I need some
> advice.
>
>
> GEMDOS emulation doesn't know whether Pexec() succeeds, and
> then there's also AES shel_write(SHELL_LAUNCH...) for starting
> programs (which doesn't necessarily do any externally visible
> GEMDOS calls), so something else needs to be used for detecting
> program startup. I was thinking of using basepage address
> for that as every concurrently resident program has it's own
> basepage.
>
> Is it safe to assume that if there's a new basepage, there's
> also a new program?
>
>
> As to program termination, I was thinking of catching Pterm(),
> Pterm0() and Ptermres() as program's files are supposed to be
> closed in each of these cases.
>
> I'm assuming that programs left resident with Ptermres() won't
> anymore access files, is this safe assumption?
>
> Are there any other ways for program to terminate AND to detect
> those? E.g. what happens if program crashes?
>
> Crashed program's file handles might not get closed by TOS, but
> for this stuff to work for GEMDOS emulation, it would need to
> detect that control moved back to previous program.
>
>
> [1] As TOS is single tasking, only last started program should be
> doing GEMDOS calls until it exits and previous program resumes.
> Any GEMDOS calls done by (Emu)TOS on behalf of the program can
> be safely assigned for that program too I assume. I.e. there's
> nothing that TOS retains after program termination?
For now, I commited just warnings on Fforce() & Pterm*() calls
and added notes about the issues to Hatari Manual.
Attached is an updated patch for Fforce() implementation
which can be used with programs that are guaranteed to
Fclose() before termination any files they Fforce()d.
It won't go into repository though, as it will cause bad issues
with anything that doesn't do that (i.e. handles remain redirected
even after program terminates).
- Eero
diff -r 93fe01d77a47 src/gemdos.c
--- a/src/gemdos.c Thu Mar 14 14:23:11 2013 +0200
+++ b/src/gemdos.c Thu Mar 14 14:35:51 2013 +0200
@@ -130,6 +130,9 @@
static Uint16 nAttrSFirst; /* File attribute for SFirst/Snext */
+#define UNFORCED_HANDLE -1
+static int ForcedHandles[5]; /* (standard) handles aliased to emulated handles */
+
#if defined(WIN32) && !defined(mkdir)
#define mkdir(name,mode) mkdir(name)
#endif /* WIN32 */
@@ -415,6 +418,7 @@
/* Clear handles structure */
memset(FileHandles, 0, sizeof(FileHandles));
+ memset(ForcedHandles, UNFORCED_HANDLE, sizeof(ForcedHandles));
/* Clear DTAs */
for(i = 0; i < MAX_DTAS_FILES; i++)
{
@@ -444,6 +448,7 @@
FileHandles[i].FileHandle = NULL;
FileHandles[i].bUsed = false;
}
+ memset(ForcedHandles, UNFORCED_HANDLE, sizeof(ForcedHandles));
for (DTAIndex = 0; DTAIndex < MAX_DTAS_FILES; DTAIndex++)
{
@@ -758,6 +763,7 @@
FileHandles[i].FileHandle = NULL;
FileHandles[i].bUsed = false;
}
+ memset(ForcedHandles, UNFORCED_HANDLE, sizeof(ForcedHandles));
}
}
@@ -783,13 +789,21 @@
/*-----------------------------------------------------------------------*/
/**
- * Check whether TOS handle is within our table range,
+ * Check whether TOS handle is within our table range, or aliased,
* return (positive) internal Handle if yes, (negative) -1 for error.
*/
static int GemDOS_GetValidFileHandle(int Handle)
{
- Handle -= BASE_FILEHANDLE;
-
+ /* Has handle been aliased with Fforce()? */
+ if (Handle >= 0 && Handle < ARRAYSIZE(ForcedHandles)
+ && ForcedHandles[Handle] != UNFORCED_HANDLE)
+ {
+ Handle = ForcedHandles[Handle];
+ }
+ else
+ {
+ Handle -= BASE_FILEHANDLE;
+ }
/* handle is valid for current program and in our handle table? */
if (Handle >= 0 && Handle < MAX_FILE_HANDLES
&& FileHandles[Handle].bUsed)
@@ -1811,7 +1825,7 @@
*/
static bool GemDOS_Close(Uint32 Params)
{
- int Handle;
+ int i, Handle;
/* Find our handle - may belong to TOS */
Handle = STMemory_ReadWord(Params);
@@ -1832,6 +1846,12 @@
}
FileHandles[Handle].bUsed = false;
+ /* unalias handle */
+ for (i = 0; i < ARRAYSIZE(ForcedHandles); i++)
+ {
+ if (ForcedHandles[i] == Handle)
+ ForcedHandles[i] = UNFORCED_HANDLE;
+ }
/* Return no error */
Regs[REG_D0] = GEMDOS_EOK;
return true;
@@ -2225,14 +2245,15 @@
/* assume it was TOS one -> let TOS handle it */
return false;
}
- /* implementation not possible because GEMDOS emulation doesn't
- * know when aliasing should be removed as it doesn't have any
- * way to track to which program aliasing belonged to AND
- * when that particular process terminates (at which point
- * aliasing should be also removed, not only at Fclose()).
- */
- Log_Printf(LOG_WARN, "Warning: Fforce() not implemented for GEMDOS emulation!\n");
- return false;
+ if (std < 0 || std >= ARRAYSIZE(ForcedHandles))
+ {
+ Log_Printf(LOG_WARN, "Warning: forcing of non-standard %d (> %d) handle ignored.\n", std, ARRAYSIZE(ForcedHandles));
+ return false;
+ }
+ ForcedHandles[std] = own;
+
+ Regs[REG_D0] = GEMDOS_EOK;
+ return true;
}