10차 ARM 리눅스 커널 스터디 49주차(2014.04.05) 후기입니다.
일시 : 2014.04.05 (49주차)
모임명 : NAVER개발자커뮤니티지원_IAMROOT.ORG_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 5명
스터디 진도 :
start_kernel()-> mm_init()->page_cgroup_init_flatmem();
// null function
start_kernel()-> mm_init()->mem_init();
mm_init()
mem_map에서 미사용영역(free area)를 찾아서 사용가능한 미사용 영역을 구하고 이것을 커널이 관리할 수 있는 메모리 관리자(memomry allocator)로 설정해 주는 과정 start_kernel이 시작한 이후 몆곳에서 일부 메모리를 할당 받아서 설정한 이후 실행됨
static void __init mm_init(void)
{
page_cgroup_init_flatmem();
// null function
mem_init();
kmem_cache_init();
percpu_init_late();
pgtable_cache_init();
vmalloc_init();
}
page_cgroup_init_flatmem();
- mem_init()의 서브 함수
- null function
mem_init();
- mem_init()의 서브 함수
- 1 각 노드에서 hole영역이 있다면 미사용영역으로 설정한다. (우리는 해당없음)
- 2 bootmem의 page frame의 가용 여부를 나타내는 비트맵의 해당 bit를 초기화함
- 3 비트맵의 bit가 0으로 초기화된 page를 버디 할당자 (buddy allocator)로 설정해 줌
- 4 현재 시스템의 가용 memory등에 대한 정보를 출력함
void __init mem_init(void) { max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map; free_unused_memmap(&meminfo); // bank 0, 1중에 연속되지 않거나 align이 되지 않았다면 free_memmap을 실행 free_all_bootmem(); ... }
max_mapnr = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
// max_mapnr : 10번째 page section 주소 + 0xA0000
free_unused_memmap(&meminfo);
// bank 0, 1중에 연속되지 않거나 align이 되지 않았다면 free_memmap을 실행
static void __init free_unused_memmap(struct meminfo *mi)
{
unsigned long bank_start, prev_bank_end = 0;
unsigned int i;
for_each_bank(i, mi) {
// for (i = 0; i < (&meminfo)->nr_banks; i++)
struct membank *bank = &mi->bank[i];
bank_start = bank_pfn_start(bank);
bank_start = min(bank_start,
ALIGN(prev_bank_end, PAGES_PER_SECTION));
if (prev_bank_end && prev_bank_end < bank_start)
free_memmap(prev_bank_end, bank_start);
prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
}
if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION))
free_memmap(prev_bank_end,
ALIGN(prev_bank_end, PAGES_PER_SECTION));
}
free_all_bootmem()
- 메모리 노드가 가진 모든 페이지의 사용 여부를 나타내는 bdata자료 구조를 사용해서 bootmem map에 해당 영역이 사용 중인지 사용 가능한지를 표시 한다.
- free_pages_check -> for {list_all_zones_managed_page() } -> free_all_bootmem_core(bdata);
unsigned long __init free_all_bootmem(void) { unsigned long total_pages = 0; bootmem_data_t *bdata; reset_all_zones_managed_pages(); list_for_each_entry(bdata, &bdata_list, list) // for (bdata = list_entry((&bdata_list)->next, typeof(*bdata), list); // &bdata->list != (&bdata_list); // bdata = list_entry(bdata->list.next, typeof(*bdata), list)) // bdata: &bdata_list, &bdata->list: (&bdata_list)->list total_pages += free_all_bootmem_core(bdata); totalram_pages += total_pages; return total_pages; }
free_all_bootmem_core(bdata);
- free_all_bootmem -> ofor (list_all_zones_managed_page() ) free_all_bootmem_core(bdata);
- 인자로 전달받은 bdata(node정보)를 이용하여 현재 노드에서 미사용영역(free)의 page를 미사용영역으로 설정함static unsigned long __init free_all_bootmem_core(bootmem_data_t *bdata) { struct page *page; unsigned long start, end, pages, count = 0;if (!bdata->node_bootmem_map)
return 0;
start = bdata->node_min_pfn; end = bdata->node_low_pfn; bdebug("nid=%td start=%lx end=%lx\n",bdata - bootmem_node_data, start, end);
while (start < end) {unsigned long *map, idx, vec; unsigned shift; map = bdata->node_bootmem_map; idx = start - bdata->node_min_pfn; shift = idx & (BITS_PER_LONG - 1); vec = ~map[idx / BITS_PER_LONG]; if (shift) { vec >>= shift; if (end - start >= BITS_PER_LONG) vec |= ~map[idx / BITS_PER_LONG + 1] << (BITS_PER_LONG - shift); } if (IS_ALIGNED(start, BITS_PER_LONG) && vec == ~0UL) { int order = ilog2(BITS_PER_LONG); __free_pages_bootmem(pfn_to_page(start), order); count += BITS_PER_LONG; start += BITS_PER_LONG; } else { unsigned long cur = start; start = ALIGN(start + 1, BITS_PER_LONG); while (vec && cur != start) { if (vec & 1) { page = pfn_to_page(cur); __free_pages_bootmem(page, 0); count++; } vec >>= 1; ++cur; } }
}page = virt_to_page(bdata->node_bootmem_map); pages = bdata->node_low_pfn - bdata->node_min_pfn; pages = bootmem_bootmap_pages(pages); count += pages; while (pages--)__free_pages_bootmem(page++, 0);
bdebug("nid=%td released=%lx\n", bdata - bootmem_node_data, count);return count; }
page->_mapcount는 -1로 초기화했었다.
__free_pages_bootmem(struct page *page, unsigned int order)
- start: 0x20000, pfn_to_page(0x20000): 0x20000의 해당하는 struct page의 주소
- __free_pages_bootmem(pfn_to_page(start), order);
void __init __free_pages_bootmem(struct page *page, unsigned int order)
{
unsigned int nr_pages = 1 << order;
unsigned int loop;
prefetchw(page);
for (loop = 0; loop < nr_pages; loop++) {
struct page *p = &page[loop];
if (loop + 1 < nr_pages)
prefetchw(p + 1);
__ClearPageReserved(p);
set_page_count(p, 0);
}
page_zone(page)->managed_pages += 1 << order;
set_page_refcounted(page);
__free_pages(page, order);
}
__free_pages(page, order);
- page: 0x20000의 해당하는 struct page의 1st page, order: 5
void __free_pages(struct page *page, unsigned int order)
{
if (put_page_testzero(page)) {
if (order == 0)
free_hot_cold_page(page, 0);
else
__free_pages_ok(page, order);
}
}
__free_pages_ok(page, order);
- page: 0x20000의 해당하는 struct page의 1st page, order: 5
static void __free_pages_ok(struct page *page, unsigned int order) { unsigned long flags; int migratetype; if (!free_pages_prepare(page, order)) return; local_irq_save(flags); __count_vm_events(PGFREE, 1 << order); migratetype = get_pageblock_migratetype(page); set_freepage_migratetype(page, migratetype); free_one_page(page_zone(page), page, order, migratetype); local_irq_restore(flags); }
if (!free_pages_prepare(page, order))
- page: 0x20000의 해당하는 struct page의 1st page, order: 5
static bool free_pages_prepare(struct page *page, unsigned int order) { int i; int bad = 0; trace_mm_page_free(page, order); kmemcheck_free_shadow(page, order); // null function if (PageAnon(page)) page->mapping = NULL; for (i = 0; i < (1 << order); i++) bad += free_pages_check(page + i); if (bad) return false; if (!PageHighMem(page)) { debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order); debug_check_no_obj_freed(page_address(page), PAGE_SIZE << order); } arch_free_page(page, order); kernel_map_pages(page, 1 << order, 0); return true; }
free_pages_check(page +i)
call code
// order: 5
for (i = 0; i < (1 << order); i++)
// page: 0x20000 (pfn)
bad += free_pages_check(page + i);
called code
static inline int free_pages_check(struct page *page)
{
if (unlikely(page_mapcount(page) |
(page->mapping != NULL) |
(atomic_read(&page->_count) != 0) |
pageflags
enum pageflags {
PG_locked, /* Page is locked. Don't touch. */
PG_error,
PG_referenced,
PG_uptodate,
PG_dirty,
PG_lru,
PG_active,
PG_slab,
PG_owner_priv_1, /* Owner use. If pagecache, fs may use*/
PG_arch_1,
PG_reserved, // ARM10C 20140118, 10
PG_private, /* If pagecache, has fs-private data */
PG_private_2, /* If pagecache, has fs aux data */
PG_writeback, /* Page is under writeback */
// ARM10C 20140125
// PG_compound: 14
PG_compound, /* A compound page */
PG_swapcache, /* Swap page: swp_entry_t in private */
PG_mappedtodisk, /* Has blocks allocated on-disk */
// ARM10C 20140125
// PG_reclaim: 17
PG_reclaim, /* To be reclaimed asap */
PG_swapbacked, /* Page is backed by RAM/swap */
PG_unevictable, /* Page is "unevictable" */
#ifdef CONFIG_MMU
PG_mlocked, /* Page is vma mlocked */
#endif
#ifdef CONFIG_ARCH_USES_PG_UNCACHED
PG_uncached, /* Page has been mapped as uncached */
#endif
#ifdef CONFIG_MEMORY_FAILURE
PG_hwpoison, /* hardware poisoned page. Don't touch */
#endif
#ifdef CONFIG_TRANSPARENT_HUGEPAGE
PG_compound_lock,
#endif
__NR_PAGEFLAGS,
/* Filesystems */
PG_checked = PG_owner_priv_1,
/* Two page bits are conscripted by FS-Cache to maintain local caching
* state. These bits are set on pages belonging to the netfs's inodes
* when those inodes are being locally cached.
*/
PG_fscache = PG_private_2, /* page backed by cache */
/* XEN */
PG_pinned = PG_owner_priv_1,
PG_savepinned = PG_dirty,
/* SLOB */
PG_slob_free = PG_private,
};
page_mapcount_reset(struct page *page)
page_mapcount_reset(struct page *page)
{
atomic_set(&(page)->_mapcount, -1);
}
(page->flags & PAGE_FLAGS_CHECK_AT_FREE) |
(mem_cgroup_bad_page_check(page)))) {
bad_page(page);
return 1;
}
page_nid_reset_last(page);
if (page->flags & PAGE_FLAGS_CHECK_AT_PREP)
page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
return 0;
}
if (unlikely(page_mapcount(page) | (page->mapping != NULL) |
// pageAton 에서 page->mapping : 0으로 초기화
(atomic_read(&page->_count) != 0) |
(page->flags & PAGE_FLAGS_CHECK_AT_FREE) | // pfn_to_page(pfn) 서 page->flags : 0x2000 0000 // free_pages_bootmem(struct page *page, unsigned int order) // 에서 ClearPageReserved(p); // p: 0x20001 (pfn) // page reserved 속성을 clear
(mem_cgroup_bad_page_check(page)))) {
bad_page(page);
PAGE_FLAGS_CHECK_AT_FREE :
PAGE_FLAGS_CHECK_AT_PREP : 0x1FFFF
page->flags :0x200000 (pfn)
page_mapcount_reset(struct page *page)
page_mapcount_reset(struct page *page)
{
atomic_set(&(page)->_mapcount, -1);
}
arch_free_page(page, order);
// null function
#ifndef HAVE_ARCH_FREE_PAGE
static inline void arch_free_page(struct page *page, int order) { }
#endif
#ifndef HAVE_ARCH_ALLOC_PAGE
static inline void arch_alloc_page(struct page *page, int order) { }
#endif
kernel_map_pages(page, 1 << order, 0);
// null function
static inline void
kernel_map_pages(struct page *page, int numpages, int enable) {}
if (!free_pages_prepare(page, order))
// page: 0x20000의 해당하는 struct page의 1st page, order: 5
static bool free_pages_prepare(struct page *page, unsigned int order)
{
int i;
int bad = 0;
// mm_page_free이름으로 아래의 trace 관련 함수가 만들어져 있음
// trace_mm_page_free, register_trace_mm_page_free
// unregister_trace_mm_page_free, check_trace_callback_type_mm_page_free
// page: 0x20000의 해당하는 struct page의 1st page, order: 5
trace_mm_page_free(page, order);
// page: 0x20000의 해당하는 struct page의 1st page, order: 5
kmemcheck_free_shadow(page, order); // null function
// page: 0x20000의 해당하는 struct page의 1st page
// PageAnon(page): 0
if (PageAnon(page))
page->mapping = NULL;
// 2014/03/29 종료
// order: 5
for (i = 0; i < (1 << order); i++)
// page: 0x20000 (pfn)
bad += free_pages_check(page + i);
// free_pages_check 페이지가 free나 reserved, flags가 있는지
// 검사하는 함수이다.
if (bad)
return false;
if (!PageHighMem(page)) {
debug_check_no_locks_freed(page_address(page),PAGE_SIZE<<order);
// null function
debug_check_no_obj_freed(page_address(page),
PAGE_SIZE << order);
// null function
}
arch_free_page(page, order);
kernel_map_pages(page, 1 << order, 0);
return true;
}
free_pages_check(page +i)
이 함수는 reserved 되어 있거나 flags에 설정된 값이 있다면 free 영역이 아니므로 bad로 수를 센다.
// order: 5
for (i = 0; i < (1 << order); i++)
// page: 0x20000 (pfn)
bad += free_pages_check(page + i);
free_pages_check(page + i); 의 의미 다음 page를 미리 읽는 것이다.
free_pages_check(page + i)
static inline int free_pages_check(struct page *page)
{
if (unlikely(page_mapcount(page) |
(page->mapping != NULL) |
(atomic_read(&page->_count) != 0) |
(page->flags & PAGE_FLAGS_CHECK_AT_FREE) |
(mem_cgroup_bad_page_check(page)))) {
bad_page(page);
return 1;
}
page_nid_reset_last(page);
if (page->flags & PAGE_FLAGS_CHECK_AT_PREP)
page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
// NR_PAGEFLAGS 만큼의 하위 비트를 전부 지워줌
// NR_PAGEFLAGS : 21
return 0;
}
if (unlikely(page_mapcount(page) |
(page->mapping != NULL) |
// PageAnon(page): 0
// if (PageAnon(page))
// page->mapping = NULL;
// pageAton 에서 page->mapping : 0으로 초기화
(atomic_read(&page->_count) != 0) |
(page->flags & PAGE_FLAGS_CHECK_AT_FREE) |
// pfn_to_page(pfn) 서 page->flags : 0x2000 0000
// __ClearPageReserved(p); 에서 reserved를 해제해줌
(mem_cgroup_bad_page_check(page)))) {
bad_page(page);
PAGE_FLAGS_CHECK_AT_FREE :
__count_vm_events(PGFREE, 1 << order);
// pcpu로 할당 받았던 영역에 my_cpu_offset :0에 대한 하는 곳에 order :32 만큼 // 델타를 설정해서 PFFREE라고 설정함
static inline void __count_vm_events(enum vm_event_item item, long delta)
{
__this_cpu_add(vm_event_states.event[item], delta);
}
::percpu.h
# define __this_cpu_add(pcp, val) __pcpu_size_call(__this_cpu_add_, (pcp), (val))
::percpu.h
# define __this_cpu_add_1(pcp, val) __this_cpu_generic_to_op((pcp), (val), +=)
::percpu.h
#define __pcpu_size_call(stem, variable, ...) \
do { \
__verify_pcpu_ptr(&(variable)); \
// __pcpu_size_call (__this_cpu_add_, (pcp),(val))
// __pcpu_size_call (__this_cpu_add_, vm_event_states.event[7], delta)
// pcp : vm_event_state.event[7], val : 32
// vm_event_stat.event[7] :PGFREE
switch(sizeof(variable)) { \
// __verify_pcpu_ptr(&(vm_event_states.event[7]));
// switch(sizeof(&(vm_event_states.event[7])); 경고용
case 1: stem##1(vm_event_states.event[7], __VA_ARGS__);break; \
// case 1: __this_cpu_add_1( __VA_ARGS__);break; \
case 2: stem##2(variable, __VA_ARGS__);break; \
case 4: stem##4(variable, __VA_ARGS__);break; \
case 8: stem##8(variable, __VA_ARGS__);break; \
default: \
__bad_size_call_parameter();break; \
// __this_cpu_add_4 : *__this_cpu_ptr(&(vm_event_states.event[7]) += delta;
} \
} while (0)
migratetype = get_pageblock_migratetype(page);
mmzone.h
static inline int get_pageblock_migratetype(struct page *page)
{
return get_pageblock_flags_group(page, PB_migrate, PB_migrate_end);
}
::page_alloc.c
unsigned long get_pageblock_flags_group(struct page *page,
int start_bitidx, int end_bitidx)
{
struct zone *zone;
unsigned long *bitmap;
unsigned long pfn, bitidx;
unsigned long flags = 0;
unsigned long value = 1;
zone = page_zone(page);
pfn = page_to_pfn(page);
// pageblock_order :9 , NR_PAGEBLOCK_BITS: 4
// bit : page 1024개당 1바이트 씩 사용
bitmap = get_pageblock_bitmap(zone, pfn);
// pfn : 0x20000
bitidx = pfn_to_bitidx(zone, pfn);
// bitidx: 0
// start_bitidx : 0, end_bitidx : 2, value : 1, bitidx : 0
for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
if (test_bit(bitidx + start_bitidx, bitmap))
flags |= value;
return flags;
}
:: pfn_to_bitidx
static inline int pfn_to_bitidx(struct zone *zone, unsigned long pfn)
{
#ifdef CONFIG_SPARSEMEM
// PAGES_PER_SECTION : 0x10000
// pfn : 0 (section의 몇 번째 프레임)
// pfn : 0xF800
pfn &= (PAGES_PER_SECTION-1);
// pageblock_order: 9, NR_PAGEBLOCK_BITS : 4
// bit : page 1024개당 1 바이트씩 사용
return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
// return 0x0
// return 0x1F0
#else
pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages);
return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
#endif /* CONFIG_SPARSEMEM */
}
메모리 단위
- 1 section : 64 pageblock (256MB)
- 1 pageblock : 1024 page (4MB)
- 1 page : 4k
free_area_init_core에 대한 주석을 읽고 가자
- Set up the zone data structures:
- mark all pages reserved
- mark all memory queues empty
- clear the memory bitmaps *
- NOTE: pgdat should get zeroed by caller.static void __paginginit free_area_init_core(struct pglist_data *pgdat, unsigned long node_start_pfn, unsigned long node_end_pfn, unsigned longzones_size, unsigned long zholes_size) { ... memmap_init(size, nid, j, zone_start_pfn);// struct page 내부 멤버를 설정 // flags : section, node, zone 번호, PG_reserved(10) 설정 // page->__count.counter : 1 // page->_mapcount.counter : -1 // page->lru 초기화 // page에 해당하는 &mem_section[0][2]->pageblock_flags의 // MIGRATE_MOVABLE(2)번 비트를 1로 설정(pageblock마다) // mem_section[0][2] ~ mem_section[0][9] 까지 설정// zone_start_pfn : 0x4F800 // zone_start_pfn : 0xA0000 ... }bitidx = pfn_to_bitidx(zone,pfn);0x200000 ~ 0x203FF : 0000 0010 0x200400 ~ 0x207FF : 0000 0010
for (; start_bitidx <= end_bitidx; start_bitidx++, value <<= 1)
- 에서 0번 비트, 1번 비트 , 2번 비트를 돌면서 1번 비트(0x2)가 1인지 확인해서 flags 를 갱신하므로 최종 flags : 0x2가 리턴 된다.
free_one_page(page_zone(page), page, order, migratetype);
all_unreclaimable : all pages pinned
pages_scanned : since last reclaim
__free_one_page(page, zone, order, migratetype);
unsigned long uninitialized_var(buddy_idx);
unsigned long buddy_idx = buddy_idx ;
초기화 되지 않은 지역 변수에 대한 경고 메시지를 없에기 위함
if (unlikely(PageCompound(page)))
PageCompound (const struct page *page)
{ retrun test_bit(PG_compound, & paga->flags);}
// PG_compound : enum 14
::page-flags.h
TESTPAGEFLAG(Compound, compound)
__SETPAGEFLAG(Head, compound) __CLEARPAGEFLAG(Head, compound)
::page-flags.h
#define TESTPAGEFLAG(uname, lname) \
static inline int Page##uname(const struct page *page) \
{ return test_bit(PG_##lname, &page->flags); }
page_idx = page_to_pfn(page) & ((1 << MAX_ORDER) - 1);
- MAX_ORDER : 11 ( 1<< MAX_ORDER) -1 : 0x7FF
- page_to_pfn(page) : 0x2000011 : 4M + 4M 10 : 2M 2M 2M 2M 9 : 1M 1M 8 : 512K 7 : 256k 6 : 128l 5 : 64k 4 : 32k 3 : 16k 2 : 8k 1 : 4k
VM_BUG_ON(bad_range(zone, page)); while (order < MAX_ORDER-1) { buddy_idx = __find_buddy_index(page_idx, order); buddy = page + (buddy_idx - page_idx);
::page_alloc.c
static inline unsigned long
__find_buddy_index(unsigned long page_idx, unsigned int order)
{
return page_idx ^ (1 << order);
}
- order : 5
- rerurn : 32
__find_buddy_index
- 1 << order 만큼 떨어진 곳의 짝의 index를 찾아냄
- idx ^ ( 1<< order)
// page : 0x20000 (fpn), buddy_idx : 32, page_idx : 0 buddy = page + (buddy_idx - page_idx); // page : 0x20000 (fpn), buddy : 0x20020 if (!page_is_buddy(page, buddy, order))
page_is_buddy()
static inline int page_is_buddy(struct page *page, struct page *buddy,
int order)
{
// page_to_pfn(byddy) : 0x20020
//
// pfn_valid_within () :1
if (!pfn_valid_within(page_to_pfn(buddy)))
return 0;
// NODES_PGOFF : 28
// ZONES_PGOFF : 26
// ZONEID_PGOFF : 26
// NODES_SHIFT : 0 , MAXX_NR_ZONES : 3, MAX_NR_SHIFT : 2
// ZONEID_SHIFT : 26
// page_zone_id(buddy) : 0
if (page_zone_id(page) != page_zone_id(buddy))
return 0;
// static inline bool page_is_guard(struct page *page) { return false; }
//
if (page_is_guard(buddy) && page_order(buddy) == order) {
VM_BUG_ON(page_count(buddy) != 0);
return 1;
}
if (PageBuddy(buddy) && page_order(buddy) == order) {
VM_BUG_ON(page_count(buddy) != 0);
return 1;
}
return 0;
}
:: mm/internal.h
ostatic inline unsigned long page_order(struct page *page)
{
/* PageBuddy() must be checked by the caller */
return page_private(page);
}
set_page_order (page, order);
page-.private: 5
page->_mapcount : -128 로 설정
list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
// contig_page_data.node_zone[ZONE_NORMAL].free_area[5].free_list[MIGRATE_MOVABLE]
에 0x2000(pfn) struct page를 연결
out:
zone->free_area[order].nr_free++;
// zone->free_area[5].nr_free :1
// free 상태인 order 5 buddy 의 갯수를 증가
git log
# git log
2159499..d0bb9ad master -> origin/master
Updating 2159499..d0bb9ad
Fast-forward
arch/arm/include/asm/percpu.h | 1 +
arch/arm/include/asm/spinlock.h | 1 +
include/asm-generic/percpu.h | 2 ++
include/linux/compiler-gcc.h | 1 +
include/linux/compiler.h | 1 +
include/linux/debug_locks.h | 1 +
include/linux/debugobjects.h | 1 +
include/linux/gfp.h | 1 +
include/linux/irqflags.h | 1 +
include/linux/lockdep.h | 2 +-
include/linux/memcontrol.h | 1 +
include/linux/mm.h | 42 ++++++++++++++++++++++++++++++++++++++++--
include/linux/mm_types.h | 3 ++-
include/linux/mmzone.h | 9 ++++++++-
include/linux/numa.h | 1 +
include/linux/page-flags-layout.h | 1 +
include/linux/page-flags.h | 54 ++++++++++++++++++++++++++++++++++++++++--------------
include/linux/page-isolation.h | 3 ++-
include/linux/percpu.h | 3 +++
include/linux/spinlock.h | 2 ++
include/linux/spinlock_api_smp.h | 6 +++++-
include/linux/vm_event_item.h | 35 ++++++++++++++++++++---------------
include/linux/vmstat.h | 32 +++++++++++++++++++++++++++++++-
kernel/spinlock.c | 3 ++-
lib/spinlock_debug.c | 2 ++
mm/internal.h | 1 +
mm/page_alloc.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
27 files changed, 303 insertions(+), 43 deletions(-)2159499..d0bb9ad master -> origin/master
댓글 없음:
댓글 쓰기