Skip to content

Commit 590a150

Browse files
author
Erik Rozendaal
committed
netio.c: Lazily call gettimeofday(2). Usually gettimeofday(2) is only
needed when there are active TCP connections. git-svn-id: file:///svn/nsd/trunk@1189 a26ef69c-88ff-0310-839f-98b793d9c207
1 parent 927ac38 commit 590a150

File tree

3 files changed

+44
-23
lines changed

3 files changed

+44
-23
lines changed

netio.c

+26-15
Original file line numberDiff line numberDiff line change
@@ -90,13 +90,28 @@ netio_remove_handler(netio_type *netio, netio_handler_type *handler)
9090
}
9191
}
9292

93+
const struct timespec *
94+
netio_current_time(netio_type *netio)
95+
{
96+
assert(netio);
97+
98+
if (!netio->have_current_time) {
99+
struct timeval current_timeval;
100+
if (gettimeofday(&current_timeval, NULL) == -1) {
101+
return NULL;
102+
}
103+
timeval_to_timespec(&netio->cached_current_time, &current_timeval);
104+
netio->have_current_time = 1;
105+
}
106+
107+
return &netio->cached_current_time;
108+
}
109+
93110
int
94111
netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t *sigmask)
95112
{
96113
fd_set readfds, writefds, exceptfds;
97114
int max_fd;
98-
struct timeval current_timeval;
99-
struct timespec current_time;
100115
int have_timeout = 0;
101116
struct timespec minimum_timeout;
102117
netio_handler_type *timeout_handler = NULL;
@@ -107,14 +122,10 @@ netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t
107122
assert(netio);
108123

109124
/*
110-
* Retrieve the current time to convert all absolute handler
111-
* timeouts to a relative timeout.
125+
* Clear the cached current time.
112126
*/
113-
if (gettimeofday(&current_timeval, NULL) == -1) {
114-
return -1;
115-
}
116-
timeval_to_timespec(&current_time, &current_timeval);
117-
127+
netio->have_current_time = 0;
128+
118129
/*
119130
* Initialize the minimum timeout with the timeout parameter.
120131
*/
@@ -153,7 +164,7 @@ netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t
153164

154165
relative.tv_sec = handler->timeout->tv_sec;
155166
relative.tv_nsec = handler->timeout->tv_nsec;
156-
timespec_subtract(&relative, &current_time);
167+
timespec_subtract(&relative, netio_current_time(netio));
157168

158169
if (!have_timeout ||
159170
timespec_compare(&relative, &minimum_timeout) < 0)
@@ -186,11 +197,11 @@ netio_dispatch(netio_type *netio, const struct timespec *timeout, const sigset_t
186197
return -1;
187198
}
188199

189-
/* Initialize the current time member of netio. */
190-
if (gettimeofday(&current_timeval, NULL) == -1) {
191-
return -1;
192-
}
193-
timeval_to_timespec(&netio->current_time, &current_timeval);
200+
/*
201+
* Clear the cached current_time (pselect(2) may block for
202+
* some time so the cached value is likely to be old).
203+
*/
204+
netio->have_current_time = 0;
194205

195206
if (rc == 0) {
196207
/*

netio.h

+14-4
Original file line numberDiff line numberDiff line change
@@ -70,11 +70,16 @@ typedef struct netio_handler_list netio_handler_list_type;
7070
struct netio
7171
{
7272
/*
73-
* The current time, which is initialized just before the
74-
* event handlers are called. This structure member should be
75-
* considered read-only.
73+
* Cached value of the current time. The cached value is
74+
* cleared at the start of netio_dispatch to calculate the
75+
* relative timeouts of the event handlers and after calling
76+
* pselect(2) so handlers can use it to calculate a new
77+
* absolute timeout.
78+
*
79+
* Use netio_current_time() to read the current time.
7680
*/
77-
struct timespec current_time;
81+
int have_current_time;
82+
struct timespec cached_current_time;
7883

7984
/* Private. */
8085
region_type *region;
@@ -140,6 +145,11 @@ void netio_add_handler(netio_type *netio, netio_handler_type *handler);
140145
*/
141146
void netio_remove_handler(netio_type *netio, netio_handler_type *handler);
142147

148+
/*
149+
* Retrieve the current time (using gettimeofday(2).
150+
*/
151+
const struct timespec *netio_current_time(netio_type *netio);
152+
143153
/*
144154
* Check for events and dispatch them to the handlers. If TIMEOUT is
145155
* specified it specifies the maximum time to wait for an event to

server.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -747,7 +747,7 @@ handle_tcp_reading(netio_type *netio,
747747

748748
handler->timeout->tv_sec = TCP_TIMEOUT;
749749
handler->timeout->tv_nsec = 0L;
750-
timespec_add(handler->timeout, &netio->current_time);
750+
timespec_add(handler->timeout, netio_current_time(netio));
751751

752752
handler->event_types = NETIO_EVENT_WRITE | NETIO_EVENT_TIMEOUT;
753753
handler->event_handler = handle_tcp_writing;
@@ -842,7 +842,7 @@ handle_tcp_writing(netio_type *netio,
842842
/* Reset timeout. */
843843
handler->timeout->tv_sec = TCP_TIMEOUT;
844844
handler->timeout->tv_nsec = 0;
845-
timespec_add(handler->timeout, &netio->current_time);
845+
timespec_add(handler->timeout, netio_current_time(netio));
846846

847847
/*
848848
* Write data if/when the socket is writable
@@ -861,7 +861,7 @@ handle_tcp_writing(netio_type *netio,
861861

862862
handler->timeout->tv_sec = TCP_TIMEOUT;
863863
handler->timeout->tv_nsec = 0;
864-
timespec_add(handler->timeout, &netio->current_time);
864+
timespec_add(handler->timeout, netio_current_time(netio));
865865

866866
handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_TIMEOUT;
867867
handler->event_handler = handle_tcp_reading;
@@ -945,7 +945,7 @@ handle_accept(netio_type *netio,
945945
tcp_handler->timeout = region_alloc(tcp_region, sizeof(struct timespec));
946946
tcp_handler->timeout->tv_sec = TCP_TIMEOUT;
947947
tcp_handler->timeout->tv_nsec = 0L;
948-
timespec_add(tcp_handler->timeout, &netio->current_time);
948+
timespec_add(tcp_handler->timeout, netio_current_time(netio));
949949

950950
tcp_handler->user_data = tcp_data;
951951
tcp_handler->event_types = NETIO_EVENT_READ | NETIO_EVENT_TIMEOUT;

0 commit comments

Comments
 (0)