달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

 

<책 겉표지 그림 출처 : yes24>

 

책장을 정리하다가 낯설은 영어 책이 보인다. 내가 이런 책을 샀던가? 책 출판년도를 보니 2004년. 2004년 ~ 2006년 쯤에 구매한 게 아닌가 생각된다.

 

아무튼 쓰윽 읽어봤다. 영어를 가르치는 영어책이 아니라 영어 학습 방법에 대한 저자의 의견이 책 앞부분 절반 이상을 차지하고 있어서 소설책 읽듯이 쓰윽 읽었다. 책 뒤 절반은 저자가 주장하는 image making, 밝음, 상황별 문장 소개 등이 들어 있다.

 

CD 도 들어 있는데, 알파벳이나 주요 발음에 대해 native 의 발음 동영상이 들어 있고 저자가 만든 sendic 이라는 일종의 사전 프로그램이 들어 있다. 오래전 프로그램이라 최신 프로그램이 있나 webpage 를 찾아보니 이제는 PC 용이 아닌 Android App 으로 만드나 보다.

 

아무튼 책 앞에 부분에서 저자는 무작정 듣기, 문자 혹은 단어에만 집중하면 된다는 식의 방법은 문제가 있다고 지적하고 있다. 이보다 발음을 정확히 하고 기본 평서문을 잘 만드는 데 노력하라고 하고 있다. 그리고 영영 사전은 영영 사전을 볼 때 영한 사전을 쓰지 않아도 될 정도일 때 보면 좋다고 한다.

 

사실 난 고등학생 때 영영사전을 샀고 색칠하면서 봤다. 나름 한국인에 맞게 쉬운말로 되어 있다는 영영사전이었는데, 살짝 살짝씩 영한 사전을 찾아봐야했던 걸로 기억한다. 그런데 그래도 하고 싶어서 영한 사전보다는 영영 사전을 더 많이 그리고 계속 썼고 색칠해가면서 보다보니 나름 색칠한 게 많아졌던 걸로 기억한다. 저자 말대로 영한 사전이 없어도 영영사전을 볼 수 있어야 좋은데, 그런 실력이 될 때까지 영한 사전을 보고 있었으면 내가 영영 사전으로 다시 돌아올 수 있었을까 하는 생각이 든다. 어디까지나 사전 찾아서 보는 게 재밌어야 하고 재미를 기반으로 약간의 의지가 있어야 하지 않을까.

 

발음은 저자 말대로 중요한 것 같다. 미국 사람들처럼 연음하고 미국 사람들이 잘 쓰는 구문 쓰면 좋긴 한데 이건 정말 마라톤이랄까 천천히 쌓아가야 하는 거고. 학교 다닐 때 발음을 너무 제대로 못 배운 것 같다. 그냥 독해하고 객관식에서 맞는 답만 빠르게 골라내는 연습을 한 것 같다. 예전에 다른 곳에서 들은 기억으로, 발음으로 완벽히 미국사람처럼 될 수는 절대 없을 거고 그럴 필요 없다고 한다. 맞다. 그런데 너무 발음을 모르거나 무시한 발음을 하면 미국사람이 이해할 수 없다. 그리고 발음을 신경쓰면 그만큼 잘 들리는 것도 맞다고 생각한다.

 

그런 의미에서 요즘은 정말 Youtube 가 교육에도 너무 좋다.

내가 구독하고 있는 채널 중 하나에서 발음을 집어주는 영상들이 있어 소개한다.

https://youtu.be/KbRQtwiOQu0

'Personal Interest > Book' 카테고리의 다른 글

Power English  (0) 2022.05.08
인생 사용 설명서  (0) 2022.05.01
2월 구입 도서  (0) 2009.02.15
사랑을 찾아 돌아오다  (2) 2008.12.10
러브 다이어리  (0) 2008.12.10
Posted by neodelicious
|

그냥 mm 이 있는데, active mm 는 뭔가?

 

kernel thread 가 잠시 빌려쓰는 그전 process 의 mm 이라고 알고 있는데, 이렇게만 알고 있으면 아, 너무 외운듯한 설명이다.


https://kernelnewbies.kernelnewbies.narkive.com/Glj0IaUL/active-mm-versus-mm

 

구글링 해보면 상세 설명된 글이 쉽게 찾아진다.

위 link 에서 아래처럼 설명해주면서 Gorman book 에도 있다고 얘기해준다.

This avoids some costly TLB switches.

 

https://students.mimuw.edu.pl/SO/Linux-doc/gorman_book.pdf

그래서 Gorman book 을 찾아본다. 

The call to switch mm(), which results in a TLB flush, is avoided by borrowing the mm struct used by the previous task and placing it in task struct→active mm. This technique has made large improvements to context switch times.

 

https://docs.kernel.org/vm/active_mm.html

구글링에 kernel doc 이 검색되었다. 이런, active_mm 도 doc 이 있었다니. 그런데 Torvalds 가 1999 년에 쓴 글이다. 아, 너무 Linux 초창기 글이다. Gorman book 보다 먼저 쓴 글이리라.

 

code 좀 찾아보자.

kernel/sched/core.c @ v5.15

 

schedule 에서 next 가 kernel thread 로 되는 경우도 기존에 user thread 인지 kernel thread 인지에 조금 다르게 처리해야 하네. user thread 에서 왔으면 mmgrab 해서 mm->mm_count 를 inc 해야 하고, kernel thread 에서 왔으면 그 prev kernel thread 의 acative_mm 을 NULL 로 원복해준다. Torvalds 글이 이런 내용을 포함하고 있는 것 같다.

 

 4888 static __always_inline struct rq *
 4889 context_switch(struct rq *rq, struct task_struct *prev,
 4890                struct task_struct *next, struct rq_flags *rf)
 4891 {
 4892         prepare_task_switch(rq, prev, next);
 4893 
 4894         /*
 4895          * For paravirt, this is coupled with an exit in switch_to to
 4896          * combine the page table reload and the switch backend into
 4897          * one hypercall.
 4898          */
 4899         arch_start_context_switch(prev);
 4900 
 4901         /*
 4902          * kernel -> kernel   lazy + transfer active
 4903          *   user -> kernel   lazy + mmgrab() active
 4904          *
 4905          * kernel ->   user   switch + mmdrop() active
 4906          *   user ->   user   switch
 4907          */
 4908         if (!next->mm) {                                // to kernel
 4909                 enter_lazy_tlb(prev->active_mm, next);
 4910 
 4911                 next->active_mm = prev->active_mm;
 4912                 if (prev->mm)                           // from user
 4913                         mmgrab(prev->active_mm);
 4914                 else
 4915                         prev->active_mm = NULL;
 4916         } else {                                        // to user
 4917                 membarrier_switch_mm(rq, prev->active_mm, next->mm);
 4918                 /*
 4919                  * sys_membarrier() requires an smp_mb() between setting
 4920                  * rq->curr / membarrier_switch_mm() and returning to userspace.
 4921                  *
 4922                  * The below provides this either through switch_mm(), or in
 4923                  * case 'prev->active_mm == next->mm' through
 4924                  * finish_task_switch()'s mmdrop().
 4925                  */
 4926                 switch_mm_irqs_off(prev->active_mm, next->mm, next);
 4927 
 4928                 if (!prev->mm) {                        // from kernel
 4929                         /* will mmdrop() in finish_task_switch(). */
 4930                         rq->prev_mm = prev->active_mm;
 4931                         prev->active_mm = NULL;
 4932                 }
 4933         }
 4934 
 4935         rq->clock_update_flags &= ~(RQCF_ACT_SKIP|RQCF_REQ_SKIP);
 4936 
 4937         prepare_lock_switch(rq, next, rf);
 4938 
 4939         /* Here we just switch the register state and the stack. */
 4940         switch_to(prev, next, prev);
 4941         barrier();
 4942 
 4943         return finish_task_switch(prev);
 4944 }

 

그런데 TLB flush 를 회피한다는 내용은 어디에 있는 건가.

arch/arm64/include/asm/mmu_context.h @ v5.15

 

194 static inline void
195 enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
196 {
197         /*
198          * We don't actually care about the ttbr0 mapping, so point it at the
199          * zero page.
200          */
201         update_saved_ttbr0(tsk, &init_mm);
202 }

 

context_switch 에서 연결되는 enter_lazy_tlb 에 zero page 로 point 한다고 주석이 되어 있다. CONFIG_ARM64_SW_TTBR0_PAN 즉 SW 로 TTB0_PAN 을 하는 경우 아래처럼 update_saved_ttbr0 가 구현되어 있다.

 

170 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
171 static inline void update_saved_ttbr0(struct task_struct *tsk,
172                                       struct mm_struct *mm)
173 {
174         u64 ttbr;
175 
176         if (!system_uses_ttbr0_pan())
177                 return;
178 
179         if (mm == &init_mm)
180                 ttbr = phys_to_ttbr(__pa_symbol(reserved_pg_dir));
181         else
182                 ttbr = phys_to_ttbr(virt_to_phys(mm->pgd)) | ASID(mm) << 48;
183 
184         WRITE_ONCE(task_thread_info(tsk)->ttbr0, ttbr);
185 }
186 #else
187 static inline void update_saved_ttbr0(struct task_struct *tsk,
188                                       struct mm_struct *mm)
189 {
190 }
191 #endif

arch/arm64/kernel/vmlinux.lds.S @ v5.15

195         reserved_pg_dir = .;
196         . += PAGE_SIZE; 

 

그럼 반대로 kernel thread 로 context_switch 하지 않으면 tlb flush 를 하는 code 는 어디에 있는건지? tlb flush 를 해야 한다고 알고 있고, code 도 예전에 찾아봤었는데 code 가 바로 안 찾아지네.

 

찾았다.

 

include/linux/mmu_context.h @ v5.15

  8 /* Architectures that care about IRQ state in switch_mm can override this. */
  9 #ifndef switch_mm_irqs_off
 10 # define switch_mm_irqs_off switch_mm
 11 #endif

arch/arm64/include/asm/mmu_context.h @ v5.15

218 static inline void
219 switch_mm(struct mm_struct *prev, struct mm_struct *next,
220           struct task_struct *tsk)
221 {
222        if (prev != next)
223                 __switch_mm(next);
224 
225         /*
226          * Update the saved TTBR0_EL1 of the scheduled-in task as the previous
227          * value may have not been initialised yet (activate_mm caller) or the
228          * ASID has changed since the last run (following the context switch
229          * of another thread of the same process).
230          */
231         update_saved_ttbr0(tsk, next);
232 }
204 static inline void __switch_mm(struct mm_struct *next)
205 {
206         /*
207          * init_mm.pgd does not contain any user mappings and it is always
208          * active for kernel addresses in TTBR1. Just set the reserved TTBR0.
209          */
210         if (next == &init_mm) {
211                 cpu_set_reserved_ttbr0();
212                 return;
213         }
214 
215         check_and_switch_context(next);
216 }

arch/arm64/mm/context.c @ v5.15

 

215 void check_and_switch_context(struct mm_struct *mm)
216 {
217         unsigned long flags;
218         unsigned int cpu;
219         u64 asid, old_active_asid;
220 
221         if (system_supports_cnp())
222                 cpu_set_reserved_ttbr0();
223 
224         asid = atomic64_read(&mm->context.id);
225 
226         /*
227          * The memory ordering here is subtle.
228          * If our active_asids is non-zero and the ASID matches the current
229          * generation, then we update the active_asids entry with a relaxed
230          * cmpxchg. Racing with a concurrent rollover means that either:
231          *
232          * - We get a zero back from the cmpxchg and end up waiting on the
233          *   lock. Taking the lock synchronises with the rollover and so
234          *   we are forced to see the updated generation.
235          *
236          * - We get a valid ASID back from the cmpxchg, which means the
237          *   relaxed xchg in flush_context will treat us as reserved
238          *   because atomic RmWs are totally ordered for a given location.
239          */
240         old_active_asid = atomic64_read(this_cpu_ptr(&active_asids));
241         if (old_active_asid && asid_gen_match(asid) &&
242             atomic64_cmpxchg_relaxed(this_cpu_ptr(&active_asids),
243                                      old_active_asid, asid))
244                 goto switch_mm_fastpath;
245 
246         raw_spin_lock_irqsave(&cpu_asid_lock, flags);
247         /* Check that our ASID belongs to the current generation. */
248         asid = atomic64_read(&mm->context.id);
249         if (!asid_gen_match(asid)) {
250                 asid = new_context(mm);
251                 atomic64_set(&mm->context.id, asid);
252         }
253 
254         cpu = smp_processor_id();
255         if (cpumask_test_and_clear_cpu(cpu, &tlb_flush_pending))
256                 local_flush_tlb_all();
257 
258         atomic64_set(this_cpu_ptr(&active_asids), asid);
259         raw_spin_unlock_irqrestore(&cpu_asid_lock, flags);
260 
261 switch_mm_fastpath:

 

flush tlb 까지 오는데 code 가 이렇게 깊었던가;

그리고 ASID 에 따라서 flush_tlb 를 안 해도 된다는 건데, 아 이건 좀 나중에 다시 봐야겠다.

 

https://developer.arm.com/documentation/den0024/a/The-Memory-Management-Unit/Context-switching

 

'Linux Internal > mm' 카테고리의 다른 글

mm: vmscan: shrink_zone  (0) 2017.07.22
dma: history  (0) 2017.07.09
staging: ion: history  (0) 2017.07.09
PageReserved source  (0) 2012.07.16
Posted by neodelicious
|

<책 겉표지 그림 출처 : yes24>

 

작년에 몇 달 정도 입트영(입이 트이는 영어)를 했었는데, 그때 입트영이 아닌 다른 시간대에 방송을 접속했다가 Power English 라는 것을 알게 되었다. 듣는데, 이런! 이 방송은 전부 영어로 하네!! 어쩌다 한 두 단어를 한국어로 해주기도 하는데 한국어는 거의 없다고 봐도 무방하다. 그런데 하던 입트영을 일단 더 하는 게 좋겠다고 생각하고 Power English 는 일단 접어뒀다. 그리고 입트영을 몇 달 하다가 또 몇 달째 안 하고 있었다.

 

2022년도 이미 5월이지만, 이제 다시 영어 공부 좀 해야겠다는 생각이 들었다. 입트영도 좋다. 그런데 모르는 문구를 익히려고 하고 나오는 작문 숙제를 다 하면서 따라가다가 좀 지친 것 같다. 몇 달 쉬고 나니 다른 거 하고 싶었다. 그래서 Power English. 5월 교재 구매하고 방송 시간에 맞춰서 따라가 본다. 확실히 숙제도 적고 듣고 있으니 재밌다. 딱히 어려운 얘기를 하지도 않고 내가 부담이 적다.

 

1주일을 들어봤다. 크리스틴 조, 카메론 리 워드. 이런 1주일 들었는데 진행자의 진행에 이미 빠졌다. 그리고 마지막에 오디오 어학당! 이라고 하는데 아, 이거 어학당 들어가봐야겠다는 생각이든다. 아침 7시40분에 맞춰 듣기가 쉽지 않은데 어학당 이거 유료 결제하면 Audio On Demand 그러니까 아무 때나 들을 수 있다. 물론 저녁 시간이나 주말에도 재방송이 있긴 한데 시간이 어중간 하다. 어학당 home page 가보니 당일 방송이 제공되지 않게 최근 바뀐 건지 불만이 있어 보이긴 한데 뭐 괜찮다, 하루씩 늦게 들으면 되는 거지. (-> update : 당일도 올라오는 것 같은데?) 할당에 약 5천원 나를 위해 투자해본다.

 

아, 어학당 둘러보면서 예전에 하다가 중단한 입트영도 방송도 찾아서 마져 끝낼 수 있다. 다른 어학 방송도 들을 수 있다. 와우. 그리고 추가로 내가 잠시 의욕이 넘쳐서 동아 출판사 home page 에서 Power English 과월호 1~4월호도 구매 질러본다. 한 달에 2권씩 Power English 해 보기?

'Personal Interest > Book' 카테고리의 다른 글

Image Making English  (0) 2022.05.23
인생 사용 설명서  (0) 2022.05.01
2월 구입 도서  (0) 2009.02.15
사랑을 찾아 돌아오다  (2) 2008.12.10
러브 다이어리  (0) 2008.12.10
Posted by neodelicious
|