sched: don't keep prepared fd_set
Instead of copying a prepared fd_set to the fd_set used by select(), fill it from scratch according to the array of file handlers before each select() call. This should make the code simpler and save some memory when other events are supported.
This commit is contained in:
parent
0a10545314
commit
d8d096aa54
1 changed files with 65 additions and 49 deletions
114
sched.c
114
sched.c
|
@ -44,17 +44,6 @@ static int initialised = 0;
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
/* Variables to handle the capability to dispatch on particular file
|
||||
handles becoming readable */
|
||||
|
||||
/* Each bit set in this fd set corresponds to a read descriptor that
|
||||
we are watching and with which we have a handler associated in the
|
||||
file_handlers array */
|
||||
static fd_set read_fds;
|
||||
|
||||
/* This is the number of bits that we have set in read_fds */
|
||||
static unsigned int n_read_fds;
|
||||
|
||||
/* One more than the highest file descriptor that is registered */
|
||||
static unsigned int one_highest_fd;
|
||||
|
||||
|
@ -67,6 +56,7 @@ static unsigned int one_highest_fd;
|
|||
typedef struct {
|
||||
SCH_FileHandler handler;
|
||||
SCH_ArbitraryArgument arg;
|
||||
int events;
|
||||
} FileHandlerEntry;
|
||||
|
||||
static ARR_Instance file_handlers;
|
||||
|
@ -132,9 +122,6 @@ handle_slew(struct timeval *raw,
|
|||
void
|
||||
SCH_Initialise(void)
|
||||
{
|
||||
FD_ZERO(&read_fds);
|
||||
n_read_fds = 0;
|
||||
|
||||
file_handlers = ARR_CreateInstance(sizeof (FileHandlerEntry));
|
||||
|
||||
n_timer_queue_entries = 0;
|
||||
|
@ -178,26 +165,27 @@ SCH_AddFileHandler
|
|||
if (fd >= FD_SETSIZE)
|
||||
LOG_FATAL(LOGF_Scheduler, "Too many file descriptors");
|
||||
|
||||
/* Resize the array if the descriptor is highest so far */
|
||||
while (ARR_GetSize(file_handlers) <= fd) {
|
||||
ptr = ARR_GetNewElement(file_handlers);
|
||||
ptr->handler = NULL;
|
||||
ptr->arg = NULL;
|
||||
ptr->events = 0;
|
||||
}
|
||||
|
||||
ptr = ARR_GetElement(file_handlers, fd);
|
||||
|
||||
/* Don't want to allow the same fd to register a handler more than
|
||||
once without deleting a previous association - this suggests
|
||||
a bug somewhere else in the program. */
|
||||
if (FD_ISSET(fd, &read_fds))
|
||||
assert(0);
|
||||
assert(!ptr->handler);
|
||||
|
||||
++n_read_fds;
|
||||
|
||||
if (ARR_GetSize(file_handlers) < fd + 1)
|
||||
ARR_SetSize(file_handlers, fd + 1);
|
||||
|
||||
ptr = (FileHandlerEntry *)ARR_GetElement(file_handlers, fd);
|
||||
ptr->handler = handler;
|
||||
ptr->arg = arg;
|
||||
ptr->events = events;
|
||||
|
||||
FD_SET(fd, &read_fds);
|
||||
|
||||
if ((fd + 1) > one_highest_fd) {
|
||||
if (one_highest_fd < fd + 1)
|
||||
one_highest_fd = fd + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -206,29 +194,26 @@ SCH_AddFileHandler
|
|||
void
|
||||
SCH_RemoveFileHandler(int fd)
|
||||
{
|
||||
int fds_left, fd_to_check;
|
||||
FileHandlerEntry *ptr;
|
||||
|
||||
assert(initialised);
|
||||
|
||||
ptr = ARR_GetElement(file_handlers, fd);
|
||||
|
||||
/* Check that a handler was registered for the fd in question */
|
||||
if (!FD_ISSET(fd, &read_fds))
|
||||
assert(0);
|
||||
assert(ptr->handler);
|
||||
|
||||
--n_read_fds;
|
||||
|
||||
FD_CLR(fd, &read_fds);
|
||||
ptr->handler = NULL;
|
||||
ptr->arg = NULL;
|
||||
ptr->events = 0;
|
||||
|
||||
/* Find new highest file descriptor */
|
||||
fds_left = n_read_fds;
|
||||
fd_to_check = 0;
|
||||
while (fds_left > 0) {
|
||||
if (FD_ISSET(fd_to_check, &read_fds)) {
|
||||
--fds_left;
|
||||
}
|
||||
++fd_to_check;
|
||||
while (one_highest_fd > 0) {
|
||||
ptr = ARR_GetElement(file_handlers, one_highest_fd - 1);
|
||||
if (ptr->handler)
|
||||
break;
|
||||
one_highest_fd--;
|
||||
}
|
||||
|
||||
one_highest_fd = fd_to_check;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
@ -595,6 +580,38 @@ handle_slew(struct timeval *raw,
|
|||
|
||||
/* ================================================== */
|
||||
|
||||
static void
|
||||
fill_fd_sets(fd_set **read_fds)
|
||||
{
|
||||
FileHandlerEntry *handlers;
|
||||
fd_set *rd;
|
||||
int i, n, events;
|
||||
|
||||
n = ARR_GetSize(file_handlers);
|
||||
handlers = ARR_GetElements(file_handlers);
|
||||
rd = NULL;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
events = handlers[i].events;
|
||||
|
||||
if (!events)
|
||||
continue;
|
||||
|
||||
if (events & SCH_FILE_INPUT) {
|
||||
if (!rd) {
|
||||
rd = *read_fds;
|
||||
FD_ZERO(rd);
|
||||
}
|
||||
FD_SET(i, rd);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rd)
|
||||
*read_fds = NULL;
|
||||
}
|
||||
|
||||
/* ================================================== */
|
||||
|
||||
#define JUMP_DETECT_THRESHOLD 10
|
||||
|
||||
static int
|
||||
|
@ -650,7 +667,7 @@ check_current_time(struct timeval *prev_raw, struct timeval *raw, int timeout,
|
|||
void
|
||||
SCH_MainLoop(void)
|
||||
{
|
||||
fd_set rd;
|
||||
fd_set read_fds, *p_read_fds;
|
||||
int status, errsv;
|
||||
struct timeval tv, saved_tv, *ptv;
|
||||
struct timeval now, saved_now, cooked;
|
||||
|
@ -681,16 +698,15 @@ SCH_MainLoop(void)
|
|||
saved_tv.tv_sec = 0;
|
||||
}
|
||||
|
||||
p_read_fds = &read_fds;
|
||||
fill_fd_sets(&p_read_fds);
|
||||
|
||||
/* if there are no file descriptors being waited on and no
|
||||
timeout set, this is clearly ridiculous, so stop the run */
|
||||
if (!ptv && !n_read_fds) {
|
||||
if (!ptv && !p_read_fds)
|
||||
LOG_FATAL(LOGF_Scheduler, "Nothing to do");
|
||||
}
|
||||
|
||||
/* Copy current set of read file descriptors */
|
||||
memcpy((void *) &rd, (void *) &read_fds, sizeof(fd_set));
|
||||
|
||||
status = select(one_highest_fd, &rd, NULL, NULL, ptv);
|
||||
status = select(one_highest_fd, p_read_fds, NULL, NULL, ptv);
|
||||
errsv = errno;
|
||||
|
||||
LCL_ReadRawTime(&now);
|
||||
|
@ -713,7 +729,7 @@ SCH_MainLoop(void)
|
|||
} else if (status > 0) {
|
||||
/* A file descriptor is ready to read */
|
||||
|
||||
dispatch_filehandlers(status, &rd);
|
||||
dispatch_filehandlers(status, &read_fds);
|
||||
|
||||
} else {
|
||||
/* No descriptors readable, timeout must have elapsed.
|
||||
|
|
Loading…
Reference in a new issue