BLOCK

( u -- a-addr )

a-addr is the address of the first character of the block buffer assigned to mass-storage block u. An ambiguous condition exists if u is not an available block number.

If block u is already in a block buffer, a-addr is the address of that block buffer.

If block u is not already in memory and there is an unassigned block buffer, transfer block u from mass storage to an unassigned block buffer. a-addr is the address of that block buffer.

If block u is not already in memory and there are no unassigned block buffers, unassign a block buffer. If the block in that buffer has been UPDATEd, transfer the block to mass storage and transfer block u from mass storage into that buffer. a-addr is the address of that block buffer.

At the conclusion of the operation, the block buffer pointed to by a-addr is the current block buffer and is assigned to u.

ContributeContributions

StevePalmeravatar of StevePalmer Can `BLOCK` transfer from mass storage in the case when block u is already in a block buffer?Request for clarification2021-03-05 13:16:46

I am the author of the block word set test in Gerry Jackson's forth2012-test-suite. An issue has been raised against one of the tests since it assumes that BLOCK does not overwrite the buffer from the mass storage if the buffer is already allocated by BUFFER. The author of the issue is Francois Laagel who is coming from an implementation of FORTH-79. FORTH-79 definition for BLOCK states:

Leave the address of the first byte in block n. If the block is not already in memory, it is transferred from mass storage into whichever memory buffer has been least recently accessed. If the block occupying that buffer has been UPDATEd (i.e. modified), it is rewritten onto mass storage before block n in read into the buffer. n is an unassigned number. If correct mass storage read or write [is] not possible, an error condition exists. Only data within the latest block referenced by BLOCK is valid by byte address, due to sharing of the block buffers.

Reply New Version

StevePalmeravatar of StevePalmer Can `BLOCK` transfer from mass storage in the case when block u is already in a block buffer?Request for clarification2021-03-05 13:31:11

(Sorry - I hit submit by accident. Continuing ...)

Francois has an implementation of FORTH79 which keeps track of whether an assigned buffer has been sourced from the mass storage or not. The BLOCK word uses this to detect a buffer that has been allocated by BUFFER, but not read. In such cases, it will do the transfer from mass storage.

As I read the FORTH79 (and FORTH83) standard, this seems like a compliant implementation since the standards do not say what should happen in BLOCK if a buffer is already assigned. However, ANS FORTH seems to me to have tightened up here and states:

If block u is already in a block buffer, a-addr is the address of that block buffer.

As I read the ANS FORTH standard, is does not say that the block buffer may be altered in anyway if the block is already in a block buffer. In my head I am applying a meta rule that says "and nothing else changes" (without which all language standards would be 10 times as long and 100 times less intelligible.)

Therefore, I would expect a definition of BLOCK which transfers from mass storage when the block is already in a block buffer to be non-compliant with ANS FORTH.

Sometimes, I find a small code example can illustrate the point much better. Consider the following:

( Prepare a buffer in memory with some contents )
: PREPARE_BUFFER  ( blk c-addr u -- )
  ROT BUFFER DUP 1024 BL FILL
  SWAP 1024 MIN CMOVE
;

( Test whether BLOCK forces a read from mass storage )
: BLOCK_FORCED_READ? ( blk -- )
  EMPTY-BUFFERS  \ Establish known starting condition
  DUP S" MASS STORAGE READ" PREPARE_BUFFER UPDATE FLUSH  \ Prepare mass storage
  DUP S" MASS STORAGE NOT READ" PREPARE_BUFFER  \ Prepare buffer
  DUP BLOCK DROP  \ Does BLOCK read from mass storage? ...
  LIST ;

20 BLOCK_FORCED_READ?

Is the LIST output required by the ANS Standard to contain "MASS STORAGE READ" or "MASS STORAGE NOT READ" or are both allowed?

Thanks, Steve

AntonErtlavatar of AntonErtl

Concerning the question in the title, IMO BLOCK must not do that.

Concerning your example: If we assume that nothing between the second call to BUFFER and the call to BLOCK invalidates the buffer, it should produce "MASS STORAGE NOT READ".

However, 7.3.2 contains some caveats about buffer invalidation, including at REFILL and parsing. Given that there is parsing and refilling happening from the text interpreter between these calls, the buffer may be invalidated, and BLOCK may read the block from mass storage, resulting in "MASS STORAGE READ".

Actually, there is parsing between the first call to BUFFER and the UPDATE, so there is no guarantee that "MASS STORAGE READ" reaches mass storage.

The way to deal with that is to UPDATE inside PREPARE_BUFFER.

AFAIK these provisions are there for cooperative multi-tasking systems that may task-switch on REFILL (and apparently also on parsing), and where a different task might require a buffer, which might invalidate an existing buffer.

Closed
Reply New Version