亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 17758 | 回復(fù): 9
打印 上一主題 下一主題

測試test_bit(int a, long *b)宏的返回值 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2011-03-17 18:05 |只看該作者 |倒序瀏覽
最近在看2.4內(nèi)核網(wǎng)絡(luò)協(xié)議棧的代碼時發(fā)現(xiàn)很多地方會根據(jù)test_bit()宏的返回值的不同來進行不同的操作,形如:
return test_bit(IPS_CONFIRMED_BIT, &ct->status);
為了搞清楚這個函數(shù)到底在什么情況下會返回0,寫了個簡單的測試程序,
測試后發(fā)現(xiàn)如果被測試位的值為0,就返回0;如果被測試位的值為1,就返回非0;不知道我的測試結(jié)果對不對?

論壇徽章:
22
丑牛
日期:2014-08-15 14:32:0015-16賽季CBA聯(lián)賽之同曦
日期:2017-12-14 15:28:14黑曼巴
日期:2017-08-10 08:14:342017金雞報曉
日期:2017-02-08 10:39:42黑曼巴
日期:2016-11-15 15:48:38CU十四周年紀(jì)念徽章
日期:2016-11-09 13:19:1015-16賽季CBA聯(lián)賽之同曦
日期:2016-04-08 18:00:03平安夜徽章
日期:2015-12-26 00:06:30程序設(shè)計版塊每日發(fā)帖之星
日期:2015-12-03 06:20:002015七夕節(jié)徽章
日期:2015-08-21 11:06:17IT運維版塊每日發(fā)帖之星
日期:2015-08-09 06:20:002015亞冠之吉達阿赫利
日期:2015-07-03 08:39:42
2 [報告]
發(fā)表于 2011-03-21 10:15 |只看該作者
你去看看代碼實現(xiàn)也行
不過你都親手測試了還不相信啊。

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
3 [報告]
發(fā)表于 2011-03-21 11:11 |只看該作者
最近在看2.4內(nèi)核網(wǎng)絡(luò)協(xié)議棧的代碼時發(fā)現(xiàn)很多地方會根據(jù)test_bit()宏的返回值的不同來進行不同的操作,形如 ...
Anzyfly 發(fā)表于 2011-03-17 18:05
沒有具體看代碼的定義,但是函數(shù)的說明當(dāng)中,你是對的。
  1. 285 /**
  2. 286  * test_bit - Determine whether a bit is set
  3. 287  * @nr: bit number to test
  4. 288  * @addr: Address to start counting from
  5. 289  */
復(fù)制代碼

論壇徽章:
0
4 [報告]
發(fā)表于 2011-03-21 11:23 |只看該作者
最近在看2.4內(nèi)核網(wǎng)絡(luò)協(xié)議棧的代碼時發(fā)現(xiàn)很多地方會根據(jù)test_bit()宏的返回值的不同來進行不同的操作,形如 ...
Anzyfly 發(fā)表于 2011-03-17 18:05



    看字面含義。。。

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
5 [報告]
發(fā)表于 2011-03-21 13:31 |只看該作者
最近在看2.4內(nèi)核網(wǎng)絡(luò)協(xié)議棧的代碼時發(fā)現(xiàn)很多地方會根據(jù)test_bit()宏的返回值的不同來進行不同的操作,形如 ...
Anzyfly 發(fā)表于 2011-03-17 18:05
忍不住,又看了一下內(nèi)核代碼。順便分析了一下,希望對你更底層的了解有用。
  1. #if 0 /* Fool kernel-doc since it doesn't do macros yet */
  2. /**
  3. * test_bit - Determine whether a bit is set
  4. * @nr: bit number to test
  5. * @addr: Address to start counting from
  6. */
  7. static int test_bit(int nr, const volatile void * addr);
  8. #endif

  9. static __always_inline int constant_test_bit(int nr, const volatile unsigned long *addr)
  10. {
  11.         return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0;
  12. }
復(fù)制代碼
對于編譯時的常數(shù)使用上面的函數(shù)進行判斷
假設(shè)我們要測試的數(shù)為test = 0x00000008,它的第三位是否為1(位數(shù)是從0數(shù)起),即nr = 3 = 0x00000003,addr就是我們測試的數(shù)的地址
addr = &test; 對于運算addr[nr >> 5] = addr[0] 也就是test的值
對于前面部分 1UL左移3位,其值就是0x00000008,它們&運算后,結(jié)果是0x00000008 != 0,所以return的結(jié)果返回是1
即0x00000008的第3位是1,其結(jié)果也確實是1。其他的情況照樣子可以這樣子驗證。
  1. static inline int variable_test_bit(int nr, const volatile unsigned long * addr)
  2. {
  3.         int oldbit;

  4.         __asm__ __volatile__(
  5.                 "btl %2,%1\n\tsbbl %0,%0"
  6.                 :"=r" (oldbit)
  7.                 :"m" (ADDR),"Ir" (nr));
  8.         return oldbit;
  9. }
復(fù)制代碼
對于編譯時的非常數(shù),使用上面的函數(shù)進行判斷。上面使用了gcc的內(nèi)聯(lián)匯編。參數(shù)nr和addr的含義和上面相同,其實就兩句,翻譯成Intel格式如下:
BT                 nr, (addr)        ;測試(addr)的第nr位,如果是1,則CF = 1
SUBB        oldbit, oldbit    ;帶進位的減法,因為上面置CF = 1,所以結(jié)果是1
然后函數(shù)最后返回oldbit的值,也就是1了。
上面的匯編語言可以參看Intel Architecture Software Developer’s Manual
  1. #define test_bit(nr,addr) \
  2. (__builtin_constant_p(nr) ? \
  3. constant_test_bit((nr),(addr)) : \
  4. variable_test_bit((nr),(addr)))
復(fù)制代碼
最后,test_bit其實是一個宏,看nr的屬性(是否是編譯時常數(shù)調(diào)用不同的函數(shù)),gcc的內(nèi)建函數(shù)__builtin_constant_p(nr),測試nr是否是編譯時的常量,如果是則返回1,然后調(diào)用constant_test_bit函數(shù),否則調(diào)用variable_test_bit函數(shù)。下面是引用gcc手冊的關(guān)于__builtin_constant_p(EXP)內(nèi)建函數(shù)的說明。詳細(xì)內(nèi)容可以參看gcc的info文檔。
     You can use the built-in function `__builtin_constant_p' to
     determine if a value is known to be constant at compile-time and
     hence that GCC can perform constant-folding on expressions
     involving that value.  The argument of the function is the value
     to test.  The function returns the integer 1 if the argument is
     known to be a compile-time constant and 0 if it is not known to be
     a compile-time constant.  A return of 0 does not indicate that the
     value is _not_ a constant, but merely that GCC cannot prove it is
     a constant with the specified value of the `-O' option.

論壇徽章:
0
6 [報告]
發(fā)表于 2011-03-21 21:32 |只看該作者
return ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0; 這個語句的意思你是怎么分析出來的?
能否再幫我指點一下,我搞不清楚((1UL << (nr & 31)) 和(addr[nr >> 5]))到底表達了一個什么
意思,沒有真正看懂它的實現(xiàn)過程。

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
7 [報告]
發(fā)表于 2011-03-21 22:53 |只看該作者
return ((1UL > 5])) != 0; 這個語句的意思你是怎么分析出來的?
能否再幫我指點一下,我搞不清楚((1UL >  ...
Anzyfly 發(fā)表于 2011-03-21 21:32



    ((1UL << (nr & 31)) & (addr[nr >> 5])) != 0

對于0~31之間的數(shù)字,nr & 31就是nr,然后 1UL << nr把第nr位置位,其它為零。

后面那個就是數(shù)組和指針的混用了。對于0~31的數(shù)字,nr >> 5總是為0的,也就是數(shù)組的第一個元素,對應(yīng)就是指針指向的元素,(addr)。

論壇徽章:
0
8 [報告]
發(fā)表于 2011-03-22 10:04 |只看該作者
在/asm-i386/bitops.h中的定義如下:
#if 0 /* Fool kernel-doc since it doesn't do macros yet */
/**
* test_bit - Determine whether a bit is set
* @nr: bit number to test
* @addr: Address to start counting from
*/
static int test_bit(int nr, const volatile void * addr);
#endif

static __inline__ int constant_test_bit(int nr, const volatile void * addr)
{
        return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
}

在.../asm-generic/bitops.h中的定義如下:
extern __inline__ int test_bit(int nr, long * addr)
{
        int        mask;

        addr += nr >> 5;
        mask = 1 << (nr & 0x1f);
        return ((mask & *addr) != 0);
}

這兩定義其實都是正如你分析的那樣,都是可以釋的通的,現(xiàn)在我終于知道這個測試置位函數(shù)的實現(xiàn)過程了,
只是感概內(nèi)核中的函數(shù)為什么都要這么寫?簡單的一個函數(shù)式 return ((1<<nr) & addr[0])就可以表達的很清楚的過程,總是搞的這么復(fù)雜,是為了可移植性?還是非要把人整暈?還是我考慮的太簡單了?

論壇徽章:
1
2015年辭舊歲徽章
日期:2015-03-03 16:54:15
9 [報告]
發(fā)表于 2011-03-22 19:01 |只看該作者
在/asm-i386/bitops.h中的定義如下:
#if 0 /* Fool kernel-doc since it doesn't do macros yet */
/**
...
Anzyfly 發(fā)表于 2011-03-22 10:04
你說的那個可能考慮了所要測試的對象是結(jié)構(gòu)或者數(shù)組的原因吧。

論壇徽章:
0
10 [報告]
發(fā)表于 2012-09-11 09:33 |只看該作者
因為__alloc_bootmem_core函數(shù)中test_bit (j, bdata->node_bootmem_map)傳遞過去以后,nr=j,addr=bdata->node_bootmem_map,其中nr=j是要開始查找的頁框號,位圖保存在bdata->node_bootmem_map指向的地方,并且是32位的unsigned long型,因此 addr)[nr >> 5])也即是 addr)[nr/32]),是為了將查找地址移動到要查找的頁位圖大致位置(第幾個unsigned long型的數(shù)開始)。(nr & 31)即是(nr %31)即是算出在某一個unsigned long內(nèi)的要開始查找的精確位置,然后將1UL左移(nr & 31)即是要在一個unsigned long中要查找的精確位置。
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP