mirror of
https://github.com/ksherlock/marignotti.git
synced 2024-12-02 06:49:21 +00:00
fix select(2)
This commit is contained in:
parent
d8ec9c1962
commit
7e6b2824d3
180
mselect.c
180
mselect.c
@ -1,6 +1,7 @@
|
||||
#include "marignotti.h"
|
||||
#include <gno/kerntool.h>
|
||||
#include <errno.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include "s16debug.h"
|
||||
|
||||
@ -11,14 +12,79 @@
|
||||
* return value is ignored.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* select is rather ugly...
|
||||
* listen and connect pass in a select wakeup function which
|
||||
* takes two parameters, a collision flag and the pid to awaken.
|
||||
*
|
||||
* when select is called, it returns immediately, in the affirmative
|
||||
* if possible. Otherwise, it stores the pid and the collision flag.
|
||||
* When the condition is met, the select wakeup function is called
|
||||
* and the pid and collision flag are cleared.
|
||||
*
|
||||
* exceptions (which really mean OOB) are not supported.
|
||||
* write currently always returns immediately, in the affirmative.
|
||||
* for a server, "read" means a connection is pending.
|
||||
* otherwise, it means the read will not block (ie, data is available
|
||||
* or the connection has closed.
|
||||
*
|
||||
* this is all based on looking at the select.asm and driver source
|
||||
* code, so it could be wrong...
|
||||
*/
|
||||
|
||||
|
||||
static boolean readable(Entry *e)
|
||||
boolean readable(Entry *e)
|
||||
{
|
||||
|
||||
Word state;
|
||||
Word terr;
|
||||
Word t;
|
||||
|
||||
state = e->sr.srState;
|
||||
|
||||
// hmm.. read will return 0 immediately.
|
||||
if (e->_SHUT_RD)
|
||||
return false;
|
||||
|
||||
if (e->sr.srState > TCPSESTABLISHED && e->sr.srRcvQueued)
|
||||
return true;
|
||||
|
||||
if (e->_TYPE == SOCK_DGRAM)
|
||||
{
|
||||
Word count;
|
||||
/*
|
||||
udpVars uv;
|
||||
IncBusy();
|
||||
TCPIPStatusUDP(e->ipid, &uv);
|
||||
//t = _toolErr;
|
||||
DecBusy();
|
||||
|
||||
return uv.uvQueueSize > 0;
|
||||
*/
|
||||
IncBusy();
|
||||
count = TCPIPGetDatagramCount(e->ipid, protocolUDP);
|
||||
DecBusy();
|
||||
|
||||
return count > 0;
|
||||
}
|
||||
|
||||
|
||||
IncBusy();
|
||||
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
||||
t = _toolErr;
|
||||
if (t) terr = t;
|
||||
e->terr = terr;
|
||||
DecBusy();
|
||||
|
||||
// for a server, "read" means "accept".
|
||||
if (state == TCPSLISTEN)
|
||||
{
|
||||
return e->sr.srAcceptCount > 0;
|
||||
}
|
||||
|
||||
// eof means readable.
|
||||
if (state == TCPSCLOSED || state > TCPSESTABLISHED)
|
||||
return true;
|
||||
|
||||
|
||||
if (e->sr.srRcvQueued >= e->_RCVLOWAT)
|
||||
return true;
|
||||
@ -42,29 +108,8 @@ static boolean writable(Entry *e)
|
||||
|
||||
static boolean exceptable(Entry *e)
|
||||
{
|
||||
|
||||
switch (e->terr)
|
||||
{
|
||||
case tcperrOK:
|
||||
break;
|
||||
case tcperrConClosing:
|
||||
case tcperrClosing:
|
||||
case tcperrConReset:
|
||||
if (!e->sr.srRcvQueued)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (e->sr.srRcvQueued)
|
||||
return false;
|
||||
|
||||
if (e->sr.srNetworkError)
|
||||
return true;
|
||||
|
||||
if (e->sr.srState > TCPSESTABLISHED)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
return 0;
|
||||
// never.
|
||||
}
|
||||
|
||||
int mselect(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
@ -74,57 +119,50 @@ int mselect(Entry *e, void *p1, void *p2, void *p3, void *p4, void *p5)
|
||||
|
||||
int pid = *(int *)p2;
|
||||
int flag = *(int *)p3;
|
||||
|
||||
*(int *)p3 = 0;
|
||||
int *outflag = (int *)p3;
|
||||
|
||||
*outflag = 0;
|
||||
|
||||
|
||||
if (Debug > 0)
|
||||
{
|
||||
s16_debug_printf("select pid = %5d flag = %d", pid, flag);
|
||||
s16_debug_printf("select pid = %d flag = %d", pid, flag);
|
||||
}
|
||||
|
||||
IncBusy();
|
||||
terr = TCPIPStatusTCP(e->ipid, &e->sr);
|
||||
t = _toolErr;
|
||||
if (t) terr = t;
|
||||
e->terr = terr;
|
||||
DecBusy();
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
if (readable(e))
|
||||
{
|
||||
*outflag = 1;
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
//always writable. [?]
|
||||
*outflag = 1;
|
||||
return 0;
|
||||
break;
|
||||
case 2:
|
||||
// no exceptions.
|
||||
return 0;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// main loop will call sel flag when readable.
|
||||
|
||||
SEI();
|
||||
|
||||
if (e->select_rd_pid == 0xffff)
|
||||
e->select_rd_pid = pid;
|
||||
else if (e->select_rd_pid != pid)
|
||||
e->select_rd_collision = 1;
|
||||
|
||||
if (e->sr.srState == TCPSLISTEN)
|
||||
{
|
||||
// for a listen socket, "read" means "accept".
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
if (e->sr.srAcceptCount)
|
||||
*(int *)p3 = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (flag)
|
||||
{
|
||||
case 0:
|
||||
// readable.
|
||||
*(int *)p3 = readable(e);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// writable.
|
||||
*(int *)p3 = writable(e);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
// exception.
|
||||
*(int *)p3 = exceptable(e);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
CLI();
|
||||
|
||||
return 0;
|
||||
}
|
46
table.c
46
table.c
@ -8,6 +8,9 @@
|
||||
#pragma optimize 79
|
||||
#pragma noroot
|
||||
|
||||
|
||||
extern boolean readable(Entry *e);
|
||||
|
||||
#define TABLE_SIZE 16
|
||||
#define TABLE_MASK 15
|
||||
static struct Entry *table[TABLE_SIZE];
|
||||
@ -106,7 +109,10 @@ Entry *create_entry(Word ipid)
|
||||
e->_OOBINLINE = 1;
|
||||
e->_SNDLOWAT = 1024;
|
||||
e->_RCVLOWAT = 1;
|
||||
|
||||
|
||||
e->select_rd_pid = 0xffff;
|
||||
e->select_wr_pid = 0xffff;
|
||||
|
||||
SEI();
|
||||
e->next = table[ipid & TABLE_MASK];
|
||||
table[ipid & TABLE_MASK] = e;
|
||||
@ -136,6 +142,39 @@ void process_table(void)
|
||||
Word command;
|
||||
next = e->next;
|
||||
|
||||
|
||||
// select.
|
||||
// do this first ... a close would invalidate.
|
||||
if (e->select_rd_pid != 0xffff)
|
||||
{
|
||||
if (readable(e))
|
||||
{
|
||||
Word coll;
|
||||
Word pid;
|
||||
|
||||
SEI()
|
||||
|
||||
coll = e->select_rd_collision;
|
||||
pid = e->select_rd_pid;
|
||||
|
||||
e->select_rd_pid = 0xffff;
|
||||
e->select_rd_collision = 0;
|
||||
|
||||
CLI()
|
||||
if (e->select_fx)
|
||||
e->select_fx(coll, pid);
|
||||
|
||||
if (Debug > 0)
|
||||
{
|
||||
s16_debug_printf("select/read wakeup.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
command = e->command;
|
||||
if (command)
|
||||
{
|
||||
@ -241,7 +280,10 @@ void process_table(void)
|
||||
|
||||
DecBusy();
|
||||
} // e->command
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
if (e) prev = e;
|
||||
e = next;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user