コード例 #1
0
ファイル: uipc_domain.c プロジェクト: Digital-Chaos/freebsd
/*
 * The caller must make sure that the new protocol is fully set up and ready to
 * accept requests before it is registered.
 */
int
pf_proto_register(int family, struct protosw *npr)
{
	VNET_ITERATOR_DECL(vnet_iter);
	struct domain *dp;
	struct protosw *pr, *fpr;

	/* Sanity checks. */
	if (family == 0)
		return (EPFNOSUPPORT);
	if (npr->pr_type == 0)
		return (EPROTOTYPE);
	if (npr->pr_protocol == 0)
		return (EPROTONOSUPPORT);
	if (npr->pr_usrreqs == NULL)
		return (ENXIO);

	/* Try to find the specified domain based on the family. */
	dp = pffinddomain(family);
	if (dp == NULL)
		return (EPFNOSUPPORT);

	/* Initialize backpointer to struct domain. */
	npr->pr_domain = dp;
	fpr = NULL;

	/*
	 * Protect us against races when two protocol registrations for
	 * the same protocol happen at the same time.
	 */
	mtx_lock(&dom_mtx);

	/* The new protocol must not yet exist. */
	for (pr = dp->dom_protosw; pr < dp->dom_protoswNPROTOSW; pr++) {
		if ((pr->pr_type == npr->pr_type) &&
		    (pr->pr_protocol == npr->pr_protocol)) {
			mtx_unlock(&dom_mtx);
			return (EEXIST);	/* XXX: Check only protocol? */
		}
		/* While here, remember the first free spacer. */
		if ((fpr == NULL) && (pr->pr_protocol == PROTO_SPACER))
			fpr = pr;
	}

	/* If no free spacer is found we can't add the new protocol. */
	if (fpr == NULL) {
		mtx_unlock(&dom_mtx);
		return (ENOMEM);
	}

	/* Copy the new struct protosw over the spacer. */
	bcopy(npr, fpr, sizeof(*fpr));

	/* Job is done, no more protection required. */
	mtx_unlock(&dom_mtx);

	/* Initialize and activate the protocol. */
	VNET_LIST_RLOCK();
	VNET_FOREACH(vnet_iter) {
		CURVNET_SET_QUIET(vnet_iter);
		protosw_init(fpr);
		CURVNET_RESTORE();
	}
	VNET_LIST_RUNLOCK();

	return (0);
}
コード例 #2
0
ファイル: uinet_init.c プロジェクト: bigclouds/libuinet
static void
shutdown_helper(void *arg)
{
	struct uhi_msg *msg = arg;
	uint8_t signo;
	int lock_attempts;
	int have_lock;
	VNET_ITERATOR_DECL(vnet_iter);
	struct uinet_instance *uinst;
	int shutdown_complete = 0;

	if (msg) {

		/*
		 * Loop to respond to multiple messages, but only shutdown
		 * once.  This allows multiple, possibly concurrent,
		 * executions of uinet_shutdown() to result in one shutdown
		 * and none of the calls to uinet_shutdown() to block
		 * indefinitely.  This provides nice behavior when
		 * uinet_shutdown() is called from a signal handler in a
		 * multi-threaded application that is not carefully policing
		 * signal masks in all the threads.
		 */
		for (;;) {
			if (uhi_msg_wait(msg, &signo) == 0) {
				if (!shutdown_complete) {
					printf("\nuinet shutting down");
					if (signo)
						printf(" from signal handler (signal %u)",
						       signo);
					printf("\n");
				
					printf("Shutting down all uinet instances...\n");
					/*
					 * We may be shutting down as a
					 * result of a signal occurring
					 * while another thread is holding
					 * the vnet list lock, so attempt to
					 * acquire the lock in a way that
					 * will avoid getting stuck.
					 */ 
					lock_attempts = 0;
					have_lock = 0;
					while ((lock_attempts < 5) && !(have_lock = VNET_LIST_TRY_RLOCK())) {
						printf("Waiting for vnet list lock...\n");
						uhi_nanosleep(UHI_NSEC_PER_SEC);
						lock_attempts++;
					}
					if (lock_attempts > 0 && have_lock)
						printf("Acquired vnet list lock\n");
					if (!have_lock)
						printf("Proceeding without vnet list lock\n");
#ifdef VIMAGE
					VNET_FOREACH(vnet_iter) {
						uinst = vnet_iter->vnet_uinet;
						uinet_instance_shutdown(uinst);
					}
#else
					uinet_instance_shutdown(uinet_instance_default());
#endif
					if (have_lock)
						VNET_LIST_RUNLOCK();
			
					printf("uinet shutdown complete\n");
				
					shutdown_complete = 1;
				}

				uhi_msg_rsp_send(msg, NULL);
			} else {
				printf("Failed to receive shutdown message\n");
			}
		}