zoukankan      html  css  js  c++  java
  • cpu位图

    SMP处理器中要用到cpu位图,用来维护系统内CPU的状态信息,具有代表性的有:

    cpu_possible_map、cpu_online_map、cpu_present_map。

    static DECLARE_BITMAP(cpu_possible_bits, CONFIG_NR_CPUS) __read_mostly
    static DECLARE_BITMAP(cpu_online_bits, CONFIG_NR_CPUS) __read_mostly
    static DECLARE_BITMAP(cpu_present_bits, CONFIG_NR_CPUS) __read_mostly

    DECLARE_BITMAP宏定义如下

    #define DECLARE_BITMAP(name,bits) 
        unsigned long name[BITS_TO_LONGS(bits)]

    所以上面定义了三个unsigned long数组,数组大小有BITS_TO_LONGS宏确定,1~31个cpu,则为1;32~63个cpu,则为2。

    目前的多核处理器还没有超过31个的,所以这个数组大小一般为1.

    unsigned long cpu_possible_map[BITS_TO_LONGS(CONFIG_NR_CPUS)]
    unsigned long cpu_online_map[BITS_TO_LONGS(CONFIG_NR_CPUS)]
    unsigned long cpu_present_map [BITS_TO_LONGS(CONFIG_NR_CPUS)]

    内核中还是用下面的一种结构体,用来表示cpu位图,于上面的结构基本等价。

    typedef struct cpumask { DECLARE_BITMAP(bits, NR_CPUS); } cpumask_t;
    /*
    struct cpumask {
    
       unsigned long bits[BITS_TO_LONGS(NR_CPUS)] 
    
    }
    */

    并且定义了to_cpumask宏用于从bit_map数组转换到cpumask结构体。

    const struct cpumask *const cpu_possible_mask = to_cpumask(cpu_possible_bits);
    const struct cpumask *const cpu_online_mask = to_cpumask(cpu_online_bits);
    const struct cpumask *const cpu_present_mask = to_cpumask(cpu_present_bits);
    #define to_cpumask(bitmap)                        
        ((struct cpumask *)(1 ? (bitmap)                
                    : (void *)sizeof(__check_is_bitmap(bitmap))))
    
    static inline int __check_is_bitmap(const unsigned long *bitmap)
    {
        return 1;
    }

    内核中bitmap的设置与清除

    static inline void set_bit(int nr, volatile unsigned long *addr)
    {
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
        unsigned long flags;
    
        _atomic_spin_lock_irqsave(p, flags);
        *p  |= mask;
        _atomic_spin_unlock_irqrestore(p, flags);
    }
    
    
    static inline void clear_bit(int nr, volatile unsigned long *addr)
    {
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
        unsigned long flags;
    
        _atomic_spin_lock_irqsave(p, flags);
        *p &= ~mask;
        _atomic_spin_unlock_irqrestore(p, flags);
    }
    
    static inline void change_bit(int nr, volatile unsigned long *addr)
    {
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
        unsigned long flags;
    
        _atomic_spin_lock_irqsave(p, flags);
        *p ^= mask;
        _atomic_spin_unlock_irqrestore(p, flags);
    }
    
    static inline int test_and_set_bit(int nr, volatile unsigned long *addr)
    {
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
        unsigned long old;
        unsigned long flags;
    
        _atomic_spin_lock_irqsave(p, flags);
        old = *p;
        *p = old | mask;
        _atomic_spin_unlock_irqrestore(p, flags);
    
        return (old & mask) != 0;
    }
    
    static inline int test_and_clear_bit(int nr, volatile unsigned long *addr)
    {
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
        unsigned long old;
        unsigned long flags;
    
        _atomic_spin_lock_irqsave(p, flags);
        old = *p;
        *p = old & ~mask;
        _atomic_spin_unlock_irqrestore(p, flags);
    
        return (old & mask) != 0;
    }
    
    static inline int test_and_change_bit(int nr, volatile unsigned long *addr)
    {
        unsigned long mask = BIT_MASK(nr);
        unsigned long *p = ((unsigned long *)addr) + BIT_WORD(nr);
        unsigned long old;
        unsigned long flags;
    
        _atomic_spin_lock_irqsave(p, flags);
        old = *p;
        *p = old ^ mask;
        _atomic_spin_unlock_irqrestore(p, flags);
    
        return (old & mask) != 0;
    }

    最后几个bitmap中常用的宏

    #define BIT(nr)            (1UL << (nr))
    #define BIT_MASK(nr)        (1UL << ((nr) % BITS_PER_LONG))
    #define BIT_WORD(nr)        ((nr) / BITS_PER_LONG)
    #define BITS_PER_BYTE        8
    #define BITS_TO_LONGS(nr)    DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long))

     把位图中所有bit设置为1

    static inline void bitmap_fill(unsigned long *dst, int nbits)
    {
        size_t nlongs = BITS_TO_LONGS(nbits);
        if (!small_const_nbits(nbits)) {
            int len = (nlongs - 1) * sizeof(unsigned long);
            memset(dst, 0xff,  len);
        }
        dst[nlongs - 1] = BITMAP_LAST_WORD_MASK(nbits);
    }

    上面用到两个宏,先判断nbis是否超过32,即表示位图的数组元素是否多余1个

    #define small_const_nbits(nbits) 
        (__builtin_constant_p(nbits) && (nbits) <= BITS_PER_LONG)

    最后一个32位可能没有全用到,下面的后过滤出使用到的bit

    #define BITMAP_LAST_WORD_MASK(nbits)                    
    (                                    
        ((nbits) % BITS_PER_LONG) ?                    
            (1UL<<((nbits) % BITS_PER_LONG))-1 : ~0UL        
    )

     遍历多cpu

    #define for_each_possible_cpu(cpu) for_each_cpu((cpu), cpu_possible_mask)

    展开为

    /**
     * for_each_cpu - iterate over every cpu in a mask
     * @cpu: the (optionally unsigned) integer iterator
     * @mask: the cpumask pointer
     *
     * After the loop, cpu is >= nr_cpu_ids.
     */
    #define for_each_cpu(cpu, mask)                
        for ((cpu) = -1;                
            (cpu) = cpumask_next((cpu), (mask)),    
            (cpu) < nr_cpu_ids;)
    /**
     * cpumask_next - get the next cpu in a cpumask
     * @n: the cpu prior to the place to search (ie. return will be > @n)
     * @srcp: the cpumask pointer
     *
     * Returns >= nr_cpu_ids if no further cpus set.
     */
    static inline unsigned int cpumask_next(int n, const struct cpumask *srcp)
    {
        /* -1 is a legal arg here. */
        if (n != -1)
            cpumask_check(n);
        return find_next_bit(cpumask_bits(srcp), nr_cpumask_bits, n+1);
    }
  • 相关阅读:
    mysql 语句的查询过程解析
    postman 百度网盘下载 64位
    java 读取文内容(text,html)
    java把Word文件转成html的字符串返回出去
    spring boot 2.X上传文件限制大小
    nginx 做反向代理
    Linux下安装Redis
    微信小程序云开发个人博客项目实战(2)---引入-Vant-Weapp-小程序-UI-组件库
    微信小程序云开发个人博客项目实战(1)- 准备工作及引入 Vant Weapp 小程序 UI 组件库
    Video 视频播放防作弊和禁止下载
  • 原文地址:https://www.cnblogs.com/yangjiguang/p/8120340.html
Copyright © 2011-2022 走看看