TIL/2025

멀티코어 환경 section offset 기반 복사 & 재매핑 패턴

고무 오리 2025. 4. 24. 09:44
728x90
📢 멀티코어 시스템에서 core마다 독립적인 복사본이 필요한 데이터가 있어요. 이를 어떻게 제어하는지 확인해봐요.

 

멀티코어 시스템에서 어떤 설정 값이나 상태값들의 포맷을 .abc라는 ROM 섹션에 정의 후, 실행 중에는 각 core 별 데이터를 RAM에 복사해서 전역적으로 사용하는 경우가 많아요.

  • 그럴 때 "섹션 오프셋 기반 복사 & 재매핑 패턴"을 사용해요

 

✍️ 전역 데이터 정의 (ROM, .abc 섹션)

링커가 이 변수들을 .abc 섹션에 정렬해서 묶어 줍니다.

namespace SharedDefaults {
__attribute__((__section__(".abc"))) __attribute__((__used__))
bool FIELD_1 = true;

__attribute__((__section__(".abc"))) __attribute__((__used__))
bool FIELD_2 = false;

__attribute__((__section__(".abc"))) __attribute__((__used__))
int FIELD_3 = 42;
}

 

 

🛠️ 코드 구성

1. 글로벌 심볼 정의

__abc_start__, __abc_end__ → ROM 기준 주소

extern "C" {
  extern char __abc_start__;
  extern char __abc_end__;
}

 

 

2. 전역 테이블 선언 (core 개수만큼)

constexpr int kCoreCount = 4;
unsigned long OFFSET_TABLE[kCoreCount];

 

 

3. 초기화 함수: 각 core에서 실행

OFFSET_TABLE[core_id] = 복사된 RAM 주소 - ROM 기준 주소

void init_abc_section_for_core(int core_id) {
    auto s = reinterpret_cast<std::uintptr_t>(&__abc_start__);
    auto e = reinterpret_cast<std::uintptr_t>(&__abc_end__);
    auto size = e - s;

    void* st = xzalloc(size);               // RAM에 복사
    memcpy(st, reinterpret_cast<void*>(s), size); // Initialization, 필요 없으면 생략 가능

    OFFSET_TABLE[core_id] = reinterpret_cast<unsigned long>(st) - s;
}

 

 

4. 값 접근 함수 (core에 따라 다름)

base 인자로 들어오는 변수들이 .abc section 메모리 영역에 선언된 변수들이기 때문에 OFFSET_TABLE[core_id] 내 -s를 상쇄 시켜요

template <typename T>
T& get_field(T* base, int core_id) {
    auto addr = reinterpret_cast<unsigned long>(base) + OFFSET_TABLE[core_id];
    return *reinterpret_cast<T*>(addr);
}

 

 

사용 예시

int core_id = get_current_core_id(); // 예: MPIDR에서 추출
init_abc_section_for_core(core_id);

bool& field1 = get_field(&SharedDefaults::FIELD_1, core_id);
field1 = false;  // 쓰기
bool value = field1;  // 읽기

// 또는 바로 사용
get_field(&SharedDefaults::FIELD_1, 1) = true;

 

 

ASCII ART로 그려보기

📦 ROM 영역 (SharedDefaults, .abc 섹션 - 원본, 읽기 전용)
+----------------------------+
| SharedDefaults::FIELD_1    | ← &__abc_start__
| SharedDefaults::FIELD_2    |
| SharedDefaults::FIELD_3    | ← &__abc_end__
+----------------------------+
          │
          │ ROM → RAM으로 복사 (core 별)
          ▼

🧠 Core 0 실행 시 복사된 RAM (.abc 복사본)
+----------------------------+
| FIELD_1                    | ← 사용 주소 = FIELD_1 + OFFSET_TABLE[0]
| FIELD_2                    |
| FIELD_3                    |
+----------------------------+
...
🧠 Core N 실행 시 복사된 RAM (.abc 복사본)
+----------------------------+
| FIELD_1                    | ← 사용 주소 = FIELD_1 + OFFSET_TABLE[N]
| FIELD_2                    |
| FIELD_3                    |
+----------------------------+

🧮 OFFSET_TABLE
+------------------------------+
| OFFSET_TABLE[0] = RAM0 - ROM |
| OFFSET_TABLE[1] = RAM1 - ROM |
| ...                          |
| OFFSET_TABLE[N] = RAMN - ROM |
+------------------------------+

🛠️ get_field(&SharedDefaults::FIELD_X, core_id)
 → 실제 접근 주소 = 원본 주소 + OFFSET_TABLE[core_id]
 → 각 코어는 자신만의 복사본에 안전하게 접근!

 

 

정리하면,

  • ROM 내 .abc 에 선언 된 필드 변수들은 실행 중 사용되지 않는 원본 데이터이죠
  • RAM에 복사된 데이터들이 진짜 사용되는 데이터에요!
728x90