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.