mirror of
https://github.com/vishapoberon/compiler.git
synced 2026-04-06 02:52:24 +00:00
Various fixes to OS vs Oberon file lifetime management in Files.Mod.
This commit is contained in:
parent
51ae4c3241
commit
9f0cbccf55
4 changed files with 44 additions and 45 deletions
|
|
@ -500,8 +500,6 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *)
|
||||||
WHILE i > 0 DO LogW(" "); DEC(i) END;
|
WHILE i > 0 DO LogW(" "); DEC(i) END;
|
||||||
|
|
||||||
LogVT100(VT100.Green); LogW("^"); LogVT100(VT100.ResetAll);
|
LogVT100(VT100.Green); LogW("^"); LogVT100(VT100.ResetAll);
|
||||||
|
|
||||||
Files.Close(f);
|
|
||||||
END ShowLine;
|
END ShowLine;
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -597,7 +595,8 @@ MODULE OPM; (* RC 6.3.89 / 28.6.89, J.Templ 10.7.89 / 22.7.96 *)
|
||||||
oldSFile := Files.Old(fileName); done := oldSFile # NIL;
|
oldSFile := Files.Old(fileName); done := oldSFile # NIL;
|
||||||
IF done THEN
|
IF done THEN
|
||||||
Files.Set(oldSF, oldSFile, 0); Files.Read(oldSF, tag); Files.Read(oldSF, ver);
|
Files.Set(oldSF, oldSFile, 0); Files.Read(oldSF, tag); Files.Read(oldSF, ver);
|
||||||
IF (tag # SFtag) OR (ver # SFver) THEN err(-306); (*possibly a symbol file from another Oberon implementation, e.g. HP-Oberon*)
|
IF (tag # SFtag) OR (ver # SFver) THEN
|
||||||
|
err(-306); (*possibly a symbol file from another Oberon implementation, e.g. HP-Oberon*)
|
||||||
CloseOldSym; done := FALSE
|
CloseOldSym; done := FALSE
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|
|
||||||
|
|
@ -18,14 +18,15 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
BufSize = 4096;
|
BufSize = 4096;
|
||||||
NoDesc = -1;
|
NoDesc = -1;
|
||||||
|
|
||||||
(* file states *)
|
(* No file states, used when FileDesc.fd = NoDesc *)
|
||||||
open = 0; (* OS File has been opened *)
|
open = 0; (* OS File has been opened *)
|
||||||
create = 1; (* OS file needs to be created *)
|
create = 1; (* OS file needs to be created *)
|
||||||
close = 2; (* Register telling Create to use registerName directly:
|
close = 2; (* Flag used by Files.Register to tell Create to create the
|
||||||
i.e. since we're closing and all data is still in
|
file using it's registerName directly, rather than to
|
||||||
buffers bypass writing to temp file and then renaming
|
create a temporary file: i.e. since we're closing and all
|
||||||
and just write directly to fianl register name *)
|
data is still in buffers bypass writing to temp file and
|
||||||
|
then renaming and just write directly to final register
|
||||||
|
name *)
|
||||||
|
|
||||||
TYPE
|
TYPE
|
||||||
FileName = ARRAY 101 OF CHAR;
|
FileName = ARRAY 101 OF CHAR;
|
||||||
|
|
@ -37,7 +38,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
registerName: FileName;
|
registerName: FileName;
|
||||||
tempFile: BOOLEAN;
|
tempFile: BOOLEAN;
|
||||||
identity: Platform.FileIdentity;
|
identity: Platform.FileIdentity;
|
||||||
fd-: Platform.FileHandle;
|
fd: Platform.FileHandle;
|
||||||
len, pos: LONGINT;
|
len, pos: LONGINT;
|
||||||
bufs: ARRAY NumBufs OF Buffer;
|
bufs: ARRAY NumBufs OF Buffer;
|
||||||
swapper: INTEGER;
|
swapper: INTEGER;
|
||||||
|
|
@ -63,7 +64,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
|
|
||||||
|
|
||||||
VAR
|
VAR
|
||||||
files: File; (* List of files that have an OS file handle/descriptor assigned *)
|
files: File; (* List of files backed by an OS file, whether open, registered or temporary. *)
|
||||||
tempno: INTEGER;
|
tempno: INTEGER;
|
||||||
HOME: ARRAY 1024 OF CHAR;
|
HOME: ARRAY 1024 OF CHAR;
|
||||||
SearchPath: POINTER TO ARRAY OF CHAR;
|
SearchPath: POINTER TO ARRAY OF CHAR;
|
||||||
|
|
@ -122,6 +123,10 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
END GetTempName;
|
END GetTempName;
|
||||||
|
|
||||||
PROCEDURE Create(f: File);
|
PROCEDURE Create(f: File);
|
||||||
|
(* Makes sure there is an OS file backing this Oberon file.
|
||||||
|
Used when more data has been written to an unregistered new file than
|
||||||
|
buffers can hold, or when registering a new file whose data is all in
|
||||||
|
buffers. *)
|
||||||
VAR
|
VAR
|
||||||
identity: Platform.FileIdentity;
|
identity: Platform.FileIdentity;
|
||||||
done: BOOLEAN;
|
done: BOOLEAN;
|
||||||
|
|
@ -137,16 +142,20 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
*)
|
*)
|
||||||
IF f.fd = NoDesc THEN
|
IF f.fd = NoDesc THEN
|
||||||
IF f.state = create THEN
|
IF f.state = create THEN
|
||||||
|
(* New file with enough data written to exceed buffers, so we need to
|
||||||
|
create a temporary file to back it. *)
|
||||||
GetTempName(f.registerName, f.workName); f.tempFile := TRUE
|
GetTempName(f.registerName, f.workName); f.tempFile := TRUE
|
||||||
ELSIF f.state = close THEN
|
ELSE
|
||||||
|
ASSERT(f.state = close);
|
||||||
|
(* New file with all data in buffers being registered. No need for a
|
||||||
|
temp file, will just write the buffers to the registerName. *)
|
||||||
f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE
|
f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE
|
||||||
END;
|
END;
|
||||||
error := Platform.Unlink(f.workName); (*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
|
error := Platform.Unlink(f.workName); (*unlink first to avoid stale NFS handles and to avoid reuse of inodes*)
|
||||||
|
|
||||||
error := Platform.New(f.workName, f.fd);
|
error := Platform.New(f.workName, f.fd);
|
||||||
done := error = 0;
|
done := error = 0;
|
||||||
IF done THEN
|
IF done THEN
|
||||||
f.next := files; files := f;
|
f.next := files; files := f; (* Link this file into the list of OS bakced files. *)
|
||||||
INC(Heap.FileCount);
|
INC(Heap.FileCount);
|
||||||
Heap.RegisterFinalizer(f, Finalize);
|
Heap.RegisterFinalizer(f, Finalize);
|
||||||
f.state := open;
|
f.state := open;
|
||||||
|
|
@ -186,31 +195,12 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
IF error # 0 THEN Err("error writing file", f, error) END;
|
IF error # 0 THEN Err("error writing file", f, error) END;
|
||||||
f.pos := buf.org + buf.size;
|
f.pos := buf.org + buf.size;
|
||||||
buf.chg := FALSE;
|
buf.chg := FALSE;
|
||||||
error := Platform.Identify(f.fd, f.identity);
|
error := Platform.Identify(f.fd, f.identity); (* Update identity with new modification time. *)
|
||||||
IF error # 0 THEN Err("error identifying file", f, error) END;
|
IF error # 0 THEN Err("error identifying file", f, error) END;
|
||||||
(*
|
|
||||||
error := Platform.Identify(f.fd, identity);
|
|
||||||
f.identity.mtime := identity.mtime;
|
|
||||||
*)
|
|
||||||
END
|
END
|
||||||
END Flush;
|
END Flush;
|
||||||
|
|
||||||
|
|
||||||
PROCEDURE CloseOSFile(f: File);
|
|
||||||
(* Close the OS file handle and remove f from 'files' *)
|
|
||||||
VAR prev: File; error: Platform.ErrorCode;
|
|
||||||
BEGIN
|
|
||||||
IF files = f THEN files := f.next
|
|
||||||
ELSE
|
|
||||||
prev := files;
|
|
||||||
WHILE (prev # NIL) & (prev.next # f) DO prev := prev.next END;
|
|
||||||
IF prev.next # NIL THEN prev.next := f.next END
|
|
||||||
END;
|
|
||||||
error := Platform.Close(f.fd);
|
|
||||||
f.fd := NoDesc; f.state := create; DEC(Heap.FileCount);
|
|
||||||
END CloseOSFile;
|
|
||||||
|
|
||||||
|
|
||||||
PROCEDURE Close* (f: File);
|
PROCEDURE Close* (f: File);
|
||||||
VAR
|
VAR
|
||||||
i: LONGINT;
|
i: LONGINT;
|
||||||
|
|
@ -219,12 +209,6 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
IF (f.state # create) OR (f.registerName # "") THEN
|
IF (f.state # create) OR (f.registerName # "") THEN
|
||||||
Create(f); i := 0;
|
Create(f); i := 0;
|
||||||
WHILE (i < NumBufs) & (f.bufs[i] # NIL) DO Flush(f.bufs[i]); INC(i) END;
|
WHILE (i < NumBufs) & (f.bufs[i] # NIL) DO Flush(f.bufs[i]); INC(i) END;
|
||||||
(* There's no reason to sync this file - we're about to close it. The OS
|
|
||||||
will sync if necessary. Further, sync will fail for a R/O file on Windows.
|
|
||||||
error := Platform.Sync(f.fd);
|
|
||||||
IF error # 0 THEN Err("error syncing file", f, error) END;
|
|
||||||
*)
|
|
||||||
CloseOSFile(f);
|
|
||||||
END
|
END
|
||||||
END Close;
|
END Close;
|
||||||
|
|
||||||
|
|
@ -323,7 +307,7 @@ MODULE Files; (* J. Templ 1.12. 89/12.4.95 Oberon files mapped onto Unix files
|
||||||
error := Platform.Identify(fd, identity);
|
error := Platform.Identify(fd, identity);
|
||||||
f := CacheEntry(identity);
|
f := CacheEntry(identity);
|
||||||
IF f # NIL THEN
|
IF f # NIL THEN
|
||||||
(* error := Platform.Close(fd); DCWB: Either this should be removed or should call CloseOSFile. *)
|
error := Platform.Close(fd); (* fd not needed - we'll be using f.fd. *)
|
||||||
RETURN f
|
RETURN f
|
||||||
ELSE NEW(f); Heap.RegisterFinalizer(f, Finalize);
|
ELSE NEW(f); Heap.RegisterFinalizer(f, Finalize);
|
||||||
f.fd := fd; f.state := open; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*)
|
f.fd := fd; f.state := open; f.pos := 0; f.swapper := -1; (*all f.buf[i] = NIL*)
|
||||||
|
|
@ -579,7 +563,7 @@ Especially Length would become fairly complex.
|
||||||
END Rename;
|
END Rename;
|
||||||
|
|
||||||
PROCEDURE Register* (f: File);
|
PROCEDURE Register* (f: File);
|
||||||
VAR idx, errcode: INTEGER; f1: File; file: ARRAY 104 OF CHAR;
|
VAR idx, errcode: INTEGER; f1: File;
|
||||||
BEGIN
|
BEGIN
|
||||||
(*
|
(*
|
||||||
Out.String("Files.Register f.registerName = "); Out.String(f.registerName);
|
Out.String("Files.Register f.registerName = "); Out.String(f.registerName);
|
||||||
|
|
@ -595,7 +579,7 @@ Especially Length would become fairly complex.
|
||||||
Out.String(" to registerName "); Out.String(f.registerName);
|
Out.String(" to registerName "); Out.String(f.registerName);
|
||||||
Out.String(" errorcode = "); Out.Int(errcode,1); Out.Ln;
|
Out.String(" errorcode = "); Out.Int(errcode,1); Out.Ln;
|
||||||
*)
|
*)
|
||||||
IF errcode # 0 THEN COPY(f.registerName, file); HALT(99) END;
|
IF errcode # 0 THEN Err("Couldn't rename temp name as register name", f, errcode) END;
|
||||||
f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE
|
f.workName := f.registerName; f.registerName := ""; f.tempFile := FALSE
|
||||||
END
|
END
|
||||||
END Register;
|
END Register;
|
||||||
|
|
@ -725,6 +709,20 @@ Especially Length would become fairly complex.
|
||||||
COPY (f.workName, name);
|
COPY (f.workName, name);
|
||||||
END GetName;
|
END GetName;
|
||||||
|
|
||||||
|
PROCEDURE CloseOSFile(f: File);
|
||||||
|
(* Close the OS file handle and remove f from 'files' *)
|
||||||
|
VAR prev: File; error: Platform.ErrorCode;
|
||||||
|
BEGIN
|
||||||
|
IF files = f THEN files := f.next
|
||||||
|
ELSE
|
||||||
|
prev := files;
|
||||||
|
WHILE (prev # NIL) & (prev.next # f) DO prev := prev.next END;
|
||||||
|
IF prev.next # NIL THEN prev.next := f.next END
|
||||||
|
END;
|
||||||
|
error := Platform.Close(f.fd);
|
||||||
|
f.fd := NoDesc; f.state := create; DEC(Heap.FileCount);
|
||||||
|
END CloseOSFile;
|
||||||
|
|
||||||
PROCEDURE Finalize(o: SYSTEM.PTR);
|
PROCEDURE Finalize(o: SYSTEM.PTR);
|
||||||
VAR f: File; res: LONGINT;
|
VAR f: File; res: LONGINT;
|
||||||
BEGIN
|
BEGIN
|
||||||
|
|
|
||||||
|
|
@ -530,7 +530,8 @@ MODULE Heap;
|
||||||
PROCEDURE GC*(markStack: BOOLEAN);
|
PROCEDURE GC*(markStack: BOOLEAN);
|
||||||
VAR
|
VAR
|
||||||
m: Module;
|
m: Module;
|
||||||
i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11, i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23: S.ADDRESS;
|
i0, i1, i2, i3, i4, i5, i6, i7, i8, i9, i10, i11,
|
||||||
|
i12, i13, i14, i15, i16, i17, i18, i19, i20, i21, i22, i23: S.ADDRESS;
|
||||||
cand: ARRAY 10000 OF S.ADDRESS;
|
cand: ARRAY 10000 OF S.ADDRESS;
|
||||||
BEGIN
|
BEGIN
|
||||||
IF (lockdepth = 0) OR (lockdepth = 1) & ~markStack THEN
|
IF (lockdepth = 0) OR (lockdepth = 1) & ~markStack THEN
|
||||||
|
|
|
||||||
|
|
@ -136,7 +136,7 @@ MODULE Modules; (* jt 6.1.96 *)
|
||||||
|
|
||||||
PROCEDURE Halt*(code: SYSTEM.INT32);
|
PROCEDURE Halt*(code: SYSTEM.INT32);
|
||||||
BEGIN
|
BEGIN
|
||||||
(*IF HaltHandler # NIL THEN HaltHandler(code) END;*)
|
Heap.FINALL;
|
||||||
errstring("Terminated by Halt("); errint(code); errstring("). ");
|
errstring("Terminated by Halt("); errint(code); errstring("). ");
|
||||||
IF code < 0 THEN DisplayHaltCode(code) END;
|
IF code < 0 THEN DisplayHaltCode(code) END;
|
||||||
errstring(Platform.NL);
|
errstring(Platform.NL);
|
||||||
|
|
@ -145,6 +145,7 @@ MODULE Modules; (* jt 6.1.96 *)
|
||||||
|
|
||||||
PROCEDURE AssertFail*(code: SYSTEM.INT32);
|
PROCEDURE AssertFail*(code: SYSTEM.INT32);
|
||||||
BEGIN
|
BEGIN
|
||||||
|
Heap.FINALL;
|
||||||
errstring("Assertion failure.");
|
errstring("Assertion failure.");
|
||||||
IF code # 0 THEN errstring(" ASSERT code "); errint(code); errstring("."); END;
|
IF code # 0 THEN errstring(" ASSERT code "); errint(code); errstring("."); END;
|
||||||
errstring(Platform.NL);
|
errstring(Platform.NL);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue