|
Line
Link Here
|
|
-- |
|
|
| 1 |
include/linux/interrupt.h | 6 ++++-- |
|
include/linux/interrupt.h | 6 ++++-- |
| 2 |
kernel/softirq.c | 13 +++++++++++++ |
1 |
kernel/softirq.c | 13 +++++++++++++ |
| 3 |
2 files changed, 17 insertions(+), 2 deletions(-) |
2 |
2 files changed, 17 insertions(+), 2 deletions(-) |
| 4 |
-- a/include/linux/interrupt.h |
3 |
++ b/include/linux/interrupt.h |
|
Lines 470-482
struct tasklet_struct
Link Here
|
| 470 |
atomic_t count; |
470 |
atomic_t count; |
| 471 |
void (*func)(unsigned long); |
471 |
void (*func)(unsigned long); |
| 472 |
unsigned long data; |
472 |
unsigned long data; |
|
|
473 |
unsigned long checkp; |
| 474 |
unsigned int usage; |
| 473 |
}; |
475 |
}; |
| 474 |
|
476 |
|
| 475 |
#define DECLARE_TASKLET(name, func, data) \ |
477 |
#define DECLARE_TASKLET(name, func, data) \ |
| 476 |
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data } |
478 |
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data, INITIAL_JIFFIES } |
| 477 |
|
479 |
|
| 478 |
#define DECLARE_TASKLET_DISABLED(name, func, data) \ |
480 |
#define DECLARE_TASKLET_DISABLED(name, func, data) \ |
| 479 |
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data } |
481 |
struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data, INITIAL_JIFFIES } |
| 480 |
|
482 |
|
| 481 |
|
483 |
|
| 482 |
enum |
484 |
enum |
| 483 |
-- a/kernel/softirq.c |
485 |
++ b/kernel/softirq.c |
|
Lines 389-394
void __tasklet_schedule(struct tasklet_s
Link Here
|
| 389 |
{ |
389 |
{ |
| 390 |
unsigned long flags; |
390 |
unsigned long flags; |
| 391 |
|
391 |
|
|
|
392 |
if (t->checkp == INITIAL_JIFFIES) |
| 393 |
t->checkp = jiffies + HZ; |
| 394 |
|
| 392 |
local_irq_save(flags); |
395 |
local_irq_save(flags); |
| 393 |
t->next = NULL; |
396 |
t->next = NULL; |
| 394 |
*__get_cpu_var(tasklet_vec).tail = t; |
397 |
*__get_cpu_var(tasklet_vec).tail = t; |
|
Lines 443-448
static void tasklet_action(struct softir
Link Here
|
| 443 |
if (!atomic_read(&t->count)) { |
446 |
if (!atomic_read(&t->count)) { |
| 444 |
if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) |
447 |
if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state)) |
| 445 |
BUG(); |
448 |
BUG(); |
|
|
449 |
t->usage++; |
| 450 |
if (time_before(t->checkp, jiffies)) { |
| 451 |
printk("%s: %ps %pf scheduled too many times: %u\n", __func__, t, t->func, t->usage); |
| 452 |
if (t->usage > 100) |
| 453 |
printk("%s: %ps %pf scheduled too many times: %u\n", __func__, t, t->func, t->usage); |
| 454 |
t->usage = 0; |
| 455 |
t->checkp = jiffies + HZ; |
| 456 |
} |
| 446 |
t->func(t->data); |
457 |
t->func(t->data); |
| 447 |
tasklet_unlock(t); |
458 |
tasklet_unlock(t); |
| 448 |
continue; |
459 |
continue; |
|
Lines 503-508
void tasklet_init(struct tasklet_struct
Link Here
|
| 503 |
atomic_set(&t->count, 0); |
514 |
atomic_set(&t->count, 0); |
| 504 |
t->func = func; |
515 |
t->func = func; |
| 505 |
t->data = data; |
516 |
t->data = data; |
|
|
517 |
t->usage = 0; |
| 518 |
t->checkp = jiffies + HZ; |
| 506 |
} |
519 |
} |
| 507 |
|
520 |
|
| 508 |
EXPORT_SYMBOL(tasklet_init); |
521 |
EXPORT_SYMBOL(tasklet_init); |