[comp.sys.amiga.tech] Proposal for new DOS calls

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (11/08/88)

	There are several lackings in DOS that make interactive handling of
file handles difficult.  For one, there is no way to determine whether data
is pending (e.g. via SER: AUX:, interactive PIPE: etc...) without calling
Read() or WaitForChar().  Neither of these methods are acceptable as
both will block or require busy waiting.  

	I propose the following additional calls.  Since these are in the
domain of DOS packets, you simply get an error if the DOS device does not
support them.  All calls would be implemented via ACTION_<blahblah> on
the packet level.  The actual assignment of id numbers is not pertainent at 
this point.

	fh = some file handle

	Note on Read() calls.  Since 0 is an acceptable return value when
a handle is set to non-blocking, -1 is used to indicate an EOF condition.
either -1 or 0 indicate an EOF condition if the handle is set to blocking.
Use IoErr() to determine whether it is an EOF or error.

				-Matt

mask = Capabilities(fh)

	Return a mask of capabilities provided by this file handle.  I.E.
	each bit is assigned to one of the calls below where a '1' indicates
	the call is implemented and a '0' indicates the call is not.  This
	is a quick way to ensure you can do what you want to do with the 
	handle.

bool = SetRBlockMode(fh, mode)

	0- return less than requested or 0 if no/little read data available
 (def)	1- block if no read data available
	2- (atomic non-blocking): either read everything or nothing.
	   i.e. if you request 30 bytes and only 20 are ready, the call
	   returns 0.

bool = SetWBlockMode(fh, mode)

	0- write less than requested or 0 if no/little buffer space available
	   for write.
 (def)	1- block until all data can be written
	2- (atomic non-blocking): either write everything or nothing.  i.e.
	   if you want to write 30 bytes and it can only write 20, the call
	   returns 0.

bool = SetRSignal(fh, signo, amount)

	-1 disables the function.  Otherwise, set the signal # that should
	occur when read data is available.  This signal is also set when
	a Read() call fails to completely empty the buffer.  The signal
	is also set if Read() is called but the other end closed/shutdown
	(i.e. an exception condition).  The signal is cleared otherwise.

	The minimum amount of data present in the read buffer before you
	get signaled is also specified.  If larger than the read buffer
	it is chopped to the read buffer.  You will get signaled if less
	than this amount is available only if the other end has sent an EOF
	(by closing the channel or shutting it down).

bool = SetWSignal(fh, signo, amount)

	-1 disables the function.  Otherwise, set the signal # that should
	occur when write buffer space is available.  This signal is also
	set when a Write() call does not exhaust the buffer space.  This
	signal is also set when a Write() fails due to the other end
	having closed or shutdown.  The signal is cleared otherwise.

	The amount of space available to write may be set.  If larger than
	the buffer size, it is chopped to the buffer size.

amnt = GetRDataReady(fh)

	Return the number of bytes ready to be read, -1 if no bytes remain
	and the other end closed or shutdown.  This also sets the RSignal
	if >0 or -1 is returned, clears it if 0 is returned.

amnt = GetWSpaceAvail(fh)

	Return the number of bytes that can be written without blocking,
	-1 if the other end closed or shutdown.  This also sets the WSignal
	if >0 or -1 is returned, clears it if 0 is returned.

amnt = SetWBufSize(fh, amount)

	Set the write buffer size, in bytes.  The actual buffer size is 
	returned and may be different then what you request.

	Default: depends on handler.  Normally you can ignore the return
	value unless you are doing atomic IO, in which case the buffer
	has to be at least as big as the largest block you intend to write.

amnt = SetRBufSize(fh, amount)

	Set the read buffer size, in bytes.  The actual buffer size is
	returned and may be different then what you request.

	Default: depends on handler.  Same restrictions apply as for 
	SetWBufSize().

bool = ShutDown(fh, how)

	Shutdown (effectively send an EOF or refuse receive data), how =

	0	nop
	1	disallow further reads
	2	disallow further writes (send EOF)
	3	both

	TRUE is returned if the call is implemented, FALSE if not.

peter@sugar.uu.net (Peter da Silva) (11/08/88)

In article <8811072046.AA04999@postgres.Berkeley.EDU>, dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
> 	There are several lackings in DOS that make interactive handling of
> file handles difficult.  For one, there is no way to determine whether data
> is pending (e.g. via SER: AUX:, interactive PIPE: etc...) without calling
> Read() or WaitForChar().  Neither of these methods are acceptable as
> both will block or require busy waiting.  

What about the third method? Don't use the standard DOS calls, just send the
packets yourself. Then you can "Wait(1<<IOPort->mp_SigBit | WaitMask)" and
get a notice of completion when it's done.

You wrote a library to do this yourself, Matt. It's not a UNIX way of doing
things, true. It's a very Amiga way of working, though. About the only thing
you'd need dos.library for would be opening the file in the first place.

Be a lot simpler than your set of packets. Surely you can prune them somewhat.
-- 
		    Peter da Silva  `-_-'  peter@sugar.uu.net
		     Have you hugged  U  your wolf today?

	      Disclaimer: My typos are my own damn business.

peter@sugar.uu.net (Peter da Silva) (11/08/88)

The SetXSignal functions are redundant if you do your own packet handling
and provide your own message ports.
-- 
		    Peter da Silva  `-_-'  peter@sugar.uu.net
		     Have you hugged  U  your wolf today?

	      Disclaimer: My typos are my own damn business.

dale@boing.UUCP (Dale Luck) (11/09/88)

In article dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
>	There are several lackings in DOS that make interactive handling of
>file handles difficult.  For one, there is no way to determine whether data
>is pending (e.g. via SER: AUX:, interactive PIPE: etc...) without calling
>Read() or WaitForChar().

I agree, the DOS is lacking here. We need a consistent concept of
non-blocking i/o through files.

>bool = SetRBlockMode(fh, mode)
>	0- return less than requested or 0 if no/little read data available
> (def)	1- block if no read data available
>	2- (atomic non-blocking): either read everything or nothing.

I prefer '0' being the default mode, so maybe just renumbering is inorder.

>bool = SetRSignal(fh, signo, amount),bool = SetWSignal(fh, signo, amount)
>	-1 disables the function.  Otherwise, set the signal # that should
>	occur when read data is available.

Wow, is someone else trying to design a consistent select() call?

>amnt = GetRDataReady(fh) ,amnt = GetWSpaceAvail(fh)

All nice things I wish I had when writing my stdio support for X-Windows
and sockets.

>bool = ShutDown(fh, how)

So tell me, Matt, is your next project a socket library maybe?

-- 
Dale Luck     Boing, Inc. {uunet!cbmvax|pyramid}!amiga!boing!dale
Although I do contract work for Amiga-LosGatos, my opinions probably
don't represent those of Commodore or its management or its engineers,
but I think the world would be a better place if they did.

bader+@andrew.cmu.edu (Miles Bader) (11/09/88)

peter@sugar.uu.net (Peter da Silva) writes:
> The SetXSignal functions are redundant if you do your own packet handling
> and provide your own message ports.

I think the idea is to make the functionality available	*simply*!

Even if the functionality is already there, a standard interface at
the same level as the other dos functions is a good thing.  This
isn't something obscure, after all-- look how useful select (the
more-or-less analogue of SetXSIgnal/Wait) is in BSD.

-Miles

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (11/09/88)

>In article <8811072046.AA04999@postgres.Berkeley.EDU>, dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
>> 	There are several lackings in DOS that make interactive handling of
>> file handles difficult.  For one, there is no way to determine whether data
>> is pending (e.g. via SER: AUX:, interactive PIPE: etc...) without calling
>> Read() or WaitForChar().  Neither of these methods are acceptable as
>> both will block or require busy waiting.  

Peter da Silva  `-_-'  peter@sugar.uu.net Writes:
>What about the third method? Don't use the standard DOS calls, just send the
>packets yourself. Then you can "Wait(1<<IOPort->mp_SigBit | WaitMask)" and
>get a notice of completion when it's done.
...
>Be a lot simpler than your set of packets. Surely you can prune them somewhat.

	I disagree ... I've tried that method.  It is not compatible and
it doesn't work.  For one, you cannot make more then one DOS call pending
at a time, so between sending the packet and waiting for the reply you
can't make any DOS calls.  Now, I suppose you CAN make it go to a different
replyport, but a second problem exists:  You can't have more than one 
pending packet for a given file handle for a given process.  Reason:
Many device drivers can't handle it.  Specifically, the filesystem. 
Finally, you have to keep track of ports and messages and pending messages
and possibly other resources and free them yourself... they are far removed
from the DOS domain because they do not go away automatically with Close().

>Be a lot simpler than your set of packets. Surely you can prune them somewhat.

	Doing things manually gives you less control and certainly
is not simple in any sense of the word!  Very much more difficult, I would
say!
	One need not implement ALL the calls I proposed.  The basic three 
(capabilities, signal when read data present, signal when able to write) are 
usually sufficient.  Most of the others, except ShutDown(), are more
specialized.  ShutDown() *IS* a definate must when two interactive processes
communicate, sort of like saying "OK, I'm done sending stuff to you, 
finish up what you intend to send to me and then we'll close" rather than
"Close() = OK, I'm done sending stuff to you and I don't give a damn if
you still have stuff to send to me".  

				-Matt

dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) (11/09/88)

peter@sugar.uu.net (Peter da Silva) Writes:
>The SetXSignal functions are redundant if you do your own packet handling
>and provide your own message ports.

	No they aren't.  You cannot do certain things with your own packet
handling, even if you provide your own message ports.  Specifically, you
cannot implement both Reading AND Writing the handle at the same time
because this crashes most current day device drivers.  Also, my functions
include low (read) and high (write) water marks which are impossible to
duplicate your way:

	Another reason:  Sure, you can make your own packets pending, but
there is NO WAY TO ABORT THEM!  You *HAVE* to wait for something to happen!!!
YOU CANNOT CLOSE A FILE HANDLE WHILE OTHER PACKETS ARE PENDING ON IT!!!

	OK Pete, that last one is a very big item ... admit your defeat in
this particular bout!  "A time will come again for thee to take up thy
vocal prose".

					-Matt

gmg@hcx.uucp (Greg M. Garner) (11/09/88)

Matt, I agree with your proposed dos packets, but I would also like 
to see a simple way to implement the one that checks for characters
to be read (See if any are available) on the serial port. 
    I would like to be able to access the serial port like this:

fp=fopen("ser:","r");
   (error check here)

while( (status=any_chars_to_read(fp)) != 0)
     {
      c = getc(fp);
      do_stuff();
     }

do_other_stuff();

---------------------


Maybe there is a simple way to do this now, but I sure haven't found it
yet. I need to do this to be able to write a Eprom programmer driver,
( I use a B&C microsystems 1409C ).  I think I could implement the 
above using the serial device, but I really haven't gotten into the
devices and exec deeply enough to understand how to do it yet. Any
body out there have any good ideas? Thanks for any help!

   Greg Garner
   gmg@hcx.uucp    path:   ...!uunet!harris.cis.ksu.edu!hcx!gmg
     

dale@boing.UUCP (Dale Luck) (11/09/88)

In article <2966@sugar.uu.net> peter@sugar.uu.net (Peter da Silva) writes:
>
>What about the third method? Don't use the standard DOS calls, just send the
>packets yourself. Then you can "Wait(1<<IOPort->mp_SigBit | WaitMask)" and
>get a notice of completion when it's done.
>
>You wrote a library to do this yourself, Matt. It's not a UNIX way of doing
>things, true. It's a very Amiga way of working, though. About the only thing
>you'd need dos.library for would be opening the file in the first place.
>
>Be a lot simpler than your set of packets. Surely you can prune them somewhat.
>-- 

I have to disagree. Programs doing this packet management instead
of some simple setup calls that control a basic set of orthogonal
functions is much simpler then managing a several sets of asynch packets
that have been sent to multiple destinations.

Let's say you have sent several asynch packets to several destinations.
One comes back saying there is data there now. What do you do with the
outstanding packets? I need to cancel those packets and yank them back.

This get's all very messy, I know since I've written a library to try
to emulate nonblocking i/o that deals with several types of files and
the way to get at the information I need (like BytesReadable) is not
standardized. So we clearly need this information to be made available.

After looking at the way the unix libraries work and the packets in
amigados I have to say the unix stuff, being a library mechanism is
easier to program.
-- 
Dale Luck     Boing, Inc. {uunet!cbmvax|pyramid}!amiga!boing!dale
Although I do contract work for Amiga-LosGatos, my opinions probably
don't represent those of Commodore or its management or its engineers,
but I think the world would be a better place if they did.

peter@sugar.uu.net (Peter da Silva) (11/09/88)

In article <cXRn5Ey00UkaITS7RF@andrew.cmu.edu>, bader+@andrew.cmu.edu (Miles Bader) writes:
> peter@sugar.uu.net (Peter da Silva) writes:
> > The SetXSignal functions are redundant if you do your own packet handling
> > and provide your own message ports.

> I think the idea is to make the functionality available	*simply*!

This is what Matt has started to do with his xio stuff, a set of routines
that give pretty clean asynchronous access to the current DOS calls and
allow you to implement "select()" (or poll() or whatever) without changing
the existing DOS software. He uses them in his terminal program, DTerm...
another Dillon product I recommend highly.
-- 
		    Peter da Silva  `-_-'  peter@sugar.uu.net
		     Have you hugged  U  your wolf today?

	      Disclaimer: My typos are my own damn business.

peter@sugar.uu.net (Peter da Silva) (11/09/88)

In article <8811082053.AA26882@postgres.Berkeley.EDU>, dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
> 	I disagree ... I've tried that method.  It is not compatible and
> it doesn't work.

It seems to work in DTerm... (plug).

> Now, I suppose you CAN make it go to a different
> replyport, but a second problem exists:  You can't have more than one 
> pending packet for a given file handle for a given process.  Reason:
> Many device drivers can't handle it.  Specifically, the filesystem. 

This is a problem that needs to be addressed. It's not a fatal failure,
since I'd expect you'd want to use this to monitor multiple files. It'd
make it hard to do a write while you have a read outstanding, though. Can
you open the file (device) twice and get two handles on it?

> Finally, you have to keep track of ports and messages and pending messages
> and possibly other resources and free them yourself... they are far removed
> from the DOS domain because they do not go away automatically with Close().

This is the major part of the excersize... providing a library that gives you
the functionality of dos.library. Your "file handle" would be a pointer to
your DOS filehandle, message port, and pending message. You'd have to provide
some sort of locking. You'd have to provide a close routine that took care
of all this.

But you'd have to do much of this work to implement these extra DOS calls
anyway, wouldn't you?

> 	Doing things manually gives you less control and certainly
> is not simple in any sense of the word!

I do things manually in a couple of places in Browser, and it's not that hard.
It's harder to send a packet than call Rename, but it gives me more control...
I can specify a lock on the source *and* destination directories.

> Very much more difficult, I would say!

It's more difficult to write the library in the first place. I don't see how
it can be that hard for individual users to use it when it's written. Sure,
they'd have to call your Close and your Open and so on, but these routines
could be made transparent. Just link with your library ahead of the dos.library
stubs and even printf() would work. Build your sockets on top of this...

And if you do it cleverly enough you'd make it possible to do DOS stuff from
tasks!
-- 
		    Peter da Silva  `-_-'  peter@sugar.uu.net
		     Have you hugged  U  your wolf today?

	      Disclaimer: My typos are my own damn business.

peter@sugar.uu.net (Peter da Silva) (11/09/88)

In article <8811082059.AA26891@postgres.Berkeley.EDU>, dillon@POSTGRES.BERKELEY.EDU (Matt Dillon) writes:
> 	Another reason:  Sure, you can make your own packets pending, but
> there is NO WAY TO ABORT THEM!  You *HAVE* to wait for something to happen!!!
> YOU CANNOT CLOSE A FILE HANDLE WHILE OTHER PACKETS ARE PENDING ON IT!!!

How big a problem is this, really? Just make Close mark the file handle for
deletion and string it on a list that you'll clean up before you exit.

> 	OK Pete, that last one is a very big item ... admit your defeat in
> this particular bout!

I wasn't aware we were fighting. I was just trying to suggest a way you could
solve your problems without waiting for CATS and AmigaOS 1.4. I guess you're
going to have to wait for drivers that can handle simultaneous reads and
writes, but I got the impression you're writing one of those yourself. If
you check first to see if it can handle it before going ahead and trying to
do the I/O then there's a workaround.

You didn't make your goals clear... you're trying to implement sockets. A
laudable goal, and it might well need all the baggage you're describing. It
wasn't obvious to those of us who haven't used sockets... I'm used to doing
IPC on real-time operating systems and the Amiga model is very close to the
ones I'm used to.
-- 
		    Peter da Silva  `-_-'  peter@sugar.uu.net
		     Have you hugged  U  your wolf today?

	      Disclaimer: My typos are my own damn business.