Commit cdcdbe0b authored by Luiz Capitulino's avatar Luiz Capitulino Committed by David S. Miller
Browse files

[PKTGEN]: Ports thread list to Kernel list implementation.



The final result is a simpler and smaller code.

Note that I'm adding a new member in the struct pktgen_thread called
'removed'. The reason is that I didn't find a better wait condition to
be used in the place of the replaced one.

Signed-off-by: default avatarLuiz Capitulino <lcapitulino@mandriva.com.br>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 222f1806
Loading
Loading
Loading
Loading
+41 −55
Original line number Original line Diff line number Diff line
@@ -125,6 +125,7 @@
#include <linux/capability.h>
#include <linux/capability.h>
#include <linux/delay.h>
#include <linux/delay.h>
#include <linux/timer.h>
#include <linux/timer.h>
#include <linux/list.h>
#include <linux/init.h>
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/skbuff.h>
#include <linux/netdevice.h>
#include <linux/netdevice.h>
@@ -330,7 +331,8 @@ struct pktgen_hdr {
struct pktgen_thread {
struct pktgen_thread {
	spinlock_t if_lock;
	spinlock_t if_lock;
	struct pktgen_dev *if_list;	/* All device here */
	struct pktgen_dev *if_list;	/* All device here */
	struct pktgen_thread *next;
	struct list_head th_list;
	int removed;
	char name[32];
	char name[32];
	char result[512];
	char result[512];
	u32 max_before_softirq;	/* We'll call do_softirq to prevent starvation. */
	u32 max_before_softirq;	/* We'll call do_softirq to prevent starvation. */
@@ -492,7 +494,7 @@ static int pg_clone_skb_d;
static int debug;
static int debug;


static DECLARE_MUTEX(pktgen_sem);
static DECLARE_MUTEX(pktgen_sem);
static struct pktgen_thread *pktgen_threads = NULL;
static LIST_HEAD(pktgen_threads);


static struct notifier_block pktgen_notifier_block = {
static struct notifier_block pktgen_notifier_block = {
	.notifier_call = pktgen_device_event,
	.notifier_call = pktgen_device_event,
@@ -1522,9 +1524,7 @@ static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
	struct pktgen_thread *t;
	struct pktgen_thread *t;
	struct pktgen_dev *pkt_dev = NULL;
	struct pktgen_dev *pkt_dev = NULL;


	t = pktgen_threads;
	list_for_each_entry(t, &pktgen_threads, th_list) {

	while (t) {
		pkt_dev = pktgen_find_dev(t, ifname);
		pkt_dev = pktgen_find_dev(t, ifname);
		if (pkt_dev) {
		if (pkt_dev) {
			if (remove) {
			if (remove) {
@@ -1535,7 +1535,6 @@ static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove)
			}
			}
			break;
			break;
		}
		}
		t = t->next;
	}
	}
	return pkt_dev;
	return pkt_dev;
}
}
@@ -2455,15 +2454,15 @@ static void pktgen_run(struct pktgen_thread *t)


static void pktgen_stop_all_threads_ifs(void)
static void pktgen_stop_all_threads_ifs(void)
{
{
	struct pktgen_thread *t = pktgen_threads;
	struct pktgen_thread *t;


	PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n"));
	PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n"));


	thread_lock();
	thread_lock();
	while (t) {

	list_for_each_entry(t, &pktgen_threads, th_list)
		t->control |= T_STOP;
		t->control |= T_STOP;
		t = t->next;

	}
	thread_unlock();
	thread_unlock();
}
}


@@ -2503,40 +2502,36 @@ static int pktgen_wait_thread_run(struct pktgen_thread *t)


static int pktgen_wait_all_threads_run(void)
static int pktgen_wait_all_threads_run(void)
{
{
	struct pktgen_thread *t = pktgen_threads;
	struct pktgen_thread *t;
	int sig = 1;
	int sig = 1;


	while (t) {
	thread_lock();

	list_for_each_entry(t, &pktgen_threads, th_list) {
		sig = pktgen_wait_thread_run(t);
		sig = pktgen_wait_thread_run(t);
		if (sig == 0)
		if (sig == 0)
			break;
			break;
		thread_lock();
		t = t->next;
		thread_unlock();
	}
	}
	if (sig == 0) {

		thread_lock();
	if (sig == 0)
		while (t) {
		list_for_each_entry(t, &pktgen_threads, th_list)
			t->control |= (T_STOP);
			t->control |= (T_STOP);
			t = t->next;

		}
	thread_unlock();
	thread_unlock();
	}
	return sig;
	return sig;
}
}


static void pktgen_run_all_threads(void)
static void pktgen_run_all_threads(void)
{
{
	struct pktgen_thread *t = pktgen_threads;
	struct pktgen_thread *t;


	PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));
	PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n"));


	thread_lock();
	thread_lock();


	while (t) {
	list_for_each_entry(t, &pktgen_threads, th_list)
		t->control |= (T_RUN);
		t->control |= (T_RUN);
		t = t->next;

	}
	thread_unlock();
	thread_unlock();


	schedule_timeout_interruptible(msecs_to_jiffies(125));	/* Propagate thread->control  */
	schedule_timeout_interruptible(msecs_to_jiffies(125));	/* Propagate thread->control  */
@@ -2693,24 +2688,12 @@ static void pktgen_rem_thread(struct pktgen_thread *t)
{
{
	/* Remove from the thread list */
	/* Remove from the thread list */


	struct pktgen_thread *tmp = pktgen_threads;

	remove_proc_entry(t->name, pg_proc_dir);
	remove_proc_entry(t->name, pg_proc_dir);


	thread_lock();
	thread_lock();


	if (tmp == t)
	list_del(&t->th_list);
		pktgen_threads = tmp->next;

	else {
		while (tmp) {
			if (tmp->next == t) {
				tmp->next = t->next;
				t->next = NULL;
				break;
			}
			tmp = tmp->next;
		}
	}
	thread_unlock();
	thread_unlock();
}
}


@@ -2969,6 +2952,8 @@ static void pktgen_thread_worker(struct pktgen_thread *t)


	PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
	PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name));
	pktgen_rem_thread(t);
	pktgen_rem_thread(t);

	t->removed = 1;
}
}


static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t,
@@ -3081,21 +3066,20 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname)


static struct pktgen_thread *__init pktgen_find_thread(const char *name)
static struct pktgen_thread *__init pktgen_find_thread(const char *name)
{
{
	struct pktgen_thread *t = NULL;
	struct pktgen_thread *t;


	thread_lock();
	thread_lock();


	t = pktgen_threads;
	list_for_each_entry(t, &pktgen_threads, th_list)
	while (t) {
		if (strcmp(t->name, name) == 0) {
		if (strcmp(t->name, name) == 0)
			break;

		t = t->next;
	}
			thread_unlock();
			thread_unlock();
			return t;
			return t;
		}
		}


	thread_unlock();
	return NULL;
}

static int __init pktgen_create_thread(const char *name, int cpu)
static int __init pktgen_create_thread(const char *name, int cpu)
{
{
	struct pktgen_thread *t = NULL;
	struct pktgen_thread *t = NULL;
@@ -3132,8 +3116,9 @@ static int __init pktgen_create_thread(const char *name, int cpu)
	pe->proc_fops = &pktgen_thread_fops;
	pe->proc_fops = &pktgen_thread_fops;
	pe->data = t;
	pe->data = t;


	t->next = pktgen_threads;
	list_add_tail(&t->th_list, &pktgen_threads);
	pktgen_threads = t;

	t->removed = 0;


	if (kernel_thread((void *)pktgen_thread_worker, (void *)t,
	if (kernel_thread((void *)pktgen_thread_worker, (void *)t,
			  CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0)
			  CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0)
@@ -3234,17 +3219,18 @@ static int __init pg_init(void)


static void __exit pg_cleanup(void)
static void __exit pg_cleanup(void)
{
{
	struct pktgen_thread *t;
	struct list_head *q, *n;
	wait_queue_head_t queue;
	wait_queue_head_t queue;
	init_waitqueue_head(&queue);
	init_waitqueue_head(&queue);


	/* Stop all interfaces & threads */
	/* Stop all interfaces & threads */


	while (pktgen_threads) {
	list_for_each_safe(q, n, &pktgen_threads) {
		struct pktgen_thread *t = pktgen_threads;
		t = list_entry(q, struct pktgen_thread, th_list);
		pktgen_threads->control |= (T_TERMINATE);
		t->control |= (T_TERMINATE);


		wait_event_interruptible_timeout(queue, (t != pktgen_threads),
		wait_event_interruptible_timeout(queue, (t->removed == 1), HZ);
						 HZ);
	}
	}


	/* Un-register us from receiving netdevice events */
	/* Un-register us from receiving netdevice events */