2017-03-09 1 views
0

다음 문서를 읽으십시오 : Barrier_Litmus_Tests_and_Cookbook by ARM.ARM Cortex-M4 뮤텍스 잠금. DMB 명령어

7.2 절은 뮤텍스/세마포어를 획득하는 코드를 보여줍니다.

Loop 
    LDREX R5, [R1] ; read lock 
    CMP R5, #0 ; check if 0 
    STREXEQ R5, R0, [R1] ; attempt to store new value 
    CMPEQ R5, #0 ; test if store suceeded 
    BNE Loop ; retry if not 
    DMB 

LDREX 명령은 메모리 주소에 대해 단독 액세스를 요청합니다. 프로세서에 단독 액세스 권한이있는 경우에만 STREX로 작성합니다. DMB 명령어를 사용하여 독점 쓰기가 모든 프로세서에 동기화되도록합니다.

나는 그것에 약간의 문제가 있습니다. 프로세서가 메모리 주소에 대한 독점적 인 액세스 권한을 갖고 있다고 가정합니다. STREX 명령어가 완료되면 독점 액세스가 제거됩니다. 다른 프로세서는 지금부터이 메모리에 액세스 할 수 있습니다. 그러나 DMB가 완료 될 때까지 쓰기는 여전히 프로세서의 캐시에 있습니다. 첫 번째 프로세서가 이미 잠겨 있지만 다른 프로세서가 아직 RAM에 동기화되지 않은 경우 다른 프로세서가 잠금에 대한 액세스를 시도하면 어떻게됩니까? 메모리 주소가 독점적으로 첫 번째 프로세서에 고정되어 있지는 않지만 쓰기가 완료되지 않았습니다.

누구나 설명 할 수 있습니까? 왜 작동하며 안전합니다. 나는 그것에 문제가있다.

+0

'DMB '는 메모리 계층 구조 (즉, 캐시)의 다양한 지점까지 볼 수있게하여 메모리 액세스를 정렬합니다. 캐시 일관성 메커니즘은 프로세서가 다른 캐시를 스누핑 할 수있게하는 데 필요합니다. 가설을 세운 상황이 발생할 수 있습니다. ARM 캐시는 일관성이 있습니다. 옵션이없는 추가 'DMB'는 전체 시스템 동기화를 수행 할 것이며, 그것이 의미하는 바를 모르지만 메모리에 쓸 수는 있습니다. –

+3

'DMB'는 읽기 - 수정 - 쓰기의 원 자성에 필요하지 않습니다. 'DMB'는 RMW 작업과 관련하여 * 다른 * 메모리 작업이 순서대로 이루어 지도록 보장합니다. – EOF

+0

DMB는 부하를 밀어 내고 저장하고 다른 사람이 볼 수 있도록 완료하십시오 ... "모든 관찰자가 잠금 장치를 성공적으로 수행했음을 모든 부하 또는 저장소를 관찰하기 전에 관찰하십시오." 다른 메모리 장벽을 사용하고, 쓰기 버퍼와 캐시 등을 플러시하는 것처럼. –

답변

2

나는 당신이 그것을 복잡하게 생각한다고 생각합니다. Amba/Axi 스펙 (멀티 코어 피질 -m4는 어디서 찾았습니까?)을보십시오. ldrex/strex는 다중 프로세서 칩의 프로세서에서 자원을 공유하기위한 것입니다. 그들은 오랫동안 다른 것들에 대해 부정확하게 사용되었습니다. ARM은 불행하게도이 모든 것을 올바르게 문서화하는 비정상적으로 나쁜 일을했습니다.

ldr의 독점적 인 부분은 프로세서 ID와 주소 (범위)가 테이블에 저장된다는 것입니다. strex가 발생하면 해당 주소 (범위)에 대한 processorid는 EXOKAY와 일치하는지 확인하고 OK가 아니라면 저장소를 수행하고 그렇지 않습니다. Strex는 아무 것도 지우지 않습니다. 흥미롭게도이 프로세서는 프로세서 ID를 설정하거나 테이블을 작성하는 방법에 따라 테이블 항목을 비울 수 있습니다.

나는이 글을 쓰고 나서 이것을 시도 할 수있다. 그러나 당신은 쉽게 ldrex와 strex 그리고 strex를 할 수있다. 나는 완전한 크기의 팔에 정수를 만들었고, 피질 -m4 ldrex, strex, strex, clrex, strex 그리고 어떻게되는지보십시오.

단일 프로세서 시스템에서 ldrex/strex는 ARM 로직에서 작동 할 것으로 예상되지만 칩 공급 업체는이를 지원할 필요가 없으며 간단히 OK (EXOKAY 대신)를 반환 할 수 있습니다. 확실히 L1과 아마도 L2는 당신이 칩 벤더에 들어가는 것 이상의 완강 한 논리입니다. (cortex-ms에는 l2가 있습니까?). 일반적으로 칩 공급 업체 코드를 치는 것에 대해 걱정할 필요가 없습니다. 캐시 중 하나에 남아 있기 때문에 무언가 알지도 못하면 오랫동안 실행할 수 있습니다. 예를 들어 Linux에서 두 캐시를 모두 사용하지 않도록 설정하는 것은 왕실 PITA입니다. 컴파일 옵션 인 것처럼 보이지만 실제를 파고 들여다 볼 수는 있습니다. 단 하나의 프로세서로 어떻게 다른 프로세서 ID를 얻을 수 있습니까?

멀티 프로세서 칩의 경우 칩 독점 공급 업체가 독점적 인 액세스로도 액세스 할 수있는 경우 캐시를 넘어서 올바르게 지원해야합니다. ldrex/strex가 정상적으로 사용되는 방법, L1 캐시에 저장되고 칩 공급 업체가 제공 한 것에 노출되지는 않지만 중간에 중단되어 L2로 저장 될 가능성이있는 경우 발생할 수 있습니다. 그리고이 경우 칩에 프로세서 ID가 두 개 이상있는 것은 의미가 있습니다. 하나 이상의 프로세서가 있기 때문입니다.

코어 텍스 M4 프로세서 로컬 배타적 모니터를 구현 좋다.프로세서 내의 로컬 모니터는 실제 주소를 보유하지 않고 대신 이 이전 LDREX의 주소와 일치하도록 처리합니다. 즉, 구현 된 배타적 예약 과립은 전체 메모리가 의 주소 범위입니다.

m7 trm은 동일한 것을 말합니다.

다중 코어가 없음 어떻게 다른 ID를 생성 할 수 있습니까? 문서에서 processorid라는 용어를 사용하여 사용중인 프로세서를 나타냅니다. 대뇌 피질에 몇 개의 프로세서가 있습니까? 아마도 그것은 다른 문자열/이름을 사용하여 다른 곳에서 문서화되었지만 현재로서는 피질 m의 프로세서 ID가 어떻게 생성되고 단일 프로세서가 되는가가 여러 개 있다는 것을 알지 못합니다. 코어에 대한 액세스 권한은 확실히 알지 못합니다.

로직이 주소 별 배타적 액세스를 지원하지는 않지만 프로세서 ID를 확인하지 못했다고 말하면 공유 된 것으로 표시된 모든 strex 액세스를 마지막 ldrex 독립 프로세서의 프로세서 ID와 비교하여 확인해야합니다 그 주소의. 그들이 여기 한 무엇 LDREX 주소의 독립 통과 한 후 다음 STREX이 같은

00000001 
00000001 
00000001 
00000600 <-- ldrex 
00000000 <-- strex pass 
00000001 <-- strex fail 
00000001 
00006666 
00000000 
00000001 
00006666 
00007777 
00000800 
AABBCCDD 
00006666 
00000001 
00006666 

을 생산하는 편집은

PUT32(0x01000600,0x600); 
PUT32(0x01000700,0x700); 
PUT32(0x01000800,0x800); 
CLREX(); 
hexstring(STREX(0x20000600,0x12345678)); 
hexstring(STREX(0x20000700,0x12345678)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000600,0x6666)); 
hexstring(STREX(0x20000700,0x12345678)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000700,0x7777)); 
hexstring(STREX(0x20000800,0x12345678)); 
hexstring(GET32(0x20000600)); 
hexstring(GET32(0x20000700)); 
hexstring(GET32(0x20000800)); 
CLREX(); 
hexstring(0xAABBCCDD); 
hexstring(LDREX(0x20000600)); 
CLREX(); 
hexstring(STREX(0x20000600,0x2222)); 
hexstring(GET32(0x20000600)); 

그래서 보인다. 그래서 당신의 용어를 사용하여 strex는 "자물쇠를 지 웁니다".

그리고 ldrex와 strex 사이에 clrex를두면 strex가 실패합니다. 같은 주소를 타격하지

결과를 변경없이 하나의 LDREX을 didnt의 데이터 캐시를 켜기

hexstring(LDREX(0x20000900)); 
hexstring(STREX(0x20000900,0x2222)); 
hexstring(STREX(0x20000900,0x2222)); 

3EEDCC1B 
00000000 
00000001 

STREX 하나 나던.

테스트 기능 : 큰 형 암과는 달리

.thumb_func 
.globl LDREX 
LDREX: 
    ldrex r0,[r0] 
    bx lr 

.thumb_func 
.globl CLREX 
CLREX: 
    clrex 
    bx lr 

.thumb_func 
.globl STREX 
STREX: 
    strex r0,r1,[r0] 
    bx lr 

:

CLREX(); 
hexstring(STREX(0x20000600,0x12345678)); 
hexstring(LDREX(0x20000600)); 
hexstring(STREX(0x20000600,0x6666)); 
hexstring(LDREX(0x20000600)); 
PUT32(0x20000600,0x11); 
hexstring(STREX(0x20000600,0x6666)); 

00000001 
00000600 
00000000 
00006666 
00000000 

STREX 적어도 문서에 기반이 아닌 전용 상점을 게시 사이에있는 비 독점적 인 액세스를 살아 이전 ldrex를 망쳐야합니다 (armv7-a에서).

참고 상기 외피-M4 r0p1에 CPUID 0x410FC241 칩 설계자가 안전하게 만들기 때문에 안전 할

0

. Test_and_Set 명령어의 전체 점은 semaphone 및 mutex 명령에 대해 운영 체제에서 사용됩니다. 다중 코어/다중 프로세서 환경에서는 내장 어셈블리 명령을 제외하고는이 기능을 정확하게 구현할 수있는 다른 방법이 없습니다.