FreeBSD/sys/dev/iscsi/icl_soft_proxy.c
/*
 * XXX: Doing accept in a separate thread in each socket might not be the best way
 * 	to do stuff, but it's pretty clean and debuggable - and you probably won't
 * 	have hundreds of listening sockets anyway.
 */
Doing accept in a separate thread in each socket might not be the best way
to do stuff, but it's pretty clean and debuggable - and you probably won't
have hundreds of listening sockets anyway.
Doing accept in a separate thread in each socket might not be the best way to do stuff but it ' s pretty clean and debuggable - and you probably won ' t have hundreds of listening sockets anyway .
static void
icl_accept_thread(void *arg)
{
	struct icl_listen_sock *ils;
	struct socket *head, *so;
	struct sockaddr *sa;
	int error;
	ils = arg;
	head = ils->ils_socket;
	ils->ils_running = true;
	for (;;) {
		ACCEPT_LOCK();
		while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0 && ils->ils_disconnecting == false) {
			if (head->so_rcv.sb_state & SBS_CANTRCVMORE) {
				head->so_error = ECONNABORTED;
				break;
			}
			error = msleep(&head->so_timeo, &accept_mtx, PSOCK | PCATCH,
			    "accept", 0);
			if (error) {
				ACCEPT_UNLOCK();
				ICL_WARN("msleep failed with error %d", error);
				continue;
			}
			if (ils->ils_disconnecting) {
				ACCEPT_UNLOCK();
				ICL_DEBUG("terminating");
				ils->ils_running = false;
				kthread_exit();
				return;
			}
		}
		if (head->so_error) {
			error = head->so_error;
			head->so_error = 0;
			ACCEPT_UNLOCK();
			ICL_WARN("socket error %d", error);
			continue;
		}
		so = TAILQ_FIRST(&head->so_comp);
		KASSERT(so != NULL, ("NULL so"));
		KASSERT(!(so->so_qstate & SQ_INCOMP), ("accept1: so SQ_INCOMP"));
		KASSERT(so->so_qstate & SQ_COMP, ("accept1: so not SQ_COMP"));
		SOCK_LOCK(so);			
		soref(so);			
		TAILQ_REMOVE(&head->so_comp, so, so_list);
		head->so_qlen--;
		so->so_state |= (head->so_state & SS_NBIO);
		so->so_qstate &= ~SQ_COMP;
		so->so_head = NULL;
		SOCK_UNLOCK(so);
		ACCEPT_UNLOCK();
		sa = NULL;
		error = soaccept(so, &sa);
		if (error != 0) {
			ICL_WARN("soaccept error %d", error);
			if (sa != NULL)
				free(sa, M_SONAME);
			soclose(so);
			continue;
		}
		(ils->ils_listen->il_accept)(so, sa, ils->ils_id);
	}
}
static void icl_accept_thread ( void * arg ) { struct icl_listen_sock * ils ; struct socket * head , * so ; struct sockaddr * sa ; int error ; ils = arg ; head = ils -> ils_socket ; ils -> ils_running = true ; for ( ; ; ) { ACCEPT_LOCK ( ) ; while ( TAILQ_EMPTY ( & head -> so_comp ) && head -> so_error == 0 && ils -> ils_disconnecting == false ) { if ( head -> so_rcv . sb_state & SBS_CANTRCVMORE ) { head -> so_error = ECONNABORTED ; break ; } error = msleep ( & head -> so_timeo , & accept_mtx , PSOCK | PCATCH , " " , 0 ) ; if ( error ) { ACCEPT_UNLOCK ( ) ; ICL_WARN ( " " , error ) ; continue ; } if ( ils -> ils_disconnecting ) { ACCEPT_UNLOCK ( ) ; ICL_DEBUG ( " " ) ; ils -> ils_running = false ; kthread_exit ( ) ; return ; } } if ( head -> so_error ) { error = head -> so_error ; head -> so_error = 0 ; ACCEPT_UNLOCK ( ) ; ICL_WARN ( " " , error ) ; continue ; } so = TAILQ_FIRST ( & head -> so_comp ) ; KASSERT ( so != NULL , ( " " ) ) ; KASSERT ( ! ( so -> so_qstate & SQ_INCOMP ) , ( " " ) ) ; KASSERT ( so -> so_qstate & SQ_COMP , ( " " ) ) ; SOCK_LOCK ( so ) ; soref ( so ) ; TAILQ_REMOVE ( & head -> so_comp , so , so_list ) ; head -> so_qlen -- ; so -> so_state |= ( head -> so_state & SS_NBIO ) ; so -> so_qstate &= ~ SQ_COMP ; so -> so_head = NULL ; SOCK_UNLOCK ( so ) ; ACCEPT_UNLOCK ( ) ; sa = NULL ; error = soaccept ( so , & sa ) ; if ( error != 0 ) { ICL_WARN ( " " , error ) ; if ( sa != NULL ) free ( sa , M_SONAME ) ; soclose ( so ) ; continue ; } ( ils -> ils_listen -> il_accept ) ( so , sa , ils -> ils_id ) ; } }
XXX: Doing accept in a separate thread in each socket might not be the best way
      to do stuff, but it's pretty clean and debuggable - and you probably won't
      have hundreds of listening sockets anyway.
XXX : Doing accept in a separate thread in each socket might not be the best way to do stuff but it ' s pretty clean and debuggable - and you probably won ' t have hundreds of listening sockets anyway .
/*
		 * Before changing the flags on the socket, we have to bump the
		 * reference count.  Otherwise, if the protocol calls sofree(),
		 * the socket will be released due to a zero refcount.
		 */ /* soref() and so_state update */ /* file descriptor reference */