krxiod.c

来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 260 行

C
260
字号
/* krxiod.c: Rx I/O daemon * * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved. * Written by David Howells (dhowells@redhat.com) * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */#include <linux/sched.h>#include <linux/completion.h>#include <linux/spinlock.h>#include <linux/init.h>#include <rxrpc/krxiod.h>#include <rxrpc/transport.h>#include <rxrpc/peer.h>#include <rxrpc/call.h>#include "internal.h"static DECLARE_WAIT_QUEUE_HEAD(rxrpc_krxiod_sleepq);static DECLARE_COMPLETION(rxrpc_krxiod_dead);static atomic_t rxrpc_krxiod_qcount = ATOMIC_INIT(0);static LIST_HEAD(rxrpc_krxiod_transportq);static spinlock_t rxrpc_krxiod_transportq_lock = SPIN_LOCK_UNLOCKED;static LIST_HEAD(rxrpc_krxiod_callq);static spinlock_t rxrpc_krxiod_callq_lock = SPIN_LOCK_UNLOCKED;static volatile int rxrpc_krxiod_die;/*****************************************************************************//* * Rx I/O daemon */static int rxrpc_krxiod(void *arg){	DECLARE_WAITQUEUE(krxiod,current);	printk("Started krxiod %d\n",current->pid);	daemonize("krxiod");	/* loop around waiting for work to do */	do {		/* wait for work or to be told to exit */		_debug("### Begin Wait");		if (!atomic_read(&rxrpc_krxiod_qcount)) {			set_current_state(TASK_INTERRUPTIBLE);			add_wait_queue(&rxrpc_krxiod_sleepq, &krxiod);			for (;;) {				set_current_state(TASK_INTERRUPTIBLE);				if (atomic_read(&rxrpc_krxiod_qcount) ||				    rxrpc_krxiod_die ||				    signal_pending(current))					break;				schedule();			}			remove_wait_queue(&rxrpc_krxiod_sleepq, &krxiod);			set_current_state(TASK_RUNNING);		}		_debug("### End Wait");		/* do work if been given some to do */		_debug("### Begin Work");		/* see if there's a transport in need of attention */		if (!list_empty(&rxrpc_krxiod_transportq)) {			struct rxrpc_transport *trans = NULL;			spin_lock_irq(&rxrpc_krxiod_transportq_lock);			if (!list_empty(&rxrpc_krxiod_transportq)) {				trans = list_entry(					rxrpc_krxiod_transportq.next,					struct rxrpc_transport,					krxiodq_link);				list_del_init(&trans->krxiodq_link);				atomic_dec(&rxrpc_krxiod_qcount);				/* make sure it hasn't gone away and doesn't go				 * away */				if (atomic_read(&trans->usage)>0)					rxrpc_get_transport(trans);				else					trans = NULL;			}			spin_unlock_irq(&rxrpc_krxiod_transportq_lock);			if (trans) {				rxrpc_trans_receive_packet(trans);				rxrpc_put_transport(trans);			}		}		/* see if there's a call in need of attention */		if (!list_empty(&rxrpc_krxiod_callq)) {			struct rxrpc_call *call = NULL;			spin_lock_irq(&rxrpc_krxiod_callq_lock);			if (!list_empty(&rxrpc_krxiod_callq)) {				call = list_entry(rxrpc_krxiod_callq.next,						  struct rxrpc_call,						  rcv_krxiodq_lk);				list_del_init(&call->rcv_krxiodq_lk);				atomic_dec(&rxrpc_krxiod_qcount);				/* make sure it hasn't gone away and doesn't go				 * away */				if (atomic_read(&call->usage) > 0) {					_debug("@@@ KRXIOD"					       " Begin Attend Call %p", call);					rxrpc_get_call(call);				}				else {					call = NULL;				}			}			spin_unlock_irq(&rxrpc_krxiod_callq_lock);			if (call) {				rxrpc_call_do_stuff(call);				rxrpc_put_call(call);				_debug("@@@ KRXIOD End Attend Call %p", call);			}		}		_debug("### End Work");                /* discard pending signals */		rxrpc_discard_my_signals();	} while (!rxrpc_krxiod_die);	/* and that's all */	complete_and_exit(&rxrpc_krxiod_dead, 0);} /* end rxrpc_krxiod() *//*****************************************************************************//* * start up a krxiod daemon */int __init rxrpc_krxiod_init(void){	return kernel_thread(rxrpc_krxiod, NULL, 0);} /* end rxrpc_krxiod_init() *//*****************************************************************************//* * kill the krxiod daemon and wait for it to complete */void rxrpc_krxiod_kill(void){	rxrpc_krxiod_die = 1;	wake_up_all(&rxrpc_krxiod_sleepq);	wait_for_completion(&rxrpc_krxiod_dead);} /* end rxrpc_krxiod_kill() *//*****************************************************************************//* * queue a transport for attention by krxiod */void rxrpc_krxiod_queue_transport(struct rxrpc_transport *trans){	unsigned long flags;	_enter("");	if (list_empty(&trans->krxiodq_link)) {		spin_lock_irqsave(&rxrpc_krxiod_transportq_lock, flags);		if (list_empty(&trans->krxiodq_link)) {			if (atomic_read(&trans->usage) > 0) {				list_add_tail(&trans->krxiodq_link,					      &rxrpc_krxiod_transportq);				atomic_inc(&rxrpc_krxiod_qcount);			}		}		spin_unlock_irqrestore(&rxrpc_krxiod_transportq_lock, flags);		wake_up_all(&rxrpc_krxiod_sleepq);	}	_leave("");} /* end rxrpc_krxiod_queue_transport() *//*****************************************************************************//* * dequeue a transport from krxiod's attention queue */void rxrpc_krxiod_dequeue_transport(struct rxrpc_transport *trans){	unsigned long flags;	_enter("");	spin_lock_irqsave(&rxrpc_krxiod_transportq_lock, flags);	if (!list_empty(&trans->krxiodq_link)) {		list_del_init(&trans->krxiodq_link);		atomic_dec(&rxrpc_krxiod_qcount);	}	spin_unlock_irqrestore(&rxrpc_krxiod_transportq_lock, flags);	_leave("");} /* end rxrpc_krxiod_dequeue_transport() *//*****************************************************************************//* * queue a call for attention by krxiod */void rxrpc_krxiod_queue_call(struct rxrpc_call *call){	unsigned long flags;	if (list_empty(&call->rcv_krxiodq_lk)) {		spin_lock_irqsave(&rxrpc_krxiod_callq_lock, flags);		if (atomic_read(&call->usage) > 0) {			list_add_tail(&call->rcv_krxiodq_lk,				      &rxrpc_krxiod_callq);			atomic_inc(&rxrpc_krxiod_qcount);		}		spin_unlock_irqrestore(&rxrpc_krxiod_callq_lock, flags);	}	wake_up_all(&rxrpc_krxiod_sleepq);} /* end rxrpc_krxiod_queue_call() *//*****************************************************************************//* * dequeue a call from krxiod's attention queue */void rxrpc_krxiod_dequeue_call(struct rxrpc_call *call){	unsigned long flags;	spin_lock_irqsave(&rxrpc_krxiod_callq_lock, flags);	if (!list_empty(&call->rcv_krxiodq_lk)) {		list_del_init(&call->rcv_krxiodq_lk);		atomic_dec(&rxrpc_krxiod_qcount);	}	spin_unlock_irqrestore(&rxrpc_krxiod_callq_lock, flags);} /* end rxrpc_krxiod_dequeue_call() */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?