Monitor是4字节对齐,还是8字节对齐?

时间:2022-07-07 17:05:03
/dalvik/vm/Sync.cpp中有这样的代码:
/*
 * Monitors provide:
 *  - mutually exclusive access to resources
 *  - a way for multiple threads to wait for notification
 *
 * In effect, they fill the role of both mutexes and condition variables.
 *
 * Only one thread can own the monitor at any time.  There may be several
 * threads waiting on it (the wait call unlocks it).  One or more waiting
 * threads may be getting interrupted or notified at any given time.
 *
 * TODO: the various members of monitor are not SMP-safe.
 */
struct Monitor {
    Thread*     owner;          /* which thread currently owns the lock? */
    int         lockCount;      /* owner's recursive lock depth */
    Object*     obj;            /* what object are we part of [debug only] */

    Thread*     waitSet; /* threads currently waiting on this monitor */

    pthread_mutex_t lock;

    Monitor*    next;

    /*
     * Who last acquired this monitor, when lock sampling is enabled.
     * Even when enabled, ownerMethod may be NULL.
     */
    const Method* ownerMethod;
    u4 ownerPc;
};


/*
 * Create and initialize a monitor.
 */
Monitor* dvmCreateMonitor(Object* obj)
{
    Monitor* mon;

    mon = (Monitor*) calloc(1, sizeof(Monitor));
    if (mon == NULL) {
        ALOGE("Unable to allocate monitor");
        dvmAbort();
    }
    if (((u4)mon & 7) != 0) {//从这里来看,Monitor应该是8字节对齐的
        ALOGE("Misaligned monitor: %p", mon);
        dvmAbort();
    }
    mon->obj = obj;
    dvmInitMutex(&mon->lock);

    /* replace the head of the list with the new monitor */
    do {
        mon->next = gDvm.monitorList;
    } while (android_atomic_release_cas((int32_t)mon->next, (int32_t)mon,
            (int32_t*)(void*)&gDvm.monitorList) != 0);

    return mon;
}


    但是,我怎么算,都觉得Monitor是4字节对齐的:所有指针的长度都是4字节,int和u4也是4字节对齐,pthread_mutex_t还是个4字节对齐的结构体:
/*
 * Types
 */
typedef struct
{
    int volatile value;
} pthread_mutex_t;

哪位对C++比较熟悉的兄弟给指点下,常年用java的人伤不起。


8 个解决方案

#1


結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

#2


引用 1 楼 iltgcl 的回复:
結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

    结构体8字节对齐是arm平台的特色么? 之前看到的资料基本都是X86的,没有提到这个规则。


#3


引用 2 楼 a220315410 的回复:
Quote: 引用 1 楼 iltgcl 的回复:

結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

    结构体8字节对齐是arm平台的特色么? 之前看到的资料基本都是X86的,没有提到这个规则。



應該是編譯器的規則,可以用#progma修改,

#4


引用 3 楼 iltgcl 的回复:
Quote: 引用 2 楼 a220315410 的回复:

Quote: 引用 1 楼 iltgcl 的回复:

結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

    结构体8字节对齐是arm平台的特色么? 之前看到的资料基本都是X86的,没有提到这个规则。



應該是編譯器的規則,可以用#progma修改,


    你是想说#pragma pack( [ show ] | [ push | pop ] [, identifier ] , n ) 指令吧?

    我看资料的时候,很多资料有提到可以使用这个指令修改编译器默认的内存对齐值。
但是根据如下原则:
结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
    如果Monitor中的所有数据成员的长度都是4字节,那么Monitor应该是4字节对齐啊?
    

#5


仔细考虑一下,应该是这样的:
结构体对齐和该结构体所在的内存地址是两回事。结构体对齐如你上面所说,但是内存管理器将结构体分配到哪个地址是跟内存管理有关的,
if (((u4)mon & 7) != 0) 只是说明该结构体的首地址必须是8字节对齐的地址上,该结构体实际占用多少字节是按上面你所说的对齐规则来计算。

#6


引用 5 楼 iltgcl 的回复:
仔细考虑一下,应该是这样的:
结构体对齐和该结构体所在的内存地址是两回事。结构体对齐如你上面所说,但是内存管理器将结构体分配到哪个地址是跟内存管理有关的,
if (((u4)mon & 7) != 0) 只是说明该结构体的首地址必须是8字节对齐的地址上,该结构体实际占用多少字节是按上面你所说的对齐规则来计算。

   这个听起来挺有道理。但是,又有些说不通:
1. 如果Monitor是4字节对齐的,那么编译器是通过什么方式来保证Monitor的首地址是放在8字节对齐的地址上?
2. 假如我申请一个Monitor数组,长度为2,假设Monitor的长度为36(不是8的整数倍)字节,那么根据数组的地址连续分配的原则,第2个Monitor就应该无法放在首地址为8字节对齐的地址上了?

#7


1 內存管理器在你申請內存的時候,會將結構體的首地址放在8字節的地址上,注意是首地址。比如dalvik用的開源的內存管理器,有興趣可以去看看
2 該數組也的首地址分配在8字節對齊的地址處,而數組中的元素只需要對齊,不一頂要求其首地址8字節對齊。
你可以寫個簡單的程序測試一下就知道了

#8


引用 7 楼 iltgcl 的回复:
1 內存管理器在你申請內存的時候,會將結構體的首地址放在8字節的地址上,注意是首地址。比如dalvik用的開源的內存管理器,有興趣可以去看看
2 該數組也的首地址分配在8字節對齊的地址處,而數組中的元素只需要對齊,不一頂要求其首地址8字節對齊。
你可以寫個簡單的程序測試一下就知道了

    Thanks, 我试试~

#1


結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

#2


引用 1 楼 iltgcl 的回复:
結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

    结构体8字节对齐是arm平台的特色么? 之前看到的资料基本都是X86的,没有提到这个规则。


#3


引用 2 楼 a220315410 的回复:
Quote: 引用 1 楼 iltgcl 的回复:

結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

    结构体8字节对齐是arm平台的特色么? 之前看到的资料基本都是X86的,没有提到这个规则。



應該是編譯器的規則,可以用#progma修改,

#4


引用 3 楼 iltgcl 的回复:
Quote: 引用 2 楼 a220315410 的回复:

Quote: 引用 1 楼 iltgcl 的回复:

結構體是8個字節對齊的,我覺得是只要支持浮點數的就應該8字節對齊,其它小的單片機由於不支持浮點數可能就是4字節對齊了

    结构体8字节对齐是arm平台的特色么? 之前看到的资料基本都是X86的,没有提到这个规则。



應該是編譯器的規則,可以用#progma修改,


    你是想说#pragma pack( [ show ] | [ push | pop ] [, identifier ] , n ) 指令吧?

    我看资料的时候,很多资料有提到可以使用这个指令修改编译器默认的内存对齐值。
但是根据如下原则:
结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。
    如果Monitor中的所有数据成员的长度都是4字节,那么Monitor应该是4字节对齐啊?
    

#5


仔细考虑一下,应该是这样的:
结构体对齐和该结构体所在的内存地址是两回事。结构体对齐如你上面所说,但是内存管理器将结构体分配到哪个地址是跟内存管理有关的,
if (((u4)mon & 7) != 0) 只是说明该结构体的首地址必须是8字节对齐的地址上,该结构体实际占用多少字节是按上面你所说的对齐规则来计算。

#6


引用 5 楼 iltgcl 的回复:
仔细考虑一下,应该是这样的:
结构体对齐和该结构体所在的内存地址是两回事。结构体对齐如你上面所说,但是内存管理器将结构体分配到哪个地址是跟内存管理有关的,
if (((u4)mon & 7) != 0) 只是说明该结构体的首地址必须是8字节对齐的地址上,该结构体实际占用多少字节是按上面你所说的对齐规则来计算。

   这个听起来挺有道理。但是,又有些说不通:
1. 如果Monitor是4字节对齐的,那么编译器是通过什么方式来保证Monitor的首地址是放在8字节对齐的地址上?
2. 假如我申请一个Monitor数组,长度为2,假设Monitor的长度为36(不是8的整数倍)字节,那么根据数组的地址连续分配的原则,第2个Monitor就应该无法放在首地址为8字节对齐的地址上了?

#7


1 內存管理器在你申請內存的時候,會將結構體的首地址放在8字節的地址上,注意是首地址。比如dalvik用的開源的內存管理器,有興趣可以去看看
2 該數組也的首地址分配在8字節對齊的地址處,而數組中的元素只需要對齊,不一頂要求其首地址8字節對齊。
你可以寫個簡單的程序測試一下就知道了

#8


引用 7 楼 iltgcl 的回复:
1 內存管理器在你申請內存的時候,會將結構體的首地址放在8字節的地址上,注意是首地址。比如dalvik用的開源的內存管理器,有興趣可以去看看
2 該數組也的首地址分配在8字節對齊的地址處,而數組中的元素只需要對齊,不一頂要求其首地址8字節對齊。
你可以寫個簡單的程序測試一下就知道了

    Thanks, 我试试~