Problem with Socket under Linux...
John M McIntosh
johnmci at smalltalkconsulting.com
Sun Apr 28 01:00:28 UTC 2002
>don't exactly help. I just don't understand a word of what you're trying
>to say. It may be that I'm just no native speaker but I just can't
>figure out what that is supposed to mean ;-(
>
>Cheers,
> - Andreas
Well there is always the source code to look at, both the mac and the
unix code, two different implementations in fact. Besides even with
perhaps incomprehensible documentation it's a step up from lots of
the code which has *no* documentation.
However I think what would be really interesting here is to change
both the smalltalk code and the vm code to use what Craig did in
Flow. Pass a method based semaphore down to the primitive call in
question. It gets signaled once, or never on a timeout condition.
Perhaps this is a cleaner solution.
But is there any interest in doing it?
At 1:29 AM +0200 4/28/02, Andreas Raab wrote:
>Also, I've been over your description many times and I just could not
>understand into what more common (e.g., BSD) terms most of it
>translates. Formulations like:
>
> > The Read Semaphore is signaled when data arrives at
> > the interrupt level for a socket and the trigger is true,
> > the trigger is reset.The Read Semaphore trigger is set when
> > the user calls sqlSocketReceiveDataAvailable and we do NOT have
> > any data waiting to be read we of course return false from the
>routine.
>
>don't exactly help. I just don't understand a word of what you're trying
>to say.
Well let's look at the bsd unix code. I see pendingEvents contains
the mask bits for the triggers, or my interest in having a semaphore
signaled. The Mac VM will buffer incoming data until squeak reads it,
so having the semaphore signaled a dozen times before we actually
read things is counter productive so a "trigger" or indicator to
indicate which semaphore should be signaled once was introduced,
perhaps passing a semaphore around might be cleaner?
from the unix code.
/* answer whether the socket has data available for reading */
int sqSocketReceiveDataAvailable(SocketPtr s)
{
if (!socketValid(s))
return false; //This was -1, but I believe that was shown to be incorrect
if (SOCKETSTATE(s) == Connected)
{
if (socketReadable(SOCKET(s)))
return true;
PSP(s)->pendingEvents|= READ_NOTIFY;
aioHandle(SOCKET(s), dataHandler, PSP(s), AIO_RW);
}
return false;
}
"The Read Semaphore trigger is set when the user calls
sqlSocketReceiveDataAvailable and we do NOT have any data waiting to
be read"
That happens at PSP(s)->pendingEvents|= READ_NOTIFY; after confirming
the socket is not readable, versus of course taking the return true;
>and we do NOT have
> any data waiting to be read we of course return false from the routine.
the routine does return false; versus the return true after
confirming the socket is not readable. to continue lets look at
/*** asynchronous io handlers ***/
/* Each handler must at least:
* - suspend further handling for the associated socket
* - signal its semaphore to indicate that the operation is complete
*/
void notify(privateSocketStruct *pss, int eventMask)
{
int mask= pss->pendingEvents | eventMask;
if (mask & CONN_NOTIFY)
interpreterProxy->signalSemaphoreWithIndex((pss)->connSema);
if (mask & READ_NOTIFY)
interpreterProxy->signalSemaphoreWithIndex((pss)->readSema);
if (mask & WRITE_NOTIFY)
interpreterProxy->signalSemaphoreWithIndex((pss)->writeSema);
pss->pendingEvents= 0;
}
Note the if (mask & READ_NOTIFY) that completes the
>The Read Semaphore is signaled when data arrives at
> > the interrupt level for a socket and the trigger is true,
> the trigger is reset
which is the reset piece.
pss->pendingEvents= 0;
But I'll note Ian changed the code a few days ago to
void notify(privateSocketStruct *pss, int eventMask)
{
int mask= pss->pendingEvents & eventMask;
if (mask & CONN_NOTIFY)
interpreterProxy->signalSemaphoreWithIndex((pss)->connSema);
if (mask & READ_NOTIFY)
interpreterProxy->signalSemaphoreWithIndex((pss)->readSema);
if (mask & WRITE_NOTIFY)
interpreterProxy->signalSemaphoreWithIndex((pss)->writeSema);
pss->pendingEvents&= ~mask;
}
I'd bet turning off all the bits via pss->pendingEvents= 0; is wrong,
since my description states "and the trigger is true, the trigger is
reset." done by pss->pendingEvents&= ~mask; (no?) versus resetting
all the triggers (=0).
the notify gets called from
/* read or write data transfer is now possible for the socket */
static void dataHandler(void *pssIn, int readFlag, int writeFlag, int errFlag)
{
privateSocketStruct *pss = (privateSocketStruct *)pssIn;
sockSuspend(pss);
FPRINTF((stderr, "dataHandler(%d,%d,%d)\n", pss->s, errFlag, readFlag));
if (errFlag)
/* error: almost certainly "connection closed by peer" */
pss->sockState= OtherEndClosed;
notify(pss, (readFlag ? READ_NOTIFY : WRITE_NOTIFY));
}
which was set via the aioHandle in the sqSocketReceiveDataAvailable.
I'd guess that is the "data arrives at the interrupt level for a
socket" part of equation.
Mmm I'll admit I'm not a doc writer, so if someone who is a doc
writer wants to take the mac and unix code and the docs and create a
easy to understand swiki of the magic that is going on. I'll help in
the translation.
--
--
===========================================================================
John M. McIntosh <johnmci at smalltalkconsulting.com> 1-800-477-2659
Corporate Smalltalk Consulting Ltd. http://www.smalltalkconsulting.com
===========================================================================
More information about the Squeak-dev
mailing list
|