Exemple #1
0
int
sel_select(selector_t      *sel,
	   sel_send_sig_cb send_sig,
	   long            thread_id,
	   void            *cb_data,
	   struct timeval  *timeout)
{
    int             err;
    struct timeval  loc_timeout;
    sel_wait_list_t wait_entry;

    if (sel->have_timer_lock)
	sel->os_hnd->lock(sel->os_hnd, sel->timer_lock);
    process_timers(sel, (struct timeval *)(&loc_timeout));
    if (timeout) { 
	if (cmp_timeval((struct timeval *)(&loc_timeout), timeout) >= 0)
	    memcpy(&loc_timeout, timeout, sizeof(loc_timeout));
    }
    add_sel_wait_list(sel, &wait_entry, send_sig, cb_data, thread_id,
		      &loc_timeout);
    if (sel->have_timer_lock)
	sel->os_hnd->unlock(sel->os_hnd, sel->timer_lock);

    err = process_fds(sel, send_sig, thread_id, cb_data, &loc_timeout);

    if (sel->have_timer_lock)
	sel->os_hnd->lock(sel->os_hnd, sel->timer_lock);
    remove_sel_wait_list(sel, &wait_entry);
    if (sel->have_timer_lock)
	sel->os_hnd->unlock(sel->os_hnd, sel->timer_lock);
    return err;
}
static int
timeval_to_relative_ms(struct timeval * tv)
{
  struct timeval now;
  struct timeval dt;
  long long t;
  int r;

  gettimeofday(&now, NULL);
  r = cmp_timeval(tv, &now);
  if (r >= 0) {
    timersub(tv, &now, &dt);
  } else {
    timersub(&now, tv, &dt);
  }
  t = dt.tv_sec;
  t *= 1000;
  t += (dt.tv_usec + 500) / 1000;

  if (t > INT_MAX) {
    t = INT_MAX;
  } else if (t < INT_MIN) {
    t = INT_MIN;
  }

  return r >= 0 ? t : -t;
}
Exemple #3
0
static void
send_up(sel_timer_t *elem, sel_timer_t **top, sel_timer_t **last)
{
    sel_timer_t *tmp1, *tmp2, *parent;

    parent = elem->up;
    while (parent && (cmp_timeval(&elem->timeout, &parent->timeout) < 0)) {
	tmp1 = elem->left;
	tmp2 = elem->right;
	if (parent->left == elem) {
	    elem->left = parent;
	    elem->right = parent->right;
	    if (elem->right)
		elem->right->up = elem;
	} else {
	    elem->right = parent;
	    elem->left = parent->left;
	    if (elem->left)
		elem->left->up = elem;
	}
	elem->up = parent->up;

	if (parent->up) {
	    if (parent->up->left == parent) {
		parent->up->left = elem;
	    } else {
		parent->up->right = elem;
	    }
	} else {
	    *top = elem;
	}

	parent->up = elem;
	parent->left = tmp1;
	if (parent->left)
	    parent->left->up = parent;
	parent->right = tmp2;
	if (parent->right)
	    parent->right->up = parent;

	if (*last == elem)
	    *last = parent;

	parent = elem->up;
    }
}
Exemple #4
0
/* 
 * Process timers on selector.  The timeout is always set, to a very
 * long value if no timers are waiting.  Note that this *must* be
 * called with sel->timer_lock held.  Note that if this processes
 * any timers, the timeout will be set to { 0,0 }.
 */
static void
process_timers(selector_t	       *sel,
	       volatile struct timeval *timeout)
{
    struct timeval now;
    sel_timer_t    *timer;
    int            called = 0;
    
    timer = theap_get_top(&sel->timer_heap);
    gettimeofday(&now, NULL);
    while (timer && cmp_timeval(&now, &timer->val.timeout) >= 0) {
	called = 1;
	theap_remove(&(sel->timer_heap), timer);
	timer->val.in_heap = 0;
	if (sel->have_timer_lock)
	    sel->os_hnd->unlock(sel->os_hnd, sel->timer_lock);
	
	timer->val.handler(sel, timer, timer->val.user_data);
	
	if (sel->have_timer_lock)
	    sel->os_hnd->lock(sel->os_hnd, sel->timer_lock);
	timer = theap_get_top(&sel->timer_heap);
    }

    if (called) {
	/* If called, set the timeout to zero. */
	timeout->tv_sec = 0;
	timeout->tv_usec = 0;
    } else if (timer) {
	gettimeofday(&now, NULL);   
	diff_timeval((struct timeval *) timeout,
		     (struct timeval *) &timer->val.timeout,
		     &now);
    } else {
	/* No timers, just set a long time. */
	timeout->tv_sec = 100000;
	timeout->tv_usec = 0;
    }
}
Exemple #5
0
static void
add_to_heap(sel_timer_t **top, sel_timer_t **last, sel_timer_t *elem)
{
    sel_timer_t **next;
    sel_timer_t *parent;

#ifdef MASSIVE_DEBUG
    fprintf(*debug_out, "add_to_heap entry\n");
    print_tree(*top, *last);
    check_tree(*top, *last);
#endif

    elem->left = NULL;
    elem->right = NULL;
    elem->up = NULL;

    if (*top == NULL) {
	*top = elem;
	*last = elem;
	goto out;
    }

    find_next_pos(*last, &next, &parent);
    *next = elem;
    elem->up = parent;
    *last = elem;
    if (cmp_timeval(&elem->timeout, &parent->timeout) < 0) {
	send_up(elem, top, last);
    }

 out:
#ifdef MASSIVE_DEBUG
    fprintf(*debug_out, "add_to_heap exit\n");
    print_tree(*top, *last);
    check_tree(*top, *last);
#endif
    return;
}
Exemple #6
0
void
sel_select_once(selector_t *sel)
{
    fd_set      tmp_read_set;
    fd_set      tmp_write_set;
    fd_set      tmp_except_set;
    int         i;
    int         err;
    sel_timer_t *timer;
    struct timeval timeout, *to_time;

    if (sel->timer_top) {
	struct timeval now;

	/* Check for timers to time out. */
	gettimeofday(&now, NULL);
	timer = sel->timer_top;
	while (cmp_timeval(&now, &timer->timeout) >= 0) {
	    remove_from_heap(&(sel->timer_top),
			     &(sel->timer_last),
			     timer);

	    timer->in_heap = 0;
	    timer->handler(sel, timer, timer->user_data);

	    timer = sel->timer_top;
	    gettimeofday(&now, NULL);
	    if (!timer)
		goto no_timers;
	}

	/* Calculate how long to wait now. */
	diff_timeval(&timeout, &sel->timer_top->timeout, &now);
	to_time = &timeout;
    } else {
      no_timers:
	to_time = NULL;
    }
    memcpy(&tmp_read_set, &sel->read_set, sizeof(tmp_read_set));
    memcpy(&tmp_write_set, &sel->write_set, sizeof(tmp_write_set));
    memcpy(&tmp_except_set, &sel->except_set, sizeof(tmp_except_set));
    err = select(sel->maxfd+1,
		 &tmp_read_set,
		 &tmp_write_set,
		 &tmp_except_set,
		 to_time);
    if (err == 0) {
	/* A timeout occurred. */
    } else if (err < 0) {
	/* An error occurred. */
	if (errno == EINTR) {
	    /* EINTR is ok, just restart the operation. */
	    timeout.tv_sec = 1;
	    timeout.tv_usec = 0;
	} else {
	    /* An error is bad, we need to abort. */
	    syslog(LOG_ERR, "select_loop() - select: %m");
	    exit(1);
	}
    } else {
	/* We got some I/O. */
	for (i=0; i<=sel->maxfd; i++) {
	    if (FD_ISSET(i, &tmp_read_set)) {
		if (sel->fds[i].handle_read == NULL) {
		    /* Somehow we don't have a handler for this.
		       Just shut it down. */
		    sel_set_fd_read_handler(sel, i, SEL_FD_HANDLER_DISABLED);
		} else {
		    sel->fds[i].handle_read(i, sel->fds[i].data);
		}
	    }
	    if (FD_ISSET(i, &tmp_write_set)) {
		if (sel->fds[i].handle_write == NULL) {
		    /* Somehow we don't have a handler for this.
		       Just shut it down. */
		    sel_set_fd_write_handler(sel, i, SEL_FD_HANDLER_DISABLED);
		} else {
		    sel->fds[i].handle_write(i, sel->fds[i].data);
		}
	    }
	    if (FD_ISSET(i, &tmp_except_set)) {
		if (sel->fds[i].handle_except == NULL) {
		    /* Somehow we don't have a handler for this.
		       Just shut it down. */
		    sel_set_fd_except_handler(sel, i, SEL_FD_HANDLER_DISABLED);
		} else {
		    sel->fds[i].handle_except(i, sel->fds[i].data);
		}
	    }
	}
    }

    if (got_sighup) {
	got_sighup = 0;
	if (user_sighup_handler != NULL) {
	    user_sighup_handler();
	}
    }
    if (got_sigint) {
	got_sigint = 0;
	if (user_sigint_handler != NULL) {
	    user_sigint_handler();
	}
    }
}
Exemple #7
0
static void
remove_from_heap(sel_timer_t **top, sel_timer_t **last, sel_timer_t *elem)
{
    sel_timer_t *to_insert;

#ifdef MASSIVE_DEBUG
    fprintf(*debug_out, "remove_from_head entry\n");
    print_tree(*top, *last);
    check_tree(*top, *last);
#endif

    /* First remove the last element from the tree, if it's not what's
       being removed, we will use it for insertion into the removal
       place. */
    to_insert = *last;
    if (! to_insert->up) {
	/* This is the only element in the heap. */
	*top = NULL;
	*last = NULL;
	goto out;
    } else {
	/* Set the new last position, and remove the item we will
           insert. */
	find_prev_elem(to_insert, last);
	if (to_insert->up->left == to_insert) {
	    to_insert->up->left = NULL;
	} else {
	    to_insert->up->right = NULL;
	}
    }

    if (elem == to_insert) {
	/* We got lucky and removed the last element.  We are done. */
	goto out;
    }

    /* Now stick the formerly last element into the removed element's
       position. */
    if (elem->up) {
	if (elem->up->left == elem) {
	    elem->up->left = to_insert;
	} else {
	    elem->up->right = to_insert;
	}
    } else {
	/* The head of the tree is being replaced. */
	*top = to_insert;
    }
    to_insert->up = elem->up;
    if (elem->left)
	elem->left->up = to_insert;
    if (elem->right)
	elem->right->up = to_insert;
    to_insert->left = elem->left;
    to_insert->right = elem->right;

    if (*last == elem)
	*last = to_insert;

    elem = to_insert;

    /* Now propigate it to the right place in the tree. */
    if (elem->up && cmp_timeval(&elem->timeout, &elem->up->timeout) < 0) {
	send_up(elem, top, last);
    } else {
	send_down(elem, top, last);
    }

 out:
#ifdef MASSIVE_DEBUG
    fprintf(*debug_out, "remove_from_head exit\n");
    print_tree(*top, *last);
    check_tree(*top, *last);
#endif
    return;
}
Exemple #8
0
static void
send_down(sel_timer_t *elem, sel_timer_t **top, sel_timer_t **last)
{
    sel_timer_t *tmp1, *tmp2, *left, *right;

    left = elem->left;
    while (left) {
	right = elem->right;
	/* Choose the smaller of the two below me to swap with. */
	if ((right) && (cmp_timeval(&left->timeout, &right->timeout) > 0)) {

	    if (cmp_timeval(&elem->timeout, &right->timeout) > 0) {
		/* Swap with the right element. */
		tmp1 = right->left;
		tmp2 = right->right;
		if (elem->up) {
		    if (elem->up->left == elem) {
			elem->up->left = right;
		    } else {
			elem->up->right = right;
		    }
		} else {
		    *top = right;
		}
		right->up = elem->up;
		elem->up = right;

		right->left = elem->left;
		right->right = elem;
		elem->left = tmp1;
		elem->right = tmp2;
		if (right->left)
		    right->left->up = right;
		if (elem->left)
		    elem->left->up = elem;
		if (elem->right)
		    elem->right->up = elem;

		if (*last == right)
		    *last = elem;
	    } else
		goto done;
	} else {
	    /* The left element is smaller, or the right doesn't exist. */
	    if (cmp_timeval(&elem->timeout, &left->timeout) > 0) {
		/* Swap with the left element. */
		tmp1 = left->left;
		tmp2 = left->right;
		if (elem->up) {
		    if (elem->up->left == elem) {
			elem->up->left = left;
		    } else {
			elem->up->right = left;
		    }
		} else {
		    *top = left;
		}
		left->up = elem->up;
		elem->up = left;

		left->left = elem;
		left->right = elem->right;
		elem->left = tmp1;
		elem->right = tmp2;
		if (left->right)
		    left->right->up = left;
		if (elem->left)
		    elem->left->up = elem;
		if (elem->right)
		    elem->right->up = elem;

		if (*last == left)
		    *last = elem;
	    } else
		goto done;
	}
	left = elem->left;
    }
done:
    return;
}
Exemple #9
0
static void
check_tree_item(sel_timer_t *curr,
		int         *depth,
		int         max_depth,
		sel_timer_t **real_last,
		int         *found_last)
{
    if (! curr->left) {
	if (curr->right) {
	    fprintf(*debug_out, "Tree corrupt B\n");
	    *((int *) NULL) = 0;
	} else if (*depth > max_depth) {
	    fprintf(*debug_out, "Tree corrupt C\n");
	    *((int *) NULL) = 0;
	} else if (*depth < (max_depth - 1)) {
	    fprintf(*debug_out, "Tree corrupt D\n");
	    *((int *) NULL) = 0;
	} else if ((*found_last) && (*depth == max_depth)) {
	    fprintf(*debug_out, "Tree corrupt E\n");
	    *((int *) NULL) = 0;
	} else if (*depth == max_depth) {
	    *real_last = curr;
	} else {
	    *found_last = 1;
	}
    } else {
	if (curr->left->up != curr) {
	    fprintf(*debug_out, "Tree corrupt I\n");
	    *((int *) NULL) = 0;
	}
	if (cmp_timeval(&(curr->left->timeout), &(curr->timeout)) < 0) {
	    fprintf(*debug_out, "Tree corrupt K\n");
	    *((int *) NULL) = 0;
	}
	(*depth)++;
	check_tree_item(curr->left, depth, max_depth, real_last, found_last);
	(*depth)--;

	if (! curr->right) {
	    if (*depth != (max_depth - 1)) {
		fprintf(*debug_out, "Tree corrupt F\n");
		*((int *) NULL) = 0;
	    }
	    if (*found_last) {
		fprintf(*debug_out, "Tree corrupt G\n");
		*((int *) NULL) = 0;
	    }
	    *found_last = 1;
	} else {
	    if (curr->right->up != curr) {
		fprintf(*debug_out, "Tree corrupt H\n");
		*((int *) NULL) = 0;
	    }
	    if (cmp_timeval(&(curr->right->timeout), &(curr->timeout)) < 0) {
		fprintf(*debug_out, "Tree corrupt L\n");
		*((int *) NULL) = 0;
	    }
	    (*depth)++;
	    check_tree_item(curr->right, depth, max_depth, real_last, found_last);
	    (*depth)--;
	}
    }
}
Exemple #10
0
/*
 * return == 0  when timeout
 * 	  >  0  when successful 
 * 	  <  0  when error
 */
static int
process_fds(selector_t	            *sel,
	    sel_send_sig_cb         send_sig,
	    long                    thread_id,
	    void                    *cb_data,
	    volatile struct timeval *timeout)
{
    fd_set      tmp_read_set;
    fd_set      tmp_write_set;
    fd_set      tmp_except_set;
    int i;
    int err;
    int num_fds;
    
    if (sel->have_fd_lock)
	sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
    memcpy(&tmp_read_set, (void *) &sel->read_set, sizeof(tmp_read_set));
    memcpy(&tmp_write_set, (void *) &sel->write_set, sizeof(tmp_write_set));
    memcpy(&tmp_except_set, (void *) &sel->except_set, sizeof(tmp_except_set));
    num_fds = sel->maxfd+1;
    if (sel->add_read) {
	int timeout_invalid;
	struct timeval ttimeout;

	timeout_invalid = 1; 
	sel->add_read(sel, &num_fds, &tmp_read_set,
		      &ttimeout, &timeout_invalid,
		      sel->read_cb_data);
	if (!timeout_invalid
	    && (cmp_timeval(&ttimeout, (struct timeval *)timeout) <= 0))
	{
	    *timeout= ttimeout;
	}	      
    }
    if (sel->have_fd_lock)
	sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);

    err = select(num_fds,
		 &tmp_read_set,
		 &tmp_write_set,
		 &tmp_except_set,
		 (struct timeval *) timeout);
    if (err <= 0) {
	if ((err == 0) && (sel->check_timeout))
	    sel->check_timeout(sel, sel->read_cb_data);
	goto out;
    }

    if (sel->check_read)
	sel->check_read(sel, &tmp_read_set, sel->read_cb_data);
    
    /* We got some I/O. */
    for (i=0; i<=sel->maxfd; i++) {
	if (FD_ISSET(i, &tmp_read_set)) {
	    sel_fd_handler_t handle_read;
	    void             *data;
	    fd_state_t       *state;

	    if (sel->have_fd_lock)
		sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
	    if (sel->fds[i].handle_read == NULL) {
		/* Somehow we don't have a handler for this.
		   Just shut it down. */
		sel_set_fd_read_handler(sel, i, SEL_FD_HANDLER_DISABLED);
	    } else {
		handle_read = sel->fds[i].handle_read;
		data = sel->fds[i].data;
		state = sel->fds[i].state;
		state->use_count++;
		if (sel->have_fd_lock)
		    sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);
		handle_read(i, data);
		if (sel->have_fd_lock)
		    sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
		state->use_count--;
		if (state->deleted && state->use_count == 0) {
		    if (state->done)
			state->done(i, data);
		    free(state);
		}
	    }
	    if (sel->have_fd_lock)
		sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);
	}
	if (FD_ISSET(i, &tmp_write_set)) {
	    sel_fd_handler_t handle_write;
	    void             *data;
	    fd_state_t       *state;

	    if (sel->have_fd_lock)
		sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
	    if (sel->fds[i].handle_write == NULL) {
		/* Somehow we don't have a handler for this.
                   Just shut it down. */
		sel_set_fd_write_handler(sel, i, SEL_FD_HANDLER_DISABLED);
	    } else {
		handle_write = sel->fds[i].handle_write;
		data = sel->fds[i].data;
		state = sel->fds[i].state;
		state->use_count++;
		if (sel->have_fd_lock)
		    sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);
		handle_write(i, data);
		if (sel->have_fd_lock)
		    sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
		state->use_count--;
		if (state->deleted && state->use_count == 0) {
		    if (state->done)
			state->done(i, data);
		    free(state);
		}
	    }
	    if (sel->have_fd_lock)
		sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);
	}
	if (FD_ISSET(i, &tmp_except_set)) {
	    sel_fd_handler_t handle_except;
	    void             *data;
	    fd_state_t       *state;

	    if (sel->have_fd_lock)
		sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
	    if (sel->fds[i].handle_except == NULL) {
		/* Somehow we don't have a handler for this.
                   Just shut it down. */
		sel_set_fd_except_handler(sel, i, SEL_FD_HANDLER_DISABLED);
	    } else {
	        handle_except = sel->fds[i].handle_except;
		data = sel->fds[i].data;
		state = sel->fds[i].state;
		state->use_count++;
		if (sel->have_fd_lock)
		    sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);
	        handle_except(i, data);
		if (sel->have_fd_lock)
		    sel->os_hnd->lock(sel->os_hnd, sel->fd_lock);
		state->use_count--;
		if (state->deleted && state->use_count == 0) {
		    if (state->done)
			state->done(i, data);
		    free(state);
		}
	    }
	    if (sel->have_fd_lock)
		sel->os_hnd->unlock(sel->os_hnd, sel->fd_lock);
	}
    }
out:
    return err;
}
Exemple #11
0
static int
heap_cmp_key(heap_val_t *v1, heap_val_t *v2)
{
    return cmp_timeval(&v1->timeout, &v2->timeout);
}