Linux Kernel latency

Source: Internet
Author: User
 
 

1. # include <Linux/time. h>

Void do_gettimeofday (struct timeval * TV)
{
Unsigned long flags;
Unsigned long USEC, SEC;

Read_lock_irqsave (& xtime_lock, flags );
SEC = xtime. TV _sec;
USEC = xtime. TV _usec + do_gettimeoffset ();
Read_unlock_irqrestore (& xtime_lock, flags );

While (USEC >=1000000 ){
USEC-= 1000000;
SEC ++;
}

TV-> TV _sec = sec;
TV-> TV _usec = USEC;
}

Void mydelay (unsigned long delay)
{
Struct timeval TV;
Do_gettimeofday (& TV)
Unsigned long start = TV. TV _usec; // unsigned long start = TV. TV _sec;
While (TV. TV _usec-start <delay)
Do_gettimeofday (& TV)
}

2. If the driver uses a waiting queue to wait for an event, and you want to make sure that the driver
Extern inline longSleep_on_timeout(Wait_queue_head_t * q, signed long timeout)
{
Signed long early = 0;

Current-> timeout = jiffies + timeout;
Sleep_on (Q );
If (current-> timeout> 0 ){
Early = Current-> timeout-jiffies;
Current-> timeout = 0;
}
Return early;
}

Extern inline longInterruptible_sleep_on_timeout(Wait_queue_head_t * Q,
Signed long timeout)
{
Signed long early = 0;

Current-> timeout = jiffies + timeout;
Interruptible_sleep_on (Q );
If (current-> timeout> 0 ){
Early = Current-> timeout-jiffies;
Current-> timeout = 0;
}
Return early;
}

3. If you do not need to wait for other events, you can directly wait for a delay.
Extern inline voidSchedule_timeout(INT timeout)
{
Current-> timeout = jiffies + timeout;
Current-> state = task_interruptible;
Schedule ();
Current-> timeout = 0;
}
Set_current_state (task_interruptible );
Schedule_timeout (jit_delay * Hz );

4
We recommend a maximum of 1000us for short latency and hardware synchronization.

# Include <Linux/delay. h>

Void _ delay (INT loops)
{
Long long dummy;
_ ASM _ volatile _ ("gettr" _ t0 ", % 1/N/t"
"_ PTA 4," _ t0 "/n/t"
"Addi % 0,-1, % 0/n/t"
"BNE % 0, r63," _ t0 "/n/t"
"Ptabs % 1," _ t0 "/n/t": "= r" (loops ),
"= R" (dummy)
: "0" (loops ));
}

Void_ Udelay(Unsigned long usecs, unsigned long lpj)
{
Usecs * = (unsigned long) Hz <32)/1000000) * lpj;
_ Delay (long) usecs> 32 );
}

# Ifdef notdef
# Define mdelay (N )(/
{Unsigned long MSEC = (n); While (MSEC --) udelay (1000 );})
# Else
# Define mdelay (N )(/
(_ Builtin_constant_p (n) & (n) <= max_udelay_ms )? Udelay (n) * 1000 ):/
({Unsigned long MSEC = (n); While (MSEC --) udelay (1000 );}))
# Endif

 

Posted on:, modified on:, viewed 1690 times, and commented on two recommendation complaints
     
     

 

   
Network

   
   
 
 
 
Defines a timer static struct timer_list scan_timer;

Int _ init ir_init_module (void) during initialization
{Init_timer (& scan_timer); initialize the timer
Scan_timer.function = pad_poll_scan; // Scan
Scan_timer.data = (unsigned long) & pad_priv;
}
Static void pad_poll_scan (unsigned long dev_id)
{
-- Add your code
Mod_timer (& scan_timer, jiffies + (scan_period); // it will add timer internal
}
 
   

   
   
 
 
 
# Include <ASM/Param. h>
# Include <Linux/Timer. h>
Void add_timer (struct timer_list * timer );
Int del_timer (struct timer_list * timer );
Inline void init_timer (struct timer_list * timer );
Struct timer_list is defined:
Struct timer_list {
Struct timer_list * next;
Struct timer_list * Prev;
Unsigned long expires;
Unsigned long data;
Void (* function) (unsigned long d );
};
Expires indicates the time when the function is to be executed. The system core has a global variable jiffies
Indicates the current time. When add_timer is called, jiffies = jiffies + num indicates that
Run the function after the minimum system interval. The minimum system interval is related to the hardware platform used,
In the core, constant Hz is defined to indicate the number of minimum time intervals in one second, and num * Hz is used to indicate num.
Seconds. The system calls the function at the scheduled time and deletes this subroutine from the scheduled queue,
Therefore, if you want to execute the function at intervals, you must call the function again.
Use add_timer. Function parameter D is the data item in timer.
Sometimes the driver needs a very short delay to synchronize with the hardware. In this case, the jiffies value cannot be used. At this time, we need to use the kernel functions udelay and mdelay. The u table shows the Greek letter "Mu" (m), which represents "micro ". Their prototype is as follows:
# Include <Linux/delay. h>
Void udelay (unsigned long usecs); // The number of microseconds specified by the software loop latency
Void mdelay (unsigned long msecs); // use udelay For Loop
This function is compiled as an inline function in most architectures. The bogomips value is used in the udelay function: its loop is based on the integer loops_per_second. This value is obtained when bogomips is calculated in the pilot phase.
The udelay function can only be used to obtain a short latency. Because the accuracy of the loops_per_second value is only 8 bits, when calculating a longer latency, a considerable error will be accumulated. Although the maximum latency allowed is nearly 1 S (because the longer latency will overflow), the maximum recommended udelay function parameter is 1000us (1 ms ). The mdelay function can be used when the latency is greater than 11 ms. Many drivers need to delay the task to be processed later, but do not want to interrupt it. Linux provides three methods for this: task queue, tasklet, and kernel timer.
Note that udelay is a busy waiting function and cannot run other tasks during the delay period. For the source code, see the header file <ASM/delay. h>.
 
At present, the kernel does not support latency greater than 1 microsecond and less than 1 clock tick, but this is not a problem because the latency is identified by hardware or people. The latency interval of 1% seconds is sufficient for humans, while that of 1 ms is long enough for hardware. If you really need the latency interval, you just need to create a loop that continuously executes the udelay (1000) function.
Sample Code of the Linux kernel latency function:
1. # include <Linux/time. h>
Void do_gettimeofday (struct timeval * TV)
{
Unsigned long flags;
Unsigned long USEC, SEC;
 read_lock_irqsave(&xtime_lock, flags);
 sec = xtime.tv_sec;
 usec = xtime.tv_usec + do_gettimeoffset();
 read_unlock_irqrestore(&xtime_lock, flags);
 while (usec >= 1000000) {
  usec -= 1000000;
  sec++;
 }
 tv->tv_sec = sec;
 tv->tv_usec = usec;
}
void MyDelay(unsigned long delay)
{
 struct timeval tv;
 do_gettimeofday(&tv)
 unsigned long start = tv.tv_usec;//unsigned long start = tv.tv_sec;
 while(tv.tv_usec - start <delay)
    do_gettimeofday(&tv)
}
2. If the driver uses a waiting queue to wait for an event, and you want to make sure that the driver
Extern inline long sleep_on_timeout (wait_queue_head_t * q, signed long timeout)
{
Signed long early = 0;

Current-> timeout = jiffies + timeout;
Sleep_on (Q );
If (current-> timeout> 0 ){
Early = Current-> timeout-jiffies;
Current-> timeout = 0;
}
Return early;
}
extern inline long interruptible_sleep_on_timeout(wait_queue_head_t *q,
                signed long timeout)
{
    signed long early = 0;
       
    current->timeout = jiffies + timeout;
    interruptible_sleep_on (q);
    if (current->timeout > 0) {
        early = current->timeout - jiffies;
        current->timeout = 0;
    }
    return early;
}
3. If you do not need to wait for other events, you can directly wait for a delay.
Extern inline void schedule_timeout (INT timeout)
{
Current-> timeout = jiffies + timeout;
Current-> state = task_interruptible;
Schedule ();
Current-> timeout = 0;
}
Set_current_state (task_interruptible );
Schedule_timeout (jit_delay * Hz );
4. We recommend a maximum of us for short latency and hardware synchronization.
# Include <Linux/delay. h>
void __delay(int loops)
{
 long long dummy;
 __asm__ __volatile__("gettr " __t0 ", %1/n/t"
        "_pta 4, " __t0 "/n/t"
        "addi %0, -1, %0/n/t"
        "bne %0, r63, " __t0 "/n/t"
        "ptabs %1, " __t0 "/n/t":"=r"(loops),
        "=r"(dummy)
        :"0"(loops));
}
void __udelay(unsigned long long usecs, unsigned long lpj)
{
 usecs *= (((unsigned long long) HZ << 32) / 1000000) * lpj;
 __delay((long long) usecs >> 32);
}
#ifdef notdef
#define mdelay(n) (/
 {unsigned long msec=(n); while (msec--) udelay(1000);})
#else
#define mdelay(n) (/
 (__builtin_constant_p(n) && (n)<=MAX_UDELAY_MS) ? udelay((n)*1000) : /
 ({unsigned long msec=(n); while (msec--) udelay(1000);}))
#endif

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.