← Documents Documentation/mm/active_mm.rst GitHub 원문 ↗

Linux 6.18.37 · Memory management

Active MM

Kernel task의 real·anonymous address space, mm·active_mm, mm_users·mm_count와 lazy TLB reference를 설명합니다.

Source pathDocumentation/mm/active_mm.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

active_mm.rst:1-95

Real process는 `mm == active_mm`이고 anonymous context는 `mm == NULL`인 채 이전 mm을 `active_mm`으로 빌립니다. `mm_users`는 real user, `mm_count`는 lazy lifetime까지 보호합니다.

Task address-space 규칙
Tasktsk->mmtsk->active_mmSchedule-out
Real address spaceReal mm같은 real mmOwn mm 유지
Anonymous/lazyNULLBorrowed mmBorrowed mm 반환·clear

Real·anonymous task에서 두 pointer와 schedule-out 동작을 비교합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 =========
2 Active MM
3 =========
4
5 Note, the mm_count refcount may no longer include the "lazy" users
6 (running tasks with ->active_mm == mm && ->mm == NULL) on kernels
7 with CONFIG_MMU_LAZY_TLB_REFCOUNT=n. Taking and releasing these lazy
8 references must be done with mmgrab_lazy_tlb() and mmdrop_lazy_tlb()
9 helpers, which abstract this config option.
10
11 ::
12
13 List: linux-kernel
14 Subject: Re: active_mm
15 From: Linus Torvalds <torvalds () transmeta ! com>
16 Date: 1999-07-30 21:36:24
17
18 Cc'd to linux-kernel, because I don't write explanations all that often,
19 and when I do I feel better about more people reading them.
20
21 On Fri, 30 Jul 1999, David Mosberger wrote:
22 >
23 > Is there a brief description someplace on how "mm" vs. "active_mm" in
24 > the task_struct are supposed to be used? (My apologies if this was
25 > discussed on the mailing lists---I just returned from vacation and
26 > wasn't able to follow linux-kernel for a while).
27
28 Basically, the new setup is:
29
30 - we have "real address spaces" and "anonymous address spaces". The
31 difference is that an anonymous address space doesn't care about the
32 user-level page tables at all, so when we do a context switch into an
33 anonymous address space we just leave the previous address space
34 active.
35
36 The obvious use for a "anonymous address space" is any thread that
37 doesn't need any user mappings - all kernel threads basically fall into
38 this category, but even "real" threads can temporarily say that for
39 some amount of time they are not going to be interested in user space,
40 and that the scheduler might as well try to avoid wasting time on
41 switching the VM state around. Currently only the old-style bdflush
42 sync does that.
43
44 - "tsk->mm" points to the "real address space". For an anonymous process,
45 tsk->mm will be NULL, for the logical reason that an anonymous process
46 really doesn't _have_ a real address space at all.
47
48 - however, we obviously need to keep track of which address space we
49 "stole" for such an anonymous user. For that, we have "tsk->active_mm",
50 which shows what the currently active address space is.
51
52 The rule is that for a process with a real address space (ie tsk->mm is
53 non-NULL) the active_mm obviously always has to be the same as the real
54 one.
55
56 For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the
57 "borrowed" mm while the anonymous process is running. When the
58 anonymous process gets scheduled away, the borrowed address space is
59 returned and cleared.
60
61 To support all that, the "struct mm_struct" now has two counters: a
62 "mm_users" counter that is how many "real address space users" there are,
63 and a "mm_count" counter that is the number of "lazy" users (ie anonymous
64 users) plus one if there are any real users.
65
66 Usually there is at least one real user, but it could be that the real
67 user exited on another CPU while a lazy user was still active, so you do
68 actually get cases where you have a address space that is _only_ used by
69 lazy users. That is often a short-lived state, because once that thread
70 gets scheduled away in favour of a real thread, the "zombie" mm gets
71 released because "mm_count" becomes zero.
72
73 Also, a new rule is that _nobody_ ever has "init_mm" as a real MM any
74 more. "init_mm" should be considered just a "lazy context when no other
75 context is available", and in fact it is mainly used just at bootup when
76 no real VM has yet been created. So code that used to check
77
78 if (current->mm == &init_mm)
79
80 should generally just do
81
82 if (!current->mm)
83
84 instead (which makes more sense anyway - the test is basically one of "do
85 we have a user context", and is generally done by the page fault handler
86 and things like that).
87
88 Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,
89 because it slightly changes the interfaces to accommodate the alpha (who
90 would have thought it, but the alpha actually ends up having one of the
91 ugliest context switch codes - unlike the other architectures where the MM
92 and register state is separate, the alpha PALcode joins the two, and you
93 need to switch both together).
94
95 (From http://marc.info/?l=linux-kernel&m=93337278602211&w=2)
96

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Lazy TLB reference

1-10

`CONFIG_MMU_LAZY_TLB_REFCOUNT=n`인 kernel에서는 `mm_count` refcount가 `active_mm == mm`이면서 `mm == NULL`인 실행 task, 즉 lazy user를 더 이상 포함하지 않을 수 있습니다.

이 lazy reference의 획득과 release에는 configuration 차이를 추상화하는 `mmgrab_lazy_tlb()`와 `mmdrop_lazy_tlb()` helper를 사용해야 합니다.

=========
Active MM
=========

Note, the mm_count refcount may no longer include the "lazy" users
(running tasks with ->active_mm == mm && ->mm == NULL) on kernels
with CONFIG_MMU_LAZY_TLB_REFCOUNT=n. Taking and releasing these lazy
references must be done with mmgrab_lazy_tlb() and mmdrop_lazy_tlb()
helpers, which abstract this config option.

1999년 설명의 배경

11-27

다음 내용은 1999-07-30 Linus Torvalds가 linux-kernel mailing list에 보낸 `Re: active_mm` 답변입니다. 설명을 자주 쓰지 않으므로 더 많은 사람이 읽도록 list에 참조했다고 밝힙니다.

David Mosberger의 질문은 `task_struct` 안의 `mm`과 `active_mm`을 어떻게 사용해야 하는지 간단한 설명이 있는지 묻습니다. 휴가에서 막 돌아와 mailing-list 논의를 따라가지 못했다는 양해도 덧붙였습니다.

::

 List:       linux-kernel
 Subject:    Re: active_mm
 From:       Linus Torvalds <torvalds () transmeta ! com>
 Date:       1999-07-30 21:36:24

 Cc'd to linux-kernel, because I don't write explanations all that often,
 and when I do I feel better about more people reading them.

 On Fri, 30 Jul 1999, David Mosberger wrote:
 >
 > Is there a brief description someplace on how "mm" vs. "active_mm" in
 > the task_struct are supposed to be used?  (My apologies if this was
 > discussed on the mailing lists---I just returned from vacation and
 > wasn't able to follow linux-kernel for a while).

Real·anonymous address space

28-42

새 구조는 real address space와 anonymous address space를 구분합니다. Anonymous address space는 user-level page table을 전혀 필요로 하지 않으므로 그 context로 switch할 때 이전 address space를 active 상태로 남겨 둡니다.

명백한 사용자는 user mapping이 필요 없는 thread, 즉 거의 모든 kernel thread입니다. Real thread도 잠시 userspace에 관심이 없다고 표시해 scheduler가 VM state switch에 시간을 낭비하지 않게 할 수 있습니다. 당시에는 old-style `bdflush` sync만 이 방식을 사용했습니다.

 Basically, the new setup is:

  - we have "real address spaces" and "anonymous address spaces". The
    difference is that an anonymous address space doesn't care about the
    user-level page tables at all, so when we do a context switch into an
    anonymous address space we just leave the previous address space
    active.

    The obvious use for a "anonymous address space" is any thread that
    doesn't need any user mappings - all kernel threads basically fall into
    this category, but even "real" threads can temporarily say that for
    some amount of time they are not going to be interested in user space,
    and that the scheduler might as well try to avoid wasting time on
    switching the VM state around. Currently only the old-style bdflush
    sync does that.

`tsk->mm`과 `tsk->active_mm`

43-60

`tsk->mm`은 real address space를 가리킵니다. Anonymous process는 실제 real address space가 없으므로 `tsk->mm`이 `NULL`입니다.

Anonymous user가 빌려 쓴 address space도 추적해야 하므로 `tsk->active_mm`이 현재 active address space를 나타냅니다.

Real address space가 있는 process, 즉 `tsk->mm != NULL`이면 `active_mm`은 항상 real `mm`과 같아야 합니다. Anonymous process는 `tsk->mm == NULL`이고 실행 중 `tsk->active_mm`이 borrowed mm을 가리킵니다. Schedule-out되면 borrowed address space를 반환하고 pointer를 clear합니다.


  - "tsk->mm" points to the "real address space". For an anonymous process,
    tsk->mm will be NULL, for the logical reason that an anonymous process
    really doesn't _have_ a real address space at all.

  - however, we obviously need to keep track of which address space we
    "stole" for such an anonymous user. For that, we have "tsk->active_mm",
    which shows what the currently active address space is.

    The rule is that for a process with a real address space (ie tsk->mm is
    non-NULL) the active_mm obviously always has to be the same as the real
    one.

    For a anonymous process, tsk->mm == NULL, and tsk->active_mm is the
    "borrowed" mm while the anonymous process is running. When the
    anonymous process gets scheduled away, the borrowed address space is
    returned and cleared.

`mm_users`와 `mm_count`

61-71

`struct mm_struct`에는 두 counter가 있습니다. `mm_users`는 real address-space user 수이고, `mm_count`는 lazy user 수에 real user가 하나라도 있을 때 1을 더한 값입니다.

보통 real user가 적어도 하나 있지만, lazy user가 active인 동안 다른 CPU에서 마지막 real user가 exit할 수 있습니다. 그러면 address space를 lazy user만 사용하는 짧은 상태가 생깁니다. 그 thread가 real thread 대신 schedule-out되면 `mm_count`가 0이 되어 이 zombie mm이 release됩니다.

 To support all that, the "struct mm_struct" now has two counters: a
 "mm_users" counter that is how many "real address space users" there are,
 and a "mm_count" counter that is the number of "lazy" users (ie anonymous
 users) plus one if there are any real users.

 Usually there is at least one real user, but it could be that the real
 user exited on another CPU while a lazy user was still active, so you do
 actually get cases where you have a address space that is _only_ used by
 lazy users. That is often a short-lived state, because once that thread
 gets scheduled away in favour of a real thread, the "zombie" mm gets
 released because "mm_count" becomes zero.

`init_mm`은 real MM이 아니다

72-86

새 규칙에서는 누구도 `init_mm`을 real MM으로 갖지 않습니다. `init_mm`은 다른 context가 없을 때의 lazy context이며, 주로 real VM이 아직 만들어지지 않은 boot 초기 단계에 사용합니다.

따라서 과거의 `if (current->mm == &init_mm)` 검사는 일반적으로 `if (!current->mm)`로 바꿔야 합니다. 이 검사는 page-fault handler 등에서 현재 user context가 있는지 묻는 것이므로 후자가 의미에도 더 맞습니다.


 Also, a new rule is that _nobody_ ever has "init_mm" as a real MM any
 more. "init_mm" should be considered just a "lazy context when no other
 context is available", and in fact it is mainly used just at bootup when
 no real VM has yet been created. So code that used to check

         if (current->mm == &init_mm)

 should generally just do

         if (!current->mm)

 instead (which makes more sense anyway - the test is basically one of "do
 we have a user context", and is generally done by the page fault handler
 and things like that).

Alpha context switch와 원문 출처

87-95

답변 시점에 Alpha를 수용하기 위해 interface를 조금 바꾼 `pre-patch-2.3.13-1`이 ftp.kernel.org에 올라갔습니다. 다른 architecture는 MM과 register state가 분리되어 있지만 Alpha PALcode는 둘을 결합해 함께 switch해야 하므로 context-switch code가 복잡했습니다.

원문 보관 URL은 `http://marc.info/?l=linux-kernel&m=93337278602211&w=2`입니다.


 Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,
 because it slightly changes the interfaces to accommodate the alpha (who
 would have thought it, but the alpha actually ends up having one of the
 ugliest context switch codes - unlike the other architectures where the MM
 and register state is separate, the alpha PALcode joins the two, and you
 need to switch both together).

 (From http://marc.info/?l=linux-kernel&m=93337278602211&w=2)