コード例 #1
0
unsigned int datagram_poll(struct file * file, struct socket *sock, poll_table *wait)
{
	struct sock *sk = sock->sk;
	unsigned int mask;

	poll_wait(file, sk->sleep, wait);
	mask = 0;

	/* exceptional events? */
	if (sk->err || !skb_queue_empty(&sk->error_queue))
		mask |= POLLERR;
	if (sk->shutdown == SHUTDOWN_MASK)
		mask |= POLLHUP;

	/* readable? */
	if (!skb_queue_empty(&sk->receive_queue) || (sk->shutdown&RCV_SHUTDOWN))
		mask |= POLLIN | POLLRDNORM;

	/* Connection-based need to check for termination and startup */
	if (connection_based(sk)) {
		if (sk->state==TCP_CLOSE)
			mask |= POLLHUP;
		/* connection hasn't started yet? */
		if (sk->state == TCP_SYN_SENT)
			return mask;
	}

	/* writable? */
	if (sock_writeable(sk))
		mask |= POLLOUT | POLLWRNORM | POLLWRBAND;
	else
		set_bit(SOCK_ASYNC_NOSPACE, &sk->socket->flags);

	return mask;
}
コード例 #2
0
static int wait_for_packet(struct sock * sk, int *err, long *timeo_p)
{
	int error;

	DECLARE_WAITQUEUE(wait, current);

	__set_current_state(TASK_INTERRUPTIBLE);
	add_wait_queue_exclusive(sk->sleep, &wait);

	/* Socket errors? */
	error = sock_error(sk);
	if (error)
		goto out_err;

	if (!skb_queue_empty(&sk->receive_queue))
		goto ready;

	/* Socket shut down? */
	if (sk->shutdown & RCV_SHUTDOWN)
		goto out_noerr;

	/* Sequenced packets can come disconnected. If so we report the problem */
	error = -ENOTCONN;
	if(connection_based(sk) && !(sk->state==TCP_ESTABLISHED || sk->state==TCP_LISTEN))
		goto out_err;

	/* handle signals */
	if (signal_pending(current))
		goto interrupted;

	*timeo_p = schedule_timeout(*timeo_p);

ready:
	current->state = TASK_RUNNING;
	remove_wait_queue(sk->sleep, &wait);
	return 0;

interrupted:
	error = sock_intr_errno(*timeo_p);
out_err:
	*err = error;
out:
	current->state = TASK_RUNNING;
	remove_wait_queue(sk->sleep, &wait);
	return error;
out_noerr:
	*err = 0;
	error = 1;
	goto out;
}
/*
 * Wait for a packet..
 */
static int wait_for_packet(struct sock *sk, int *err, long *timeo_p)
{
	int error;
	DEFINE_WAIT_FUNC(wait, receiver_wake_function);
    /* 
     前面的操作都是初始化wait,为将socket加入wait队列作准备,这部分代码牵涉到进程调度。关于进程调度,我      只是知道一些皮毛,留在以后学习。这里只需要将其看作是一些加入wait队列的准备工作即可,并不影响理解代码      。
     */
	prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);

	/* Socket errors? */
	error = sock_error(sk);
	if (error)
		goto out_err;
    /* 一个完备检测。在决定wait和调用wait之间,有数据包到了,那么就不需要wait,所以这里再次检查socket      的队列是否为空 */

	if (!skb_queue_empty(&sk->sk_receive_queue))
		goto out;

	/* Socket shut down? */
	/* 完备检测。也许socket无数据包读取,因为socket已经被另外的线程关闭了。这样可以保证关闭socket的时      候,不会导致其他的socket的读写操作被阻塞。*/
	if (sk->sk_shutdown & RCV_SHUTDOWN)
		goto out_noerr;

	/* Sequenced packets can come disconnected.
	 * If so we report the problem
	 *//* 对于面向连接的socket进行检查。如果是面向连接的socket,如果不是已经建立连接或者正在监听状态的so       cket是不可能有数据包的。不然即出错*/
	error = -ENOTCONN;
	if (connection_based(sk) &&
	    !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN))
		goto out_err;

	/* handle signals */
	if (signal_pending(current))/* 检查是否有pending的signal,保证阻塞时,进程可以被signal唤醒 */
		goto interrupted;

	error = 0;
	*timeo_p = schedule_timeout(*timeo_p); /* sleep本进程,直至满足唤醒条件或者被信号唤醒——因为前面设置了TASK_INTERRUPTIBLE*/
out:
	finish_wait(sk_sleep(sk), &wait); /* wait队列的清理工作 */
	return error;
interrupted:
	error = sock_intr_errno(*timeo_p);
out_err:
	*err = error;
	goto out;
out_noerr:
	*err = 0;
	error = 1;
	goto out;
}
コード例 #4
0
static void skb_async_read_worker(void *_data)
{
	struct skb_async_info	*info = _data;
	int error;

	/* Socket errors? */
	error = sock_error(sk);
	if (error)
		goto out_err;

	if (!skb_queue_empty(&sk->receive_queue))
		goto ready;

	/* Socket shut down? */
	if (sk->shutdown & RCV_SHUTDOWN)
		goto out_noerr;

	/* Sequenced packets can come disconnected. If so we report the problem */
	error = -ENOTCONN;
	if(connection_based(sk) && !(sk->state==TCP_ESTABLISHED || sk->state==TCP_LISTEN))
		goto out_err;

	/* handle signals */
	if (signal_pending(current))
		goto interrupted;

	/* here: queue sleep */
	*timeo_p = schedule_timeout(*timeo_p);
	return;

ready:
	current->state = TASK_RUNNING;
	remove_wait_queue(sk->sleep, &wait);
	return 0;

interrupted:
	error = sock_intr_errno(*timeo_p);
out_err:
	*err = error;
out:
	current->state = TASK_RUNNING;
	remove_wait_queue(sk->sleep, &wait);
	return error;
out_noerr:
	*err = 0;
	error = 1;
	goto out;
}
コード例 #5
0
ファイル: datagram.c プロジェクト: 3null/linux
/*
 * Wait for the last received packet to be different from skb
 */
static int wait_for_more_packets(struct sock *sk, int *err, long *timeo_p,
				 const struct sk_buff *skb)
{
	int error;
	DEFINE_WAIT_FUNC(wait, receiver_wake_function);

	prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);

	/* Socket errors? */
	error = sock_error(sk);
	if (error)
		goto out_err;

	if (sk->sk_receive_queue.prev != skb)
		goto out;

	/* Socket shut down? */
	if (sk->sk_shutdown & RCV_SHUTDOWN)
		goto out_noerr;

	/* Sequenced packets can come disconnected.
	 * If so we report the problem
	 */
	error = -ENOTCONN;
	if (connection_based(sk) &&
	    !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN))
		goto out_err;

	/* handle signals */
	if (signal_pending(current))
		goto interrupted;

	error = 0;
	*timeo_p = schedule_timeout(*timeo_p);
out:
	finish_wait(sk_sleep(sk), &wait);
	return error;
interrupted:
	error = sock_intr_errno(*timeo_p);
out_err:
	*err = error;
	goto out;
out_noerr:
	*err = 0;
	error = 1;
	goto out;
}
コード例 #6
0
static int wait_for_packet(struct sock *sk, int *err, long *timeo_p)
{
	int error;
	DEFINE_WAIT_FUNC(wait, receiver_wake_function);

	prepare_to_wait_exclusive(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);

	
	error = sock_error(sk);
	if (error)
		goto out_err;

	if (!skb_queue_empty(&sk->sk_receive_queue))
		goto out;

	
	if (sk->sk_shutdown & RCV_SHUTDOWN)
		goto out_noerr;

	error = -ENOTCONN;
	if (connection_based(sk) &&
	    !(sk->sk_state == TCP_ESTABLISHED || sk->sk_state == TCP_LISTEN))
		goto out_err;

	
	if (signal_pending(current))
		goto interrupted;

	error = 0;
	*timeo_p = schedule_timeout(*timeo_p);
out:
	finish_wait(sk_sleep(sk), &wait);
	return error;
interrupted:
	error = sock_intr_errno(*timeo_p);
out_err:
	*err = error;
	goto out;
out_noerr:
	*err = 0;
	error = 1;
	goto out;
}
コード例 #7
0
ファイル: datagram.c プロジェクト: GNUHurdTR/hurd
struct sk_buff *skb_recv_datagram(struct sock *sk, unsigned flags, int noblock, int *err)
{
	int error;
	struct sk_buff *skb;

	/* Caller is allowed not to check sk->err before skb_recv_datagram() */
	error = sock_error(sk);
	if (error)
		goto no_packet;

restart:
	while(skb_queue_empty(&sk->receive_queue))	/* No data */
	{
		/* Socket errors? */
		error = sock_error(sk);
		if (error)
			goto no_packet;

		/* Socket shut down? */
		if (sk->shutdown & RCV_SHUTDOWN)
			goto no_packet;

		/* Sequenced packets can come disconnected. If so we report the problem */
		error = -ENOTCONN;
		if(connection_based(sk) && sk->state!=TCP_ESTABLISHED)
			goto no_packet;

		/* handle signals */
		error = -ERESTARTSYS;
		if (signal_pending(current))
			goto no_packet;

		/* User doesn't want to wait */
		error = -EAGAIN;
		if (noblock)
			goto no_packet;

		wait_for_packet(sk);
	}

	/* Again only user level code calls this function, so nothing interrupt level
	   will suddenly eat the receive_queue */
	if (flags & MSG_PEEK)
	{
		unsigned long cpu_flags;

		/* It is the only POTENTIAL race condition
		   in this function. skb may be stolen by
		   another receiver after peek, but before
		   incrementing use count, provided kernel
		   is reentearble (it is not) or this function
		   is called by interrupts.

		   Protect it with global skb spinlock,
		   though for now even this is overkill.
		                                --ANK (980728)
		 */
		spin_lock_irqsave(&skb_queue_lock, cpu_flags);
		skb = skb_peek(&sk->receive_queue);
		if(skb!=NULL)
			atomic_inc(&skb->users);
		spin_unlock_irqrestore(&skb_queue_lock, cpu_flags);
	} else
		skb = skb_dequeue(&sk->receive_queue);

	if (!skb)	/* Avoid race if someone beats us to the data */
		goto restart;
	return skb;

no_packet:
	*err = error;
	return NULL;
}