예제 #1
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Set an external mutex for this thread
 *
 * @param mutexp Pointer to external mutex, NULL to use internal
 */
void re_set_mutex(void *mutexp)
{
#ifdef HAVE_PTHREAD
	struct re *re = re_get();

	re->mutexp = mutexp ? mutexp : &re->mutex;
#else
	(void)mutexp;
#endif
}
예제 #2
0
/**
 * Set async I/O polling method. This function can also be called while the
 * program is running.
 *
 * @param method New polling method
 *
 * @return 0 if success, otherwise errorcode
 */
int poll_method_set(enum poll_method method)
{
	struct re *re = re_get();
	int err;

	err = fd_setsize(DEFAULT_MAXFDS);
	if (err)
		return err;

	switch (method) {

#ifdef HAVE_POLL
	case METHOD_POLL:
		break;
#endif
#ifdef HAVE_SELECT
	case METHOD_SELECT:
		if (re->maxfds > (int)FD_SETSIZE) {
			DEBUG_WARNING("SELECT: maxfds > FD_SETSIZE\n");
			return EMFILE;
		}
		break;
#endif
#ifdef HAVE_EPOLL
	case METHOD_EPOLL:
		if (!epoll_check())
			return EINVAL;
		break;
#endif
#ifdef HAVE_ACTSCHED
	case METHOD_ACTSCHED:
		break;
#endif
#ifdef HAVE_KQUEUE
	case METHOD_KQUEUE:
		break;
#endif
	default:
		DEBUG_WARNING("poll method not supported: '%s'\n",
			      poll_method_name(method));
		return EINVAL;
	}

	re->method = method;
	re->update = true;

	DEBUG_INFO("Setting async I/O polling method to `%s'\n",
		   poll_method_name(re->method));

	err = poll_init(re);
	if (err)
		return err;

	return rebuild_fds(re);
}
예제 #3
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Cancel the main polling loop
 */
void re_cancel(void)
{
	struct re *re = re_get();

	re->polling = false;

#ifdef HAVE_ACTSCHED
	if (METHOD_ACTSCHED == re->method) {
		actsched_stop();
	}
#endif
}
예제 #4
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Debug the main polling loop
 *
 * @param pf     Print handler where debug output is printed to
 * @param unused Unused parameter
 *
 * @return 0 if success, otherwise errorcode
 */
int re_debug(struct re_printf *pf, void *unused)
{
	struct re *re = re_get();
	int err = 0;

	(void)unused;

	err |= re_hprintf(pf, "re main loop:\n");
	err |= re_hprintf(pf, "  maxfds:  %d\n", re->maxfds);
	err |= re_hprintf(pf, "  nfds:    %d\n", re->nfds);
	err |= re_hprintf(pf, "  method:  %d (%s)\n", re->method,
			  poll_method_name(re->method));

	return err;
}
예제 #5
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Print all file descriptors in-use
 */
void fd_debug(void)
{
	const struct re *re = re_get();
	int i;

	if (!re->fhs)
		return;

	for (i=0; i<re->nfds; i++) {

		if (!re->fhs[i].flags)
			continue;

		(void)re_fprintf(stderr,
				 "fd %d in use: flags=%x fh=%p arg=%p\n",
				 i, re->fhs[i].flags, re->fhs[i].fh,
				 re->fhs[i].arg);
	}
}
예제 #6
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Set the maximum number of file descriptors
 *
 * @param maxfds Max FDs. 0 to free.
 *
 * @return 0 if success, otherwise errorcode
 */
int fd_setsize(int maxfds)
{
	struct re *re = re_get();

	if (!maxfds) {
		fd_debug();
		poll_close(re);
		return 0;
	}

	if (!re->maxfds)
		re->maxfds = maxfds;

	if (!re->fhs) {
		DEBUG_INFO("fd_setsize: maxfds=%d, allocating %u bytes\n",
			   re->maxfds, re->maxfds * sizeof(*re->fhs));

		re->fhs = mem_zalloc(re->maxfds * sizeof(*re->fhs), NULL);
		if (!re->fhs)
			return ENOMEM;
	}

	return 0;
}
예제 #7
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Main polling loop for async I/O events. This function will only return when
 * re_cancel() is called or an error occured.
 *
 * @param signalh Optional Signal handler
 *
 * @return 0 if success, otherwise errorcode
 */
int re_main(re_signal_h *signalh)
{
	struct re *re = re_get();
	int err;

#ifdef HAVE_SIGNAL
	if (signalh) {
		(void)signal(SIGINT, signal_handler);
		(void)signal(SIGALRM, signal_handler);
		(void)signal(SIGTERM, signal_handler);
	}
#endif

	if (re->polling) {
		DEBUG_WARNING("main loop already polling\n");
		return EALREADY;
	}

	err = poll_setup(re);
	if (err)
		goto out;

	DEBUG_INFO("Using async I/O polling method: `%s'\n",
		   poll_method_name(re->method));

	re->polling = true;

#ifdef HAVE_ACTSCHED
	if (METHOD_ACTSCHED == re->method) {
		err = actsched_start();
		goto out;
	}
#endif

	re_lock(re);
	for (;;) {

		if (re->sig) {
			if (signalh)
				signalh(re->sig);

			re->sig = 0;
		}

		if (!re->polling) {
			err = 0;
			break;
		}

		err = fd_poll(re);
		if (err) {
			if (EINTR == err)
				continue;

#ifdef DARWIN
			/* NOTE: workaround for Darwin */
			if (EBADF == err)
				continue;
#endif

			break;
		}

		tmr_poll(&re->tmrl);
	}
	re_unlock(re);

 out:
	re->polling = false;

	return err;
}
예제 #8
0
파일: main.c 프로젝트: Issic47/libre
/* Thread-safe signal handling */
static void signal_handler(int sig)
{
	(void)signal(sig, signal_handler);
	re_get()->sig = sig;
}
예제 #9
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Listen for events on a file descriptor
 *
 * @param fd     File descriptor
 * @param flags  Wanted event flags
 * @param fh     Event handler
 * @param arg    Handler argument
 *
 * @return 0 if success, otherwise errorcode
 */
int fd_listen(int fd, int flags, fd_h *fh, void *arg)
{
	struct re *re = re_get();
	int err = 0;

	DEBUG_INFO("fd_listen: fd=%d flags=0x%02x\n", fd, flags);

	if (fd < 0) {
		DEBUG_WARNING("fd_listen: corrupt fd %d\n", fd);
		return EBADF;
	}

	if (flags || fh) {
		err = poll_setup(re);
		if (err)
			return err;
	}

	if (fd >= re->maxfds) {
		if (flags) {
			DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x"
				      " - Max %d fds\n",
				      fd, flags, re->maxfds);
		}
		return EMFILE;
	}

	/* Update fh set */
	if (re->fhs) {
		re->fhs[fd].flags = flags;
		re->fhs[fd].fh    = fh;
		re->fhs[fd].arg   = arg;
	}

	re->nfds = max(re->nfds, fd+1);

	switch (re->method) {

#ifdef HAVE_POLL
	case METHOD_POLL:
		err = set_poll_fds(re, fd, flags);
		break;
#endif

#ifdef HAVE_EPOLL
	case METHOD_EPOLL:
		if (re->epfd <= 0)
			return EBADFD;
		err = set_epoll_fds(re, fd, flags);
		break;
#endif
	default:
		break;
	}

	if (err) {
		if (flags && fh) {
			fd_close(fd);
			DEBUG_WARNING("fd_listen: fd=%d flags=0x%02x (%m)\n",
				      fd, flags, err);
		}
	}

	return err;
}
예제 #10
0
파일: main.c 프로젝트: Issic47/libre
struct list *tmrl_get(void)
{
	return &re_get()->tmrl;
}
예제 #11
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Leave an 're' thread
 *
 * @note Must only be called from a non-re thread
 */
void re_thread_leave(void)
{
	re_unlock(re_get());
}
예제 #12
0
파일: main.c 프로젝트: Issic47/libre
/**
 * Enter an 're' thread
 *
 * @note Must only be called from a non-re thread
 */
void re_thread_enter(void)
{
	re_lock(re_get());
}