void __bzero (void *s, size_t len);

/*

 将s的前len字节设为0

 思路:先对齐到4的倍数的地址上,对前面的几B直接赋。然后,每次赋个32B,剩余凑不够32B的,

 每次赋4B,剩余凑不够4B的,直接赋

*/


void __bzero (void *s, size_t len)

{

    
long int dstp = (long int) s;

    
const op_t zero = 0;

 

    
if (len >= 8)

    
{

        size_t xlen;

        
// 处理前面的几B,直到地址为4的倍数,然后可以每次4B

        
// 这样做的原因与结构体对齐的原因一样,是为提高读写数据的效率

        
// 由于len >= 8 ,OPSIZ=4,所以不必担心len==0

        
while (dstp % OPSIZ != 0)   // #define op_t unsigned long int

                                    
// #define OPSIZ (sizeof(op_t))

                                    
// IA-32下是32

        
{

            ((
byte *) dstp)[0= 0;

            dstp 
+= 1;

            len 
-= 1;

        }


 

        
// 下面是典型的循环展开以提高效率,每次32B

        
// 若每次赋一个4B,程序会由于跳转太多而打断cpu流水线,降低效率

        
// http://www.lysator.liu.se/c/duffs-device.html

        
// 关键字:Duff's Device

        xlen 
= len / (OPSIZ * 8);

        
while (xlen != 0)

        
{

            ((op_t 
*) dstp)[0= zero;

            ((op_t 
*) dstp)[1= zero;

            ((op_t 
*) dstp)[2= zero;

            ((op_t 
*) dstp)[3= zero;

            ((op_t 
*) dstp)[4= zero;

            ((op_t 
*) dstp)[5= zero;

            ((op_t 
*) dstp)[6= zero;

            ((op_t 
*) dstp)[7= zero;

            dstp 
+= 8 * OPSIZ;

            xlen 
-= 1;

        }


        len 
%= OPSIZ * 8;           // 剩余的凑不足8 op_t 的

 

        xlen 
= len / OPSIZ;

        
while (xlen != 0)           // 每次填4B

        
{

            ((op_t 
*) dstp)[0= zero;

            dstp 
+= OPSIZ;

            xlen 
-= 1;

        }


        len 
%= OPSIZ;

    }


 

    
while (len != 0)                // 剩余不够4B的,直接赋值

    
{

        ((
byte *) dstp)[0= 0;

        dstp 
+= 1;

        len 
-= 1;

    }


}