The tasklet mechanism is a sort of wrapper around the softirq framework; in fact, tasklet handlers are executed by softirqs. Unlike softirqs, tasklets are not reentrant, which guarantees that the same tasklet handler can never run concurrently. This helps minimize overall latencies, provided programmers examine and impose relevant checks to ensure that work done in a tasklet is non-blocking and atomic. Another difference is with respect to their usage: unlike softirqs (which are restricted), any kernel code can use tasklets, and this includes dynamically linked services.
Each tasklet is represented through an instance of type struct tasklet_struct declared in kernel header <linux/interrupt.h>:
struct tasklet_struct { struct tasklet_struct ...