Boost.Fiber Stack allocation


Stack allocation - 스택 할당

파이버(fiber)는 레지스터 세트와 스택을 관리하는 '__econtext__'를 내부적으로 사용합니다.   스택에 사용되는 메모리는 스택 할당자(stack-allocator) 개념을 모델링하는 데 필요한 'stack_allocator'를 통해 할당(allocated)/할당 취소(deallocated)됩니다.

'stack_allocator'는 fiber::fiber() 또는 fibers::async()에 전달될 수 있습니다.

stack-allocator concept - 스택 할당자 개념

'stack_allocator'는 다음 표에 표시된 스택 할당자 개념 요구 사항을 충족해야 합니다. 여기서 'a'는 'stack_allocator' 유형(type)의 개체이고 'sctx'는 'stack_context'이며 'size'는 'std::size_t'입니다.

expressionreturn typenotes
a(size)creates a stack allocator
a.allocate()stack_contextcreates a stack
a.deallocate(sctx)voiddeallocates the stack created by a.allocate()
  • Important 1: allocate() 구현에는 컨텍스트(context)를 정의되지 않은 동작으로 두는 대신 컨텍스트의 사용 가능한 스택 크기를 초과하지 않도록 보호하는 논리가 포함될 수 있습니다.
  • Important 2: allocate()에서 얻지 못한 'stack_context'를 사용하여 deallocate()를 호출하면 정의되지 않은 동작이 발생합니다.
  • Note: 스택의 메모리는 정렬할 필요가 없습니다. 정렬은 '__econtext__' 내부에서 이루어집니다.
  • Boost.Context 스택 할당도 참조하세요.
    특히 traits_type 메소드는 'boost::context::stack_traits'에 대해 설명된 것과 같습니다.

📦 Class protected_fixedsize_stack

'Boost.Fiber'는 스택 할당자 개념(stack-allocator concept)을 모델로 하는 protected_fixedsize_stack 클래스를 제공합니다. 스택 초과(exceeding)를 방지하기 위해 각 스택 끝에 가드 페이지(guard page)를 추가합니다. 가드 페이지에 액세스하면(읽기 또는 쓰기 작업) 운영 체제에서 세그멘테이션 오류(segmentation fault)/접근 위반(access violation)이 생성됩니다.
⚛ 세그멘테이션 오류(segmentation fault)/접근 위반(access violation) 설명 (chatgpt)

  • Important:
    'protected_fixedsize_stack'을 사용하면 비용이 많이 듭니다.
    이 유형의 스택으로 새 파이버를 시작하면 메모리 보호 설정에 따른 오버헤드가 발생합니다.
    일단 할당되면 이 스택은 'fixedsize_stack'만큼 효율적으로 사용할 수 있습니다.
  • Note: 추가된 가드 페이지는 실제 메모리에 매핑되지 않으며 가상 주소만 사용됩니다.

🔧 Member function allocate()

  • Preconditions:
    traits_type::minimum_size() <= size and traits_type::is_unbounded() ||
    ( size <= traits_type::maximum_size() ).
  • Effects:
    최소 size 바이트의 메모리를 할당하고 스택에 대한 포인터와 실제 크기를 'sctx'에 저장합니다.
    아키텍처(스택이 아래쪽(downwards)/위쪽(upwards)으로 증가)에 따라 저장된 주소는 스택의 최고(highest)/최저(lowest) 주소입니다.

🔧 Member function deallocate()

  • Preconditions:
    sctx.sp is valid, traits_type::minimum_size() <= sctx.size and traits_type::is_unbounded() || ( sctx.size <= traits_type::maximum_size() ).
  • Effects: 스택 공간을 할당 해제합니다.

📦 Class pooled_fixedsize_stack

'Boost.Fiber'는 스택 할당자 개념을 모델링하는 pooled_fixedsize_stack 클래스를 제공합니다. 'protected_fixedsize_stack'과 달리 각 스택 끝에 가드 페이지(guard page)를 추가하지 않습니다. 메모리는 boost::pool<>에 의해 내부적으로 관리됩니다.

🔧 Constructor - 생성자

  • Preconditions:
    traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size) and 0 < next_size.
  • Effects:
    1) 첫 번째 인수: 최소 'stack_size' 바이트의 메모리를 할당하고 스택에 대한 포인터와 실제 크기를 'sctx'에 저장합니다. 아키텍처(스택이 아래쪽/위쪽으로 증가)에 따라 저장된 주소는 스택의 최고/최저 주소입니다.
    2) 두 번째 인수: 'next_size'는 *this가 필요로한 시스템 메모리를 할당해야 할 때 처음으로 시스템에 요청할 스택 수를 결정합니다.
    3) 세 번째 인수: 'max_size'는 스택에 할당할 수 있는 메모리 양을 제어합니다. 값이 0이면 상한이 없음을 의미합니다.

🔧 Member function allocate()

  • Preconditions:
    traits_type::is_unbounded() || ( traits_type::maximum_size() >= stack_size).
  • Effects:
    최소 'stack_size' 바이트의 메모리를 할당하고 스택에 대한 포인터와 실제 크기를 'sctx'에 저장합니다.
    아키텍처(스택이 아래쪽/위쪽으로 증가)에 따라 저장된 주소는 스택의 최고/최저 주소입니다.

🔧 Member function deallocate()

  • Preconditions:
    sctx.sp is valid, traits_type::is_unbounded() || ( traits_type::maximum_size() >= sctx.size).
  • Effects: 스택 공간을 할당 해제합니다.

Note: 이 스택 할당자는 스레드로부터 안전하지 않습니다.

📦 Class fixedsize_stack

'Boost.Fiber'는 스택 할당자 개념을 모델로 하는 고정 크기_스택 클래스를 제공합니다.
'protected_fixedsize_stack'과 달리 각 스택 끝에 가드 페이지를 추가하지 않습니다.
메모리는 std::malloc() 및 std::free()에 의해 간단히 관리됩니다.

🔧 Member function allocate()

  • Preconditions:
    traits_type::minimum_size() <= size and traits_type::is_unbounded() ||
    ( traits_type::maximum_size() >= size).
  • Effects:
    최소 size 바이트의 메모리를 할당하고 스택에 대한 포인터와 실제 크기를 sctx에 저장합니다.
    아키텍처(스택이 아래쪽/위쪽으로 증가)에 따라 저장된 주소는 스택의 최고/최저 주소입니다.

🔧 Member function deallocate()

  • Preconditions:
    sctx.sp is valid, traits_type::minimum_size() <= sctx.size and traits_type::is_unbounded() ||
    ( traits_type::maximum_size() >= sctx.size).
  • Effects: 스택 공간을 할당 해제합니다.

📦 Class segmented_stack

'Boost.Fiber'는 segmented_stack 사용을 지원합니다. 즉, 스택이 필요에 따라 증가합니다. 파이버는 필요에 따라 증가되는 최소 스택 크기로 생성됩니다. 세그먼트화된_스택 클래스는 스택 할당자 개념을 모델로 합니다. 'protected_fixedsize_stack' 및 'fixedsize_stack'과 달리 요청 시 증가하는 스택을 생성합니다.

  • Note 1: 세그먼트화된 스택은 현재 gcc 버전 4.7과 clang 버전 3.4 이상에서만 지원됩니다. 'segmented_stack'을 사용하려면 Boost.Fiber를 segmented-stacks 속성으로 구축해야 합니다. 예를 들어, toolset=gcc segmented-stacks=on 및 b2/bjam 명령줄에서 BOOST_USE_SEGMENTED_STACKS 적용.
  • Note 2: 세그먼트화된 스택은 context-impl=ucontext 속성을 사용하여 callcc()에서만 사용할 수 있습니다.
  • Note 3: 라이브러리가 'segmented stacks'용으로 컴파일된 경우에는 'segmented_stack'이 사용 가능한 유일한 스택 할당자입니다.

🔧 Member function allocate()

  • Preconditions:
    traits_type::minimum_size() <= size and traits_type::is_unbounded() ||
    ( traits_type::maximum_size() >= size).
  • Effects:
    최소 size 바이트의 메모리를 할당하고 스택에 대한 포인터와 실제 크기를 'sctx'에 저장합니다.
    아키텍처(스택이 아래쪽/위쪽으로 증가)에 따라 저장된 주소는 스택의 최고/최저 주소입니다.

🔧 Member function deallocate()

  • Preconditions:
    sctx.sp is valid, traits_type::minimum_size() <= sctx.size and traits_type::is_unbounded() ||
    ( traits_type::maximum_size() >= sctx.size).
  • Effects: 스택 공간을 할당 해제합니다.

Support for valgrind

'valgrind'에서 스택을 전환하는 프로그램을 실행하면 문제가 발생합니다. 속성(b2 명령줄) valgrind=on valgrind가 메모리 영역을 오류를 억제하는 스택 공간으로 처리하도록 합니다.

Support for sanitizers

Sanitizers(GCC/Clang)는 스택 스위치로 인해 혼동됩니다. 라이브러리(및 Boost.Context도)는 속성(b2 명령줄) context-impl=ucontext 및 컴파일러 산타이저 옵션을 사용하여 컴파일해야 합니다. 사용자는 Boost 바이너리에 연결할 때 Boost.Context 헤더를 포함하기 전에 'BOOST_USE_ASAN'을 정의해야 합니다.

⚛ 원문

Email 답글이 올라오면 이메일로 알려드리겠습니다.