diff options
author | Luiz Capitulino <lcapitulino@mandriva.com.br> | 2006-03-21 01:16:40 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2006-03-21 01:16:40 -0500 |
commit | cdcdbe0b179adca0bcf98f660fcc63e208ae4284 (patch) | |
tree | 06e20bb4e3dc8f5cacec067c8021aab2976c5971 | |
parent | 222f18065868b04df92df476b19c99c28740e00f (diff) |
[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: Luiz Capitulino <lcapitulino@mandriva.com.br>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | net/core/pktgen.c | 96 |
1 files changed, 41 insertions, 55 deletions
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index e49b006a7654..f2c0e965c139 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -125,6 +125,7 @@ | |||
125 | #include <linux/capability.h> | 125 | #include <linux/capability.h> |
126 | #include <linux/delay.h> | 126 | #include <linux/delay.h> |
127 | #include <linux/timer.h> | 127 | #include <linux/timer.h> |
128 | #include <linux/list.h> | ||
128 | #include <linux/init.h> | 129 | #include <linux/init.h> |
129 | #include <linux/skbuff.h> | 130 | #include <linux/skbuff.h> |
130 | #include <linux/netdevice.h> | 131 | #include <linux/netdevice.h> |
@@ -330,7 +331,8 @@ struct pktgen_hdr { | |||
330 | struct pktgen_thread { | 331 | struct pktgen_thread { |
331 | spinlock_t if_lock; | 332 | spinlock_t if_lock; |
332 | struct pktgen_dev *if_list; /* All device here */ | 333 | struct pktgen_dev *if_list; /* All device here */ |
333 | struct pktgen_thread *next; | 334 | struct list_head th_list; |
335 | int removed; | ||
334 | char name[32]; | 336 | char name[32]; |
335 | char result[512]; | 337 | char result[512]; |
336 | u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */ | 338 | u32 max_before_softirq; /* We'll call do_softirq to prevent starvation. */ |
@@ -492,7 +494,7 @@ static int pg_clone_skb_d; | |||
492 | static int debug; | 494 | static int debug; |
493 | 495 | ||
494 | static DECLARE_MUTEX(pktgen_sem); | 496 | static DECLARE_MUTEX(pktgen_sem); |
495 | static struct pktgen_thread *pktgen_threads = NULL; | 497 | static LIST_HEAD(pktgen_threads); |
496 | 498 | ||
497 | static struct notifier_block pktgen_notifier_block = { | 499 | static struct notifier_block pktgen_notifier_block = { |
498 | .notifier_call = pktgen_device_event, | 500 | .notifier_call = pktgen_device_event, |
@@ -1522,9 +1524,7 @@ static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove) | |||
1522 | struct pktgen_thread *t; | 1524 | struct pktgen_thread *t; |
1523 | struct pktgen_dev *pkt_dev = NULL; | 1525 | struct pktgen_dev *pkt_dev = NULL; |
1524 | 1526 | ||
1525 | t = pktgen_threads; | 1527 | list_for_each_entry(t, &pktgen_threads, th_list) { |
1526 | |||
1527 | while (t) { | ||
1528 | pkt_dev = pktgen_find_dev(t, ifname); | 1528 | pkt_dev = pktgen_find_dev(t, ifname); |
1529 | if (pkt_dev) { | 1529 | if (pkt_dev) { |
1530 | if (remove) { | 1530 | if (remove) { |
@@ -1535,7 +1535,6 @@ static struct pktgen_dev *__pktgen_NN_threads(const char *ifname, int remove) | |||
1535 | } | 1535 | } |
1536 | break; | 1536 | break; |
1537 | } | 1537 | } |
1538 | t = t->next; | ||
1539 | } | 1538 | } |
1540 | return pkt_dev; | 1539 | return pkt_dev; |
1541 | } | 1540 | } |
@@ -2455,15 +2454,15 @@ static void pktgen_run(struct pktgen_thread *t) | |||
2455 | 2454 | ||
2456 | static void pktgen_stop_all_threads_ifs(void) | 2455 | static void pktgen_stop_all_threads_ifs(void) |
2457 | { | 2456 | { |
2458 | struct pktgen_thread *t = pktgen_threads; | 2457 | struct pktgen_thread *t; |
2459 | 2458 | ||
2460 | PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n")); | 2459 | PG_DEBUG(printk("pktgen: entering pktgen_stop_all_threads_ifs.\n")); |
2461 | 2460 | ||
2462 | thread_lock(); | 2461 | thread_lock(); |
2463 | while (t) { | 2462 | |
2463 | list_for_each_entry(t, &pktgen_threads, th_list) | ||
2464 | t->control |= T_STOP; | 2464 | t->control |= T_STOP; |
2465 | t = t->next; | 2465 | |
2466 | } | ||
2467 | thread_unlock(); | 2466 | thread_unlock(); |
2468 | } | 2467 | } |
2469 | 2468 | ||
@@ -2503,40 +2502,36 @@ signal: | |||
2503 | 2502 | ||
2504 | static int pktgen_wait_all_threads_run(void) | 2503 | static int pktgen_wait_all_threads_run(void) |
2505 | { | 2504 | { |
2506 | struct pktgen_thread *t = pktgen_threads; | 2505 | struct pktgen_thread *t; |
2507 | int sig = 1; | 2506 | int sig = 1; |
2508 | 2507 | ||
2509 | while (t) { | 2508 | thread_lock(); |
2509 | |||
2510 | list_for_each_entry(t, &pktgen_threads, th_list) { | ||
2510 | sig = pktgen_wait_thread_run(t); | 2511 | sig = pktgen_wait_thread_run(t); |
2511 | if (sig == 0) | 2512 | if (sig == 0) |
2512 | break; | 2513 | break; |
2513 | thread_lock(); | ||
2514 | t = t->next; | ||
2515 | thread_unlock(); | ||
2516 | } | 2514 | } |
2517 | if (sig == 0) { | 2515 | |
2518 | thread_lock(); | 2516 | if (sig == 0) |
2519 | while (t) { | 2517 | list_for_each_entry(t, &pktgen_threads, th_list) |
2520 | t->control |= (T_STOP); | 2518 | t->control |= (T_STOP); |
2521 | t = t->next; | 2519 | |
2522 | } | 2520 | thread_unlock(); |
2523 | thread_unlock(); | ||
2524 | } | ||
2525 | return sig; | 2521 | return sig; |
2526 | } | 2522 | } |
2527 | 2523 | ||
2528 | static void pktgen_run_all_threads(void) | 2524 | static void pktgen_run_all_threads(void) |
2529 | { | 2525 | { |
2530 | struct pktgen_thread *t = pktgen_threads; | 2526 | struct pktgen_thread *t; |
2531 | 2527 | ||
2532 | PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n")); | 2528 | PG_DEBUG(printk("pktgen: entering pktgen_run_all_threads.\n")); |
2533 | 2529 | ||
2534 | thread_lock(); | 2530 | thread_lock(); |
2535 | 2531 | ||
2536 | while (t) { | 2532 | list_for_each_entry(t, &pktgen_threads, th_list) |
2537 | t->control |= (T_RUN); | 2533 | t->control |= (T_RUN); |
2538 | t = t->next; | 2534 | |
2539 | } | ||
2540 | thread_unlock(); | 2535 | thread_unlock(); |
2541 | 2536 | ||
2542 | schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */ | 2537 | schedule_timeout_interruptible(msecs_to_jiffies(125)); /* Propagate thread->control */ |
@@ -2693,24 +2688,12 @@ static void pktgen_rem_thread(struct pktgen_thread *t) | |||
2693 | { | 2688 | { |
2694 | /* Remove from the thread list */ | 2689 | /* Remove from the thread list */ |
2695 | 2690 | ||
2696 | struct pktgen_thread *tmp = pktgen_threads; | ||
2697 | |||
2698 | remove_proc_entry(t->name, pg_proc_dir); | 2691 | remove_proc_entry(t->name, pg_proc_dir); |
2699 | 2692 | ||
2700 | thread_lock(); | 2693 | thread_lock(); |
2701 | 2694 | ||
2702 | if (tmp == t) | 2695 | list_del(&t->th_list); |
2703 | pktgen_threads = tmp->next; | 2696 | |
2704 | else { | ||
2705 | while (tmp) { | ||
2706 | if (tmp->next == t) { | ||
2707 | tmp->next = t->next; | ||
2708 | t->next = NULL; | ||
2709 | break; | ||
2710 | } | ||
2711 | tmp = tmp->next; | ||
2712 | } | ||
2713 | } | ||
2714 | thread_unlock(); | 2697 | thread_unlock(); |
2715 | } | 2698 | } |
2716 | 2699 | ||
@@ -2969,6 +2952,8 @@ static void pktgen_thread_worker(struct pktgen_thread *t) | |||
2969 | 2952 | ||
2970 | PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name)); | 2953 | PG_DEBUG(printk("pktgen: %s removing thread.\n", t->name)); |
2971 | pktgen_rem_thread(t); | 2954 | pktgen_rem_thread(t); |
2955 | |||
2956 | t->removed = 1; | ||
2972 | } | 2957 | } |
2973 | 2958 | ||
2974 | static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, | 2959 | static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, |
@@ -3081,19 +3066,18 @@ static int pktgen_add_device(struct pktgen_thread *t, const char *ifname) | |||
3081 | 3066 | ||
3082 | static struct pktgen_thread *__init pktgen_find_thread(const char *name) | 3067 | static struct pktgen_thread *__init pktgen_find_thread(const char *name) |
3083 | { | 3068 | { |
3084 | struct pktgen_thread *t = NULL; | 3069 | struct pktgen_thread *t; |
3085 | 3070 | ||
3086 | thread_lock(); | 3071 | thread_lock(); |
3087 | 3072 | ||
3088 | t = pktgen_threads; | 3073 | list_for_each_entry(t, &pktgen_threads, th_list) |
3089 | while (t) { | 3074 | if (strcmp(t->name, name) == 0) { |
3090 | if (strcmp(t->name, name) == 0) | 3075 | thread_unlock(); |
3091 | break; | 3076 | return t; |
3077 | } | ||
3092 | 3078 | ||
3093 | t = t->next; | ||
3094 | } | ||
3095 | thread_unlock(); | 3079 | thread_unlock(); |
3096 | return t; | 3080 | return NULL; |
3097 | } | 3081 | } |
3098 | 3082 | ||
3099 | static int __init pktgen_create_thread(const char *name, int cpu) | 3083 | static int __init pktgen_create_thread(const char *name, int cpu) |
@@ -3132,8 +3116,9 @@ static int __init pktgen_create_thread(const char *name, int cpu) | |||
3132 | pe->proc_fops = &pktgen_thread_fops; | 3116 | pe->proc_fops = &pktgen_thread_fops; |
3133 | pe->data = t; | 3117 | pe->data = t; |
3134 | 3118 | ||
3135 | t->next = pktgen_threads; | 3119 | list_add_tail(&t->th_list, &pktgen_threads); |
3136 | pktgen_threads = t; | 3120 | |
3121 | t->removed = 0; | ||
3137 | 3122 | ||
3138 | if (kernel_thread((void *)pktgen_thread_worker, (void *)t, | 3123 | if (kernel_thread((void *)pktgen_thread_worker, (void *)t, |
3139 | CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0) | 3124 | CLONE_FS | CLONE_FILES | CLONE_SIGHAND) < 0) |
@@ -3234,17 +3219,18 @@ static int __init pg_init(void) | |||
3234 | 3219 | ||
3235 | static void __exit pg_cleanup(void) | 3220 | static void __exit pg_cleanup(void) |
3236 | { | 3221 | { |
3222 | struct pktgen_thread *t; | ||
3223 | struct list_head *q, *n; | ||
3237 | wait_queue_head_t queue; | 3224 | wait_queue_head_t queue; |
3238 | init_waitqueue_head(&queue); | 3225 | init_waitqueue_head(&queue); |
3239 | 3226 | ||
3240 | /* Stop all interfaces & threads */ | 3227 | /* Stop all interfaces & threads */ |
3241 | 3228 | ||
3242 | while (pktgen_threads) { | 3229 | list_for_each_safe(q, n, &pktgen_threads) { |
3243 | struct pktgen_thread *t = pktgen_threads; | 3230 | t = list_entry(q, struct pktgen_thread, th_list); |
3244 | pktgen_threads->control |= (T_TERMINATE); | 3231 | t->control |= (T_TERMINATE); |
3245 | 3232 | ||
3246 | wait_event_interruptible_timeout(queue, (t != pktgen_threads), | 3233 | wait_event_interruptible_timeout(queue, (t->removed == 1), HZ); |
3247 | HZ); | ||
3248 | } | 3234 | } |
3249 | 3235 | ||
3250 | /* Un-register us from receiving netdevice events */ | 3236 | /* Un-register us from receiving netdevice events */ |