示例#1
0
文件: group.c 项目: drscream/sheepdog
/*
 * Grab an additional reference to the passed in vnode info.
 *
 * The caller must already hold a reference to vnode_info, this function must
 * only be used to grab an additional reference from code that wants the
 * vnode information to outlive the request structure.
 */
struct vnode_info *grab_vnode_info(struct vnode_info *vnode_info)
{
	assert(uatomic_read(&vnode_info->refcnt) > 0);

	uatomic_inc(&vnode_info->refcnt);
	return vnode_info;
}
示例#2
0
文件: group.c 项目: drscream/sheepdog
/*
 * Release a reference to the current vnode information.
 *
 * Must be called from the main thread.
 */
void put_vnode_info(struct vnode_info *vnode_info)
{
	if (vnode_info) {
		assert(uatomic_read(&vnode_info->refcnt) > 0);

		if (uatomic_sub_return(&vnode_info->refcnt, 1) == 0)
			free(vnode_info);
	}
}
/* The entry was removed from the hashtable. No more readers can get it. Since
   all readers using the node for a longer time (outside the rcu critical
   section) increased the refcount, we only need to wait for the refcount
   to reach zero. */
static void markDead(struct rcu_head *head) {
    struct nodeEntry *entry = (struct nodeEntry*) ((uintptr_t)head - offsetof(struct nodeEntry, rcu_head)); 
    uatomic_and(&entry->refcount, ~ALIVE_BIT); // set the alive bit to zero
    if(uatomic_read(&entry->refcount) > 0)
        return;

    node_deleteMembers(&entry->node);
    UA_free(entry);
}
示例#4
0
/*
 * Wake 1 futex.
 */
LTTNG_HIDDEN
void futex_nto1_wake(int32_t *futex)
{
	if (caa_unlikely(uatomic_read(futex) == -1)) {
		uatomic_set(futex, 0);
		futex_async(futex, FUTEX_WAKE, 1, NULL, NULL, 0);
	}

	DBG("Futex n to 1 wake done");
}
示例#5
0
/*
 * Wait futex.
 */
LTTNG_HIDDEN
void futex_nto1_wait(int32_t *futex)
{
	cmm_smp_mb();

	if (uatomic_read(futex) == -1) {
		futex_async(futex, FUTEX_WAIT, -1, NULL, NULL, 0);
	}

	DBG("Futex n to 1 wait done");
}
示例#6
0
/*
 * Wake 1 futex.
 */
LTTNG_HIDDEN
void futex_nto1_wake(int32_t *futex)
{
	if (caa_unlikely(uatomic_read(futex) != -1))
		goto end;
	uatomic_set(futex, 0);
	if (futex_async(futex, FUTEX_WAKE, 1, NULL, NULL, 0) < 0) {
		PERROR("futex_async");
		abort();
	}
end:
	DBG("Futex n to 1 wake done");
}
示例#7
0
文件: urcu-qsbr.c 项目: JevonQ/urcu
/*
 * synchronize_rcu() waiting. Single thread.
 */
static void wait_gp(void)
{
	/* Read reader_gp before read futex */
	cmm_smp_rmb();
	if (uatomic_read(&rcu_gp.futex) != -1)
		return;
	while (futex_noasync(&rcu_gp.futex, FUTEX_WAIT, -1,
			NULL, NULL, 0)) {
		switch (errno) {
		case EWOULDBLOCK:
			/* Value already changed. */
			return;
		case EINTR:
			/* Retry if interrupted by signal. */
			break;	/* Get out of switch. */
		default:
			/* Unexpected error. */
			urcu_die(errno);
		}
	}
}
示例#8
0
/*
 * Wait futex.
 */
LTTNG_HIDDEN
void futex_nto1_wait(int32_t *futex)
{
	cmm_smp_mb();

	if (uatomic_read(futex) != -1)
		goto end;
	while (futex_async(futex, FUTEX_WAIT, -1, NULL, NULL, 0)) {
		switch (errno) {
		case EWOULDBLOCK:
			/* Value already changed. */
			goto end;
		case EINTR:
			/* Retry if interrupted by signal. */
			break;	/* Get out of switch. */
		default:
			/* Unexpected error. */
			PERROR("futex_async");
			abort();
		}
	}
end:
	DBG("Futex n to 1 wait done");
}
 operator T() const {
   return uatomic_read(&m_counter);
 }
示例#10
0
/*
 * main
 */
int main(int argc, char **argv)
{
	int ret = 0, retval = 0;
	void *status;

	if (set_signal_handler()) {
		retval = -1;
		goto exit_set_signal_handler;
	}

	/* Parse arguments */
	progname = argv[0];
	if (parse_args(argc, argv)) {
		retval = -1;
		goto exit_options;
	}

	/* Daemonize */
	if (opt_daemon) {
		int i;

		/*
		 * fork
		 * child: setsid, close FD 0, 1, 2, chdir /
		 * parent: exit (if fork is successful)
		 */
		ret = daemon(0, 0);
		if (ret < 0) {
			PERROR("daemon");
			retval = -1;
			goto exit_options;
		}
		/*
		 * We are in the child. Make sure all other file
		 * descriptors are closed, in case we are called with
		 * more opened file descriptors than the standard ones.
		 */
		for (i = 3; i < sysconf(_SC_OPEN_MAX); i++) {
			(void) close(i);
		}
	}

	/*
	 * Starting from here, we can create threads. This needs to be after
	 * lttng_daemonize due to RCU.
	 */

	health_consumerd = health_app_create(NR_HEALTH_CONSUMERD_TYPES);
	if (!health_consumerd) {
		retval = -1;
		goto exit_health_consumerd_cleanup;
	}

	/* Set up max poll set size */
	if (lttng_poll_set_max_size()) {
		retval = -1;
		goto exit_init_data;
	}

	if (*command_sock_path == '\0') {
		switch (opt_type) {
		case LTTNG_CONSUMER_KERNEL:
			ret = snprintf(command_sock_path, PATH_MAX,
					DEFAULT_KCONSUMERD_CMD_SOCK_PATH,
					DEFAULT_LTTNG_RUNDIR);
			if (ret < 0) {
				retval = -1;
				goto exit_init_data;
			}
			break;
		case LTTNG_CONSUMER64_UST:
			ret = snprintf(command_sock_path, PATH_MAX,
					DEFAULT_USTCONSUMERD64_CMD_SOCK_PATH,
					DEFAULT_LTTNG_RUNDIR);
			if (ret < 0) {
				retval = -1;
				goto exit_init_data;
			}
			break;
		case LTTNG_CONSUMER32_UST:
			ret = snprintf(command_sock_path, PATH_MAX,
					DEFAULT_USTCONSUMERD32_CMD_SOCK_PATH,
					DEFAULT_LTTNG_RUNDIR);
			if (ret < 0) {
				retval = -1;
				goto exit_init_data;
			}
			break;
		default:
			ERR("Unknown consumerd type");
			retval = -1;
			goto exit_init_data;
		}
	}

	/* Init */
	if (lttng_consumer_init()) {
		retval = -1;
		goto exit_init_data;
	}

	/* Initialize communication library */
	lttcomm_init();
	/* Initialize TCP timeout values */
	lttcomm_inet_init();

	if (!getuid()) {
		/* Set limit for open files */
		set_ulimit();
	}

	/* create the consumer instance with and assign the callbacks */
	ctx = lttng_consumer_create(opt_type, lttng_consumer_read_subbuffer,
		NULL, lttng_consumer_on_recv_stream, NULL);
	if (!ctx) {
		retval = -1;
		goto exit_init_data;
	}

	lttng_consumer_set_command_sock_path(ctx, command_sock_path);
	if (*error_sock_path == '\0') {
		switch (opt_type) {
		case LTTNG_CONSUMER_KERNEL:
			ret = snprintf(error_sock_path, PATH_MAX,
					DEFAULT_KCONSUMERD_ERR_SOCK_PATH,
					DEFAULT_LTTNG_RUNDIR);
			if (ret < 0) {
				retval = -1;
				goto exit_init_data;
			}
			break;
		case LTTNG_CONSUMER64_UST:
			ret = snprintf(error_sock_path, PATH_MAX,
					DEFAULT_USTCONSUMERD64_ERR_SOCK_PATH,
					DEFAULT_LTTNG_RUNDIR);
			if (ret < 0) {
				retval = -1;
				goto exit_init_data;
			}
			break;
		case LTTNG_CONSUMER32_UST:
			ret = snprintf(error_sock_path, PATH_MAX,
					DEFAULT_USTCONSUMERD32_ERR_SOCK_PATH,
					DEFAULT_LTTNG_RUNDIR);
			if (ret < 0) {
				retval = -1;
				goto exit_init_data;
			}
			break;
		default:
			ERR("Unknown consumerd type");
			retval = -1;
			goto exit_init_data;
		}
	}

	/* Connect to the socket created by lttng-sessiond to report errors */
	DBG("Connecting to error socket %s", error_sock_path);
	ret = lttcomm_connect_unix_sock(error_sock_path);
	/*
	 * Not a fatal error, but all communication with lttng-sessiond will
	 * fail.
	 */
	if (ret < 0) {
		WARN("Cannot connect to error socket (is lttng-sessiond started?)");
	}
	lttng_consumer_set_error_sock(ctx, ret);

	/*
	 * Block RT signals used for UST periodical metadata flush and the live
	 * timer in main, and create a dedicated thread to handle these signals.
	 */
	if (consumer_signal_init()) {
		retval = -1;
		goto exit_init_data;
	}

	ctx->type = opt_type;

	if (utils_create_pipe(health_quit_pipe)) {
		retval = -1;
		goto exit_health_pipe;
	}

	/* Create thread to manage the client socket */
	ret = pthread_create(&health_thread, NULL,
			thread_manage_health, (void *) NULL);
	if (ret) {
		errno = ret;
		PERROR("pthread_create health");
		retval = -1;
		goto exit_health_thread;
	}

	/*
	 * Wait for health thread to be initialized before letting the
	 * sessiond thread reply to the sessiond that we are ready.
	 */
	while (uatomic_read(&lttng_consumer_ready)) {
		usleep(100000);
	}
	cmm_smp_mb();	/* Read ready before following operations */

	/* Create thread to manage channels */
	ret = pthread_create(&channel_thread, NULL,
			consumer_thread_channel_poll,
			(void *) ctx);
	if (ret) {
		errno = ret;
		PERROR("pthread_create");
		retval = -1;
		goto exit_channel_thread;
	}

	/* Create thread to manage the polling/writing of trace metadata */
	ret = pthread_create(&metadata_thread, NULL,
			consumer_thread_metadata_poll,
			(void *) ctx);
	if (ret) {
		errno = ret;
		PERROR("pthread_create");
		retval = -1;
		goto exit_metadata_thread;
	}

	/* Create thread to manage the polling/writing of trace data */
	ret = pthread_create(&data_thread, NULL, consumer_thread_data_poll,
			(void *) ctx);
	if (ret) {
		errno = ret;
		PERROR("pthread_create");
		retval = -1;
		goto exit_data_thread;
	}

	/* Create the thread to manage the receive of fd */
	ret = pthread_create(&sessiond_thread, NULL,
			consumer_thread_sessiond_poll,
			(void *) ctx);
	if (ret) {
		errno = ret;
		PERROR("pthread_create");
		retval = -1;
		goto exit_sessiond_thread;
	}

	/*
	 * Create the thread to manage the UST metadata periodic timer and
	 * live timer.
	 */
	ret = pthread_create(&metadata_timer_thread, NULL,
			consumer_timer_thread, (void *) ctx);
	if (ret) {
		errno = ret;
		PERROR("pthread_create");
		retval = -1;
		goto exit_metadata_timer_thread;
	}

	ret = pthread_detach(metadata_timer_thread);
	if (ret) {
		errno = ret;
		PERROR("pthread_detach");
		retval = -1;
		goto exit_metadata_timer_detach;
	}

	/*
	 * This is where we start awaiting program completion (e.g. through
	 * signal that asks threads to teardown.
	 */

exit_metadata_timer_detach:
exit_metadata_timer_thread:
	ret = pthread_join(sessiond_thread, &status);
	if (ret) {
		errno = ret;
		PERROR("pthread_join sessiond_thread");
		retval = -1;
	}
exit_sessiond_thread:

	ret = pthread_join(data_thread, &status);
	if (ret) {
		errno = ret;
		PERROR("pthread_join data_thread");
		retval = -1;
	}
exit_data_thread:

	ret = pthread_join(metadata_thread, &status);
	if (ret) {
		errno = ret;
		PERROR("pthread_join metadata_thread");
		retval = -1;
	}
exit_metadata_thread:

	ret = pthread_join(channel_thread, &status);
	if (ret) {
		errno = ret;
		PERROR("pthread_join channel_thread");
		retval = -1;
	}
exit_channel_thread:

	ret = pthread_join(health_thread, &status);
	if (ret) {
		errno = ret;
		PERROR("pthread_join health_thread");
		retval = -1;
	}
exit_health_thread:

	utils_close_pipe(health_quit_pipe);
exit_health_pipe:

exit_init_data:
	lttng_consumer_destroy(ctx);
	lttng_consumer_cleanup();

	if (health_consumerd) {
		health_app_destroy(health_consumerd);
	}
exit_health_consumerd_cleanup:

exit_options:

exit_set_signal_handler:
	if (!retval) {
		exit(EXIT_SUCCESS);
	} else {
		exit(EXIT_FAILURE);
	}
}