Reenterant code means that more than one thread can call it at once. Non-reenterant code will potentially hang if it is called by more than one thread at once.
This chunk of code makes select() reenterant, just call __select() in place of select().
(Note: This forum blocks out tabs, that is why this looks funny.)
/////////////////////////////////////
static BOOL _bSelectInitialized = FALSE;
static TX_MUTEX _mutexBuffer;
#ifndef howmany
define howmany(x,y) (((x)+((y)-1))/(y))
#endif
int qselect(int width, fd_set * readset, fd_set * writeset, fd_set * exceptset)
{
struct timeval tv;
int ret;
// Make sure the mutex is initialized
if( !_bSelectInitialized )
{
UINT status = tx_mutex_create(&_mutexBuffer, "SELECTMUTEX", TX_NO_INHERIT );
_bSelectInitialized = TRUE;
}
// Wait for my turn
tx_mutex_get(&_mutexBuffer, TX_WAIT_FOREVER);
tv.tv_sec = 0;
tv.tv_usec = 8;
errno = EAGAIN;
ret = select(width, readset, writeset, exceptset, &tv);
// my turn is up
tx_mutex_put(&_mutexBuffer);
if( ret >= 0 )
errno = 0;
return ret;
}
int __select(int width, fd_set * readset, fd_set * writeset, fd_set * exceptset, struct timeval * timeout)
{
long countdown;
int ret;
if( timeout )
{
countdown = timeout->tv_sec*1000;
if( timeout->tv_usec > 0 )
countdown += timeout->tv_usec/1000;
}
else
{
countdown = 0x7FFFFFFF;
}
if( countdown <= 10 )
{
return qselect(width, readset, writeset, exceptset);
}
// Loop in wait
fd_set rs, ws, es, *prs, *pws, *pes;
int fdsetsz = howmany((int)width, NFDBITS) * sizeof(fd_mask);
do
{
// Preserve the calling fd_set
prs = pws = pes = NULL;
if( readset )
{
prs = &rs;
memcpy(prs, readset, fdsetsz);
}
if( writeset )
{
pws = &ws;
memcpy(pws, writeset, fdsetsz);
}
if( exceptset )
{
pes = &es;
memcpy(pes, exceptset, fdsetsz);
}
// quickie socket check
ret = qselect(width, prs, pws, pes);
// Have something besides a timeout?
if( ret != 0 )
{
// copy 'em back
if( readset )
memcpy(readset, prs, fdsetsz);
if( writeset )
memcpy(writeset, pws, fdsetsz);
if( exceptset )
memcpy(exceptset, pes, fdsetsz);
// return it
return ret;
}
// wait 50ms to let other threads do their thing
tx_thread_sleep(5);
countdown -= 50;
}
while( countdown > 0 );
if( readset )
memcpy(readset, prs, fdsetsz);
if( writeset )
memcpy(writeset, pws, fdsetsz);
if( exceptset )
memcpy(exceptset, pes, fdsetsz);
return 0;
}
Message was edited by: egawtry