首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么这段代码在实际的BCM2837 (pi 3)上运行时挂起,而在qemu上运行良好?

为什么这段代码在实际的BCM2837 (pi 3)上运行时挂起,而在qemu上运行良好?
EN

Stack Overflow用户
提问于 2018-11-26 17:42:35
回答 1查看 141关注 0票数 0

考虑以下函数:

代码语言:javascript
复制
_atomic_raw_lock:
.global _atomic_raw_lock
.type _atomic_raw_lock, %function
1:  ldxr        x9, [x0]                //atomic load from memory pointed to by x0
    cbz         x9, 2f                  //branch if zero (unlocked)
    wfe                                 //sleep if locked
    b           1b
2:  mov         x9, #0x01               //set x9 to be LOCKED (1).
    stxr        w10, x9, [x0]
    dsb         sy
    cbz         w10, 3f                 // atomic store success?
    b           1b
3:  ret

该函数从c代码中调用,并将地址存储为x0中的64位整数作为其第一个参数。该程序在qemu中按预期运行。通过在调用此函数的这一行之前和之后设置硬件引脚,我已经确定这是问题所在。这个函数永远不会返回。x9和w10是调用者保存的(我假设c调用代码会自动保存它们)。

详细信息:在pi 3 b+上运行,使用aarch64-buildroot-linux-gnu (glibc静态链接)从toolchains.bootlin.com进行交叉链接编译,在调用此函数之前,一切都在真实硬件上运行良好。构建命令:

代码语言:javascript
复制
aarch64-linux-g++ -g -std=gnu++17 -O0 -Wall -fno-exceptions -Wextra -Wno-attributes -fno-asynchronous-unwind-tables -Wno-sign-compare -c start.S -o 
aarch64-linux-ld start.o main.o -T link.ld -o kernel8.elf -l:libc.a -l:libstdc++.a -l:libc.so -l:libgcc_s.so

ld文件:

代码语言:javascript
复制
OUTPUT_ARCH(aarch64)
ENTRY(_start)
    MEMORY
    {
        RAM (xrw)   : ORIGIN = 0x80000, LENGTH = 0x40000000
    }
SECTIONS
{
    PROVIDE(__start_prog_mem = .); /*I may want to use this in c somehow*/
    .text : /*The place where code goes*/
    { 
        KEEP(*(.text.boot)) /*Keep this even if it is not used*/
        *(.text .text.* .gnu.linkonce.t*) /*all variations of text and
        the gnu generated (for the c ability) text sections*/
    } > RAM /*These sections now belong in .text*/
    .bss : /*Uninitialized data goes here, will not load at runtime.*/
    {
        . = ALIGN(4); /*align the current location to 4 bytes*/
        __bss_start = .; /*define __bss_start to be at the current location.*/
        *(.bss .bss.* .gnu.linkonce.b.*)
        *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
        *(COMMON)
        . = ALIGN(4); /*align the current location to 4 bytes*/
        __bss_end = .; /*Define __bss_end to be at the current location.*/
    } > RAM
    .data : /*Initialized global and static data*/
    {
        . = ALIGN(4); /*align the current location to 4 bytes*/
        __data_begin = .;
        *(.data .data.* .gnu.linkonce.d*) /*Put all data sections here.*/
        *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*)
        . = ALIGN(4);
        __data_end = .;
    } > RAM
    .rodata : /*const data*/
    {
        . = ALIGN(4); /*align the current location to 4 bytes*/
        __rodata_begin = .;
        *(.rodata .rodata.* .gnu.linkonce.r*) /*All const data sections, 
        including the gnu leftovers*/
        *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*)
        . = ALIGN(4);
        __rodata_end = .;
    } > RAM
    .stack_core0 :
    {
        . = ALIGN(16); /*stack must be 16 byte aligned*/
        __stack_start_core0 = .;
        . = . + 1024;  /*el0 size*/
        __el0_stack_core0 = .; /*el0 stack*/
        . = . + 1048576; /*el1 size*/
        __el1_stack_core0 = .; /*el1 stack*/
        PROVIDE(__el1_stack_core0 = .);
        . = . + 16384; /*el2 stack size*/
        __el2_stack_core0 = .;
        . = ALIGN(16);
        __stack_end_core0 = .;
    } > RAM
    .stack_core1 :
    {
        . = ALIGN(16); /*stack must be 16 byte aligned*/
        __stack_start_core1 = .;
        . = . + 1024;  /*el0 size*/
        __el0_stack_core1 = .; /*el0 stack*/
        . = . + 1048576; /*el1 size*/
        __el1_stack_core1 = .; /*el1 stack*/
        PROVIDE(__el1_stack_core1 = .);
        . = . + 16384; /*el2 stack size*/
        __el2_stack_core1 = .;
        . = ALIGN(16);
        __stack_end_core1 = .;
    } > RAM
    .stack_core2 :
    {
        . = ALIGN(16); /*stack must be 16 byte aligned*/
        __stack_start_core2 = .;
        . = . + 1024;  /*el0 size*/
        __el0_stack_core2 = .; /*el0 stack*/
        . = . + 1048576; /*el1 size*/
        __el1_stack_core2 = .; /*el1 stack*/
        PROVIDE(__el1_stack_core2 = .);
        . = . + 16384; /*el2 stack size*/
        __el2_stack_core2 = .;
        . = ALIGN(16);
        __stack_end_core2 = .;
    } > RAM
    .stack_core3 :
    {
        . = ALIGN(16); /*stack must be 16 byte aligned*/
        __stack_start_core3 = .;
        . = . + 1024;  /*el0 size*/
        __el0_stack_core3 = .; /*el0 stack*/
        . = . + 1048576; /*el1 size*/
        __el1_stack_core3 = .; /*el1 stack*/
        PROVIDE(__el1_stack_core3 = .);
        . = . + 16384; /*el2 stack size*/
        __el2_stack_core3 = .;
        . = ALIGN(16);
        __stack_end_core3 = .;
    } > RAM
    _end = .; /*Define _end to be at the current location*/
    PROVIDE(__end_prog_mem = .); /*I may want to use this in c somehow*/
    .heap :
    {
        . = ALIGN(4);
        __heap_start = .;
    } > RAM
    /DISCARD/ : /*Any sections listed here will not be included*/
    {
        /* *(.comment*) /*Exclude any comments made by the compiler*/
        /* *(.gnu*) /*Exclude any version numbers included by the compiler*/
        /* *(.note*) /*Exclude any notes made by the compiler.*/
        /* *(.eh_frame*) /*This sections is ecluded because it contains asyncronous
        unwind tbles we dont need.*/
    } 
}

__bss_size = (__bss_end - __bss_start) >> 3; /*Define the symbol to hold the 
size of the .bss sections.  This size will be in single units of 8 bytes 
(due to shift >> 3)*/
__prog_mem_size = (__end_prog_mem - __start_prog_mem);

删除原子锁定机制(最上面的代码列表)允许程序运行,但由于非线程安全代码,输出会变得混乱。即使是一个简单的bool标志也不会工作,因为正常的读-修改-写不是多核安全的。

问题重述:为什么这在模拟器(qemu)上运行,而不是在实际硬件上运行。已确认上述_atomic_raw_lock函数列表在实际硬件上调用时挂起,但在qemu上调用时不挂起。

编辑:代码在QEMU中运行良好,这让我相信它不是死锁。我已经通过运行一个测试来确认这一点,在这个测试中,程序所做的一切都是锁定一次,然后永远旋转。在这些情况下,问题仍然存在。

EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53478330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档