void VTIM_sleep(double t) { #ifdef HAVE_NANOSLEEP struct timespec ts; ts = VTIM_timespec(t); (void)nanosleep(&ts, NULL); #else if (t >= 1.) { (void)sleep(floor(t)); t -= floor(t); } /* XXX: usleep() is not mandated to be thread safe */ t *= 1e6; if (t > 0) (void)usleep(floor(t)); #endif }
static void * vws_thread(void *priv) { struct sess *sp; struct vws *vws; CAST_OBJ_NOTNULL(vws, priv, VWS_MAGIC); /* * timeouts: * * min_ts : Minimum timeout for port_getn * min_t : ^ equivalent in floating point representation * * max_ts : Maximum timeout for port_getn * max_t : ^ equivalent in floating point representation * * with (nevents == 1), we should always choose the correct port_getn * timeout to check session timeouts, so max is just a safety measure * (if this implementation is correct, it could be set to an "infinte" * value) * * with (nevents > 1), min and max define the acceptable range for * - additional latency of keep-alive connections and * - additional tolerance for handling session timeouts * */ static struct timespec min_ts = {0L, 100L /*ms*/ * 1000L /*us*/ * 1000L /*ns*/}; static double min_t = 0.1; /* 100 ms*/ static struct timespec max_ts = {1L, 0L}; /* 1 second */ static double max_t = 1.0; /* 1 second */ /* XXX: These should probably go in vws ? */ struct timespec ts; struct timespec *timeout; vws->dport = port_create(); assert(vws->dport >= 0); timeout = &max_ts; while (1) { port_event_t ev[MAX_EVENTS]; int nevents, ei, ret; double now, deadline; /* * XXX Do we want to scale this up dynamically to increase * efficiency in high throughput situations? - would need to * start with one to keep latency low at any rate * * Note: when increasing nevents, we must lower min_ts * and max_ts */ nevents = 1; /* * see disucssion in * - https://issues.apache.org/bugzilla/show_bug.cgi?id=47645 * - http://mail.opensolaris.org/pipermail/networking-discuss/2009-August/011979.html * * comment from apr/poll/unix/port.c : * * This confusing API can return an event at the same time * that it reports EINTR or ETIME. * */ ret = port_getn(vws->dport, ev, MAX_EVENTS, &nevents, timeout); if (ret < 0) assert((errno == EINTR) || (errno == ETIME)); for (ei = 0; ei < nevents; ei++) vws_port_ev(vws, ev + ei); /* check for timeouts */ now = VTIM_real(); deadline = now - cache_param->sess_timeout; /* * This loop assumes that the oldest sessions are always at the * beginning of the list (which is the case if we guarantee to * enqueue at the tail only * */ for (;;) { sp = VTAILQ_FIRST(&vws->sesshead); if (sp == NULL) break; if (sp->t_open > deadline) { break; } VTAILQ_REMOVE(&vws->sesshead, sp, list); if(sp->fd != -1) { vws_del(vws, sp->fd); } SES_Delete(sp, "timeout"); } /* * Calculate the timeout for the next get_portn */ if (sp) { double tmo = (sp->t_open + cache_param->sess_timeout) - now; /* we should have removed all sps whose timeout has passed */ assert(tmo > 0.0); if (tmo < min_t) { timeout = &min_ts; } else if (tmo > max_t) { timeout = &max_ts; } else { ts = VTIM_timespec(tmo); timeout = &ts; } } else { timeout = &max_ts; } } }