That is simply a sanity check on a guaranteed property of tasklets. You can see the properties of a tasklet listed in a comment in include/linux/interrupt.h:
Properties:
* If tasklet_schedule() is called, then tasklet is guaranteed
to be executed on some cpu at least once after this.
* If the tasklet is already scheduled, but its execution is still not
started, it will be executed only once.
* If this tasklet is already running on another CPU (or schedule is called
from tasklet itself), it is rescheduled for later.
* Tasklet is strictly serialized wrt itself, but not
wrt another tasklets. If client needs some intertask synchronization,
he makes it with spinlocks.
By definition, tasklets are guaranteed to run at least once after being scheduled. This code:
if (!atomic_read(&t->count)) {
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
&t->state))
BUG();
Is making sure that this property holds, otherwise there is a bug, and BUG() is used to stop execution and cause a runtime panic.
Here's a commented version of the above code, to make it clearer:
// If the tasklet never ran (t->count == 0)
if (!atomic_read(&t->count)) {
// And the tasklet is not scheduled for running (bit TASKLET_STATE_SCHED of t->state is 0)
if (!test_and_clear_bit(TASKLET_STATE_SCHED,
&t->state))
// There's something wrong, this should never happen!
BUG();
In other words, you cannot have a tasklet around with t->count == 0 and t->state & (1<<TASKLET_STATE_SCHED) == 0. If this happens, there's a bug.