Interrupt instance-tasklet

Source: Internet
Author: User

# Include <Linux/kernel. h>
# Include <Linux/module. h>
# Include <Linux/init. h>
# Include <Linux/interrupt. h>

// Define a devid

Static int mydev= 1119;
Static int IRQ;
Static char * devname = NULL;

// Define arguments for this module

Module_param (IRQ, Int, 0644 );
Module_param (devname, CHARP, 0644 );

// Define a argument of tasklet struct

Static struct tasklet_struct mytasklet;

Static void mytasklet_handler (unsigned long data)
{
Printk ("this is tasklet handler ../N ");
}

Static irqreturn_t myirq_handler (int irq, void * Dev)
{
Static int COUNT = 0;
If (count <10)
{
Printk ("----------- % d start ------------------------/N", Count + 1 );
Printk ("the interrupt handeler is working.../N ");
Printk ("the most of interrupt work will be done by following tasklet ../N ");
Tasklet_init (& mytasklet, mytasklet_handler, 0 );
Tasklet_schedule (& mytasklet );
Printk ("the top half has been done and bottom half will be processed.../N ");
}
Count ++;
Return irq_handled;
}

Static int _ init mytasklet_init ()
{
// Request a IRQ

Printk ("My module is working.../N ");
If (request_irq (IRQ, myirq_handler, ir1__shared, devname, & IRQ )! = 0)
{
Printk ("tasklet_init: Can not request IRQ % d for % s ..", IRQ, devname );
Return-1;
}
Printk ("% s request IRQ: % d success ../N", devname, IRQ );
Return 0;
}

Static void _ exit mytasklet_exit ()
{
Printk ("My module is leaving.../N ");
Free_irq (IRQ, & IRQ );
Printk ("free the IRQ % d ../N", IRQ );
}

Module_init (mytasklet_init );
Module_exit (mytasklet_exit );
Module_license ("GPL ");

 

 

 

 

What content does this article contain?
Tasklet mechanism overview; use of tasklet mechanism; an example of the call relationship of tasklet mechanism.
Which of the following are suitable for reading this article?
Want to know linuxer; learn beginner of driver development; learn kernel module programming beginner; other super Linux NBER;
Reference books:
Linux kernel design and implementation
Linux operating system Principles and Applications



Tasklet implementation


The tasklet (small task) mechanism is the most common method for Interrupt Processing in the lower half, and its usage is also very simple. As you know earlier, an interrupt program using tasklet will first execute the interrupt processing program to quickly complete the first half of the work, then, call tasklet to complete the work in the lower half. We can see that the lower half is called by the upper half, and when the lower half is executed is the work of the kernel. Corresponding to the tasklet we are talking about at the moment, in the Interrupt Processing Program, in addition to finishing the response to the interrupt and other work, we also need to call tasklet, as shown in.

Tasklet is represented by the tasklet_struct struct. Each such struct represents a tasklet. You can see the following definitions in <Linux/interrupt. h>:

1 tasklet_struct
2 {
3     struct tasklet_struct *next;
4     unsigned long state;
5     atomic_t count;
6     void (*func)(unsigned long);
7     unsigned long data;
8 };

In this struct, the first member represents the next tasklet in the linked list. The second variable represents the tasklet status at the moment. Generally, it is tasklet_state_sched, indicating that the tasklet has been scheduled and is being run. This variable can also be tasklet_state_run, indicating that it is running, however, it is only used in the case of multi-processor. The Count member is a reference counter. The tasklet is activated only when its value is 0; otherwise, it is forbidden and cannot be executed. The following func variable is obviously a function pointer pointing to the tasklet processing function. The unique parameter of this processing function is data.



Use tasklet


Before using tasklet, you must first create a variable of the tasklet_struct type. There are usually two methods: static creation and dynamic creation. This official statement still makes us unable to understand what the two types of creation are. If the source code is not enough, you can understand it.

Two Macros in <Linux/interrupt. h>:

1 464#define DECLARE_TASKLET(name, func, data) /
2 465struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }
3 466
4 467#define DECLARE_TASKLET_DISABLED(name, func, data) /
5 468struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }

This is the two methods for creating tasklet statically. The tasklet created by the first macro is in the active state, and then suspended by the scheduling function and executed by the kernel. The tasklet created by the second macro is in the forbidden state. From the definition of two macros, we can see that the so-called static creation is to directly define a variable named tasklet_struct, assign values of parameters in the macro to each member of the name variable. Note: The difference between the two macros lies in the assignment of the name variable count member. The specific reason is described in the first part. Maybe you are confused about the initialization method such as atomic_init. After reading the definition, you will be clear at a glance:

1 // In ARCH/x86/include/ASM/Atomic. h
2 15#define ATOMIC_INIT(i)  { (i) }
3 // In Linux/types. h
4 190typedef struct {
5 191        int counter;
6 192} atomic_t;

In contrast to static creation, a tasklet is created dynamically by passing a pre-defined pointer to the tasklet_init function. The source code of this function is as follows.

1 470void tasklet_init(struct tasklet_struct *t,
2 471                  void (*func)(unsigned long), unsigned long data)
3 472{
4 473        t->next = NULL;
5 474        t->state = 0;
6 475        atomic_set(&t->count, 0);
7 476        t->func = func;
8 477        t->data = data;
9 478}

I believe that you have read the above Code, which is basically not difficult to understand. However, here we should particularly explain the atomic_set function:

1 // In ARCH/x86/include/ASM/Atomic. h
2 35static inline void atomic_set(atomic_t *v, int i)
3 36{
4 37        v->counter = i;
5 38}

In tasklet_init, & T-> count is passed to this function. That is to say, the address of the count Member of the atomic_t type is passed to the atomic_set function. In this function, the counter value is assigned to the member in the count variable. If we want to use I, it should be the following reference method: T-"count. I. Do you understand?

OK. You can create a tasklet using the above two methods. At the same time, you should note that both the above-mentioned creation methods have the func parameter. Through the source code of the above analysis, we can see that the func parameter is a function pointer that points to such a function:

1 void tasklet_handler(unsigned long data);

Like the interrupt handler in the upper part, this function needs to be implemented by ourselves.

After the creation, we also need to schedule the tasklet using the following method:

1 tasklet_schedule(&my_tasklet)

Through this function call, our tasklet will be suspended, waiting for the opportunity to be executed



Example


Here, we only analyze the call relationships between the two parts. The complete code can be viewed here.

01 //define a argument of tasklet struct
02 static struct tasklet_struct mytasklet;
03  
04 static void mytasklet_handler(unsigned long data)
05 {
06     printk("This is tasklet handler../n");
07 }
08  
09 static irqreturn_t myirq_handler(int irq,void* dev)
10 {
11     static int count=0;
12     if(count<10)
13     {
14         printk("-----------%d start--------------------------/n",count+1);
15                 printk("The interrupt handeler is working../n");
16                 printk("The most of interrupt work will be done by following tasklet../n");
17                 tasklet_init(&mytasklet,mytasklet_handler,0);
18             tasklet_schedule(&mytasklet);
19                 printk("The top half has been done and bottom half will be processed../n");
20     }
21     count++;
22         return IRQ_HANDLED;
23 }

From the code, we can see that by calling tasklet in the upper half, the interrupt program with loose time requirements is pushed back and executed.

 

 

Reference file:

 

1. http://blogold.chinaunix.net/u3/117099/showart_2344767.html

2. http://edsionte.com/techblog/archives/1547

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.