ARM10C : 115 주차
일시 : 2015.08.22 (115 주차 스터디 진행)
모임명 : NAVER_개발자커뮤니티지원_10차ARM-C
장소 : 토즈 타워점
장소지원 : NAVER 개발자 커뮤니티 지원 프로그램
참여인원 : 3명
115 주차 진도
- start_kernel 1 ~/kernel/iamroot/linux-stable/init/main.c
- cgroup_init_early 634 ~/kernel/iamroot/linux-stable/init/main.c
- init_task 5239 RCU_INIT_POINTER(init_task.cgroups, &init_css_set);
- cgroup_init_early 634 ~/kernel/iamroot/linux-stable/init/main.c
main.c::start_kernel()
// ARM10C 20130824
// asmlinkage의 의미
// http://www.spinics.net/lists/arm-kernel/msg87677.html
asmlinkage void __init start_kernel(void)
{
char * command_line;
extern const struct kernel_param __start___param[], __stop___param[];
// ATAG,DTB 정보로 사용
/*
* Need to run as early as possible, to initialize the
* lockdep hash:
*/
lockdep_init();
smp_setup_processor_id();
debug_objects_early_init();
/*
* Set up the the initial canary ASAP:
*/
boot_init_stack_canary();
cgroup_init_early();
cgroup.c::cgroup_init_early()
- call: start_kernel()->cgroup_init_early()
- cgroup_init_early()
// ARM10C 20150808
int __init cgroup_init_early(void)
{
struct cgroup_subsys *ss;
int i;
atomic_set(&init_css_set.refcount, 1);
// atomic_set에서 한일:
// init_css_set.refcount: 1
INIT_LIST_HEAD(&init_css_set.cgrp_links);
// INIT_LIST_HEAD에서 한일:
// (&init_css_set.cgrp_links)->next: &init_css_set.cgrp_links
// (&init_css_set.cgrp_links)->prev: &init_css_set.cgrp_links
INIT_LIST_HEAD(&init_css_set.tasks);
// INIT_LIST_HEAD에서 한일:
// (&init_css_set.tasks)->next: &init_css_set.tasks
// (&init_css_set.tasks)->prev: &init_css_set.tasks
INIT_HLIST_NODE(&init_css_set.hlist);
// INIT_HLIST_NODE에서 한일:
// (&init_css_set.hlist)->next: NULL
// (&init_css_set.hlist)->pprev: NULL
css_set_count = 1;
// css_set_count: 1
init_cgroup_root(&cgroup_dummy_root);
// init_cgroup_root에서 한일:
// (&(&cgroup_dummy_root)->subsys_list)->next: &(&cgroup_dummy_root)->subsys_list
// (&(&cgroup_dummy_root)->subsys_list)->prev: &(&cgroup_dummy_root)->subsys_list
// (&(&cgroup_dummy_root)->root_list)->next: &(&cgroup_dummy_root)->root_list
// (&(&cgroup_dummy_root)->root_list)->prev: &(&cgroup_dummy_root)->root_list
// (&(&(&cgroup_dummy_root)->top_cgroup)->sibling)->next: &(&(&cgroup_dummy_root)->top_cgroup)->sibling
// (&(&(&cgroup_dummy_root)->top_cgroup)->sibling)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->sibling
// (&(&(&cgroup_dummy_root)->top_cgroup)->children)->next: &(&(&cgroup_dummy_root)->top_cgroup)->children
// (&(&(&cgroup_dummy_root)->top_cgroup)->children)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->children
// (&(&(&cgroup_dummy_root)->top_cgroup)->files)->next: &(&(&cgroup_dummy_root)->top_cgroup)->files
// (&(&(&cgroup_dummy_root)->top_cgroup)->files)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->files
// (&(&(&cgroup_dummy_root)->top_cgroup)->cset_links)->next: &(&(&cgroup_dummy_root)->top_cgroup)->cset_links
// (&(&(&cgroup_dummy_root)->top_cgroup)->cset_links)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->cset_links
// (&(&(&cgroup_dummy_root)->top_cgroup)->release_list)->next: &(&(&cgroup_dummy_root)->top_cgroup)->release_list
// (&(&(&cgroup_dummy_root)->top_cgroup)->release_list)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->release_list
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlists)->next: &(&(&cgroup_dummy_root)->top_cgroup)->pidlists
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlists)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->pidlists
// (&(&(&cgroup_dummy_root)->top_cgroup)->event_list)->next: &(&(&cgroup_dummy_root)->top_cgroup)->event_list
// (&(&(&cgroup_dummy_root)->top_cgroup)->event_list)->prev: &(&(&cgroup_dummy_root)->top_cgroup)->event_list
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->count: 1
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_lock)->rlock)->raw_lock: { { 0 } }
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_lock)->rlock)->magic: 0xdead4ead
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_lock)->rlock)->owner: 0xffffffff
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_lock)->rlock)->owner_cpu: 0xffffffff
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_list)->next: &(&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_list
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_list)->prev: &(&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->wait_list
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->onwer: NULL
// (&(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex)->magic: &(&(&cgroup_dummy_root)->top_cgroup)->pidlist_mutex
// (&(&(&cgroup_dummy_root)->top_cgroup)->event_list_lock)->raw_lock: { { 0 } }
// (&(&(&cgroup_dummy_root)->top_cgroup)->event_list_lock)->magic: 0xdead4ead
// (&(&(&cgroup_dummy_root)->top_cgroup)->event_list_lock)->owner: 0xffffffff
// (&(&(&cgroup_dummy_root)->top_cgroup)->event_list_lock)->owner_cpu: 0xffffffff
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->head)->next: &(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->head
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->head)->prev: &(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->head
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->lock)->raw_lock: { { 0 } }
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->lock)->magic: 0xdead4ead
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->lock)->owner: 0xffffffff
// (&(&(&(&cgroup_dummy_root)->top_cgroup)->xattrs)->lock)->owner_cpu: 0xffffffff
//
// (&(&cgroup_dummy_root)->top_cgroup)->dummy_css.cgroup: &(&cgroup_dummy_root)->top_cgroup
// (&(&cgroup_dummy_root)->top_cgroup)->root: &cgroup_dummy_root
// (&(&cgroup_dummy_root)->top_cgroup)->name: (struct cgroup_name *)(&root_cgroup_name)
// (&cgroup_dummy_root)->number_of_cgroups: 1
//
// (&cgroup_dummy_root)->cgroup_idr의 맵버값을 0으로 초기화 수행
// (&(&(&cgroup_dummy_root)->cgroup_idr)->lock)->raw_lock: { { 0 } }
// (&(&(&cgroup_dummy_root)->cgroup_idr)->lock)->magic: 0xdead4ead
// (&(&(&cgroup_dummy_root)->cgroup_idr)->lock)->owner: 0xffffffff
// (&(&(&cgroup_dummy_root)->cgroup_idr)->lock)->owner_cpu: 0xffffffff
cgroup_root_count = 1;
// cgroup_root_count: 1
RCU_INIT_POINTER(init_task.cgroups, &init_css_set);
// RCU_INIT_POINTER에서 한일:
// (&(&cgroup_dummy_root)->top_cgroup)->name: (struct cgroup_name *)(&root_cgroup_name)
// 2015/08/08 종료
// 2015/08/15 시작
init_cgrp_cset_link.cset = &init_css_set;
// init_cgrp_cset_link.cset: &init_css_set
// cgroup_dummy_top: &cgroup_dummy_root.top_cgroup
init_cgrp_cset_link.cgrp = cgroup_dummy_top;
// init_cgrp_cset_link.cgrp: &cgroup_dummy_root.top_cgroup
list_add(&init_cgrp_cset_link.cset_link, &cgroup_dummy_top->cset_links);
// list_add에서 한일:
// list의 HEAD인 &cgroup_dummy_top->cset_links에 &init_cgrp_cset_link.cset_link 추가
//
// (&cgroup_dummy_top->cset_links)->prev: &init_cgrp_cset_link.cset_link
// (&init_cgrp_cset_link.cset_link)->next: &cgroup_dummy_top->cset_links
// (&init_cgrp_cset_link.cset_link)->prev: &cgroup_dummy_top->cset_links
// (&cgroup_dummy_top->cset_links)->next: &init_cgrp_cset_link.cset_link
list_add(&init_cgrp_cset_link.cgrp_link, &init_css_set.cgrp_links);
// list_add에서 한일:
// list의 HEAD인 &init_css_set.cgrp_links에 &init_cgrp_cset_link.cgrp_link 추가
//
// (&init_css_set.cgrp_links)->prev: &init_cgrp_cset_link.cgrp_link
// (&init_cgrp_cset_link.cgrp_link)->next: &init_css_set.cgrp_links
// (&init_cgrp_cset_link.cgrp_link)->prev: &init_css_set.cgrp_links
// (&init_css_set.cgrp_links)->next: &init_cgrp_cset_link.cgrp_link
// 2015/08/15 종료
// 2015/08/22 시작
/* at bootup time, we don't worry about modular subsystems */
for_each_builtin_subsys(ss, i) {
BUG_ON(!ss->name);
BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
BUG_ON(!ss->css_alloc);
BUG_ON(!ss->css_free);
if (ss->subsys_id != i) {
printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
ss->name, ss->subsys_id);
BUG();
}
if (ss->early_init)
cgroup_init_subsys(ss);
}
return 0;
}
- for_each_builtin_subsys() 를 풀면.
#define for_each_builtin_subsys(ss, i) \
for ((i) = 0; (i) < CGROUP_BUILTIN_SUBSYS_COUNT && \
(((ss) = cgroup_subsys[i]) || true); (i)++)
- 여기서 CGROUP_BUILTIN_SUBSYS_COUNT 를 다시 풀어보자.
#define SUBSYS(_x) _x ## _subsys_id,
enum cgroup_subsys_id {
#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
#include <linux/cgroup_subsys.h>
#undef IS_SUBSYS_ENABLED
CGROUP_BUILTIN_SUBSYS_COUNT,
__CGROUP_SUBSYS_TEMP_PLACEHOLDER = CGROUP_BUILTIN_SUBSYS_COUNT - 1,
#define IS_SUBSYS_ENABLED(option) IS_MODULE(option)
#include <linux/cgroup_subsys.h>
#undef IS_SUBSYS_ENABLED
CGROUP_SUBSYS_COUNT,
};
#undef SUBSYS
- IS_ENABLED()
- IS_ENABLED()와 IS_BUILDIN()으로 모듈로 사용할지, SUBSYS로 사용할지 Config로 설정
- kernel 모률이 되면 메모리가 덜 소비되므로 커널이 사용할 시스템 메모리에 관련된다.
#define IS_BUILTIN(option) config_enabled(option)
#define config_enabled(cfg) _config_enabled(cfg)
#define _config_enabled(value) __config_enabled(__ARG_PLACEHOLDER_##value)
#define __config_enabled(arg1_or_junk) ___config_enabled(arg1_or_junk 1, 0)
#define ___config_enabled(__ignored, val, ...) val
- SUBSYS()가 config에 의해서 매크로를 거치고 나면
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEBUG)
SUBSYS(debug)
endif
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_SCHED)
SUBSYS(cpu_cgroup)
endif
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_CPUACCT)
SUBSYS(cpuacct)
endif
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_FREEZER)
SUBSYS(freezer)
endif
cgroup를 지원하는 서브 시스템
cpuset — 이 서브시스템은 개별 CPU (멀티코어 시스템에서) 및 메모리 노드를 cgroup의 작업에 할당합니다. debug - cpu_cgroup - cpu — 이 서브시스템은 CPU에 cgroup 작업 액세스를 제공하기 위해 스케줄러를 사용합니다. cpuacct — 이 하위 시스템은 cgroup의 작업에 사용된 CPU 자원에 대한 보고서를 자동으로 생성합니다. mem_cgroup memory — 이 서브시스템은 cgroup의 작업에서 사용되는 메모리에 대한 제한을 설정하고 이러한 작업에서 사용되는 메모리 자원에 대한 보고서를 자동으로 생성합니다. devices — 이 서브시스템은 cgroup의 작업 단위로 장치에 대한 액세스를 허용하거나 거부합니다. freezer — 이 서브시스템은 cgroup의 작업을 일시 중지하거나 다시 시작합니다. net_cls — 이 서브시스템은 Linux 트래픽 컨트롤러 (tc)가 특정 cgroup 작업에서 발생하는 패킷을 식별하게 하는 클래식 식별자 (classid)를 사용하여 네트워크 패킷에 태그를 지정합니다. blkio — 이 서브시스템은 물리 드라이브 (예: 디스크, 솔리드 스테이트, USB 등)와 같은 블록 장치에 대한 입력/출력 액세스에 제한을 설정합니다. perf ns — namespace 서브시스템 net_prio hugetlb
cgruop.c::
for_each_builtin_subsys(ss, i) {
BUG_ON(!ss->name);
BUG_ON(strlen(ss->name) > MAX_CGROUP_TYPE_NAMELEN);
BUG_ON(!ss->css_alloc);
BUG_ON(!ss->css_free);
if (ss->subsys_id != i) {
printk(KERN_ERR "cgroup: Subsys %s id == %d\n",
ss->name, ss->subsys_id);
BUG();
}
if (ss->early_init)
cgroup_init_subsys(ss);
}
return 0;
}
- #define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option) 에 의해서 다시 매크로가 풀린다.
#define SUBSYS(_x) extern struct cgroup_subsys _x ## _subsys;
#define IS_SUBSYS_ENABLED(option) IS_BUILTIN(option)
#define SUBSYS(_x) [_x ## _subsys_id] = &_x ## _subsys,
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_DEBUG)
SUBSYS(debug)
endif
SUBSYS(debug) [debug_subsys_id] = &debug_subsys_id,
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_SCHED)
SUBSYS(cpu_cgroup)
endif
SUBSYS(cpu_cgroup) [cpu_cgroup_subsys_id] = &cpu_cgroup_subsys_id,
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_CPUACCT)
SUBSYS(cpuacct)
endif
SUBSYS(cpuacct) [cpuacct_subsys_id] = &cpuacct_subsys_id,
if IS_SUBSYS_ENABLED(CONFIG_CGROUP_FREEZER)
SUBSYS(freezer)
endif
SUBSYS(freezer) [freezer] = &freezer_subsys_id,
다시 소스 코드를 매크로 풀린 상태로 정리하면.
for ((i) = 0; (i) < CGROUP_BUILTIN_SUBSYS_COUNT && \
(((ss) = cgroup_subsys[i]) || true); (i)++)
- [0] debug_subsys
struct cgroup_subsys debug_subsys = {
.name = "debug",
.css_alloc = debug_css_alloc,
.css_free = debug_css_free,
.subsys_id = debug_subsys_id,
.base_cftypes = debug_files,
};
- [1] cpu_cgroup_subsys
struct cgroup_subsys cpu_cgroup_subsys = {
.name = "cpu",
.css_alloc = cpu_cgroup_css_alloc,
.css_free = cpu_cgroup_css_free,
.css_online = cpu_cgroup_css_online,
.css_offline = cpu_cgroup_css_offline,
.can_attach = cpu_cgroup_can_attach,
.attach = cpu_cgroup_attach,
.exit = cpu_cgroup_exit,
.subsys_id = cpu_cgroup_subsys_id,
.base_cftypes = cpu_files,
.early_init = 1,
};
- [2] cpuacct_subsys
struct cgroup_subsys cpuacct_subsys = {
.name = "cpuacct",
.css_alloc = cpuacct_css_alloc,
.css_free = cpuacct_css_free,
.subsys_id = cpuacct_subsys_id,
.base_cftypes = files,
.early_init = 1,
};
- [3] freezer_subsys
struct cgroup_subsys freezer_subsys = {
.name = "freezer",
.css_alloc = freezer_css_alloc,
.css_online = freezer_css_online,
.css_offline = freezer_css_offline,
.css_free = freezer_css_free,
.subsys_id = freezer_subsys_id,
.attach = freezer_attach,
.fork = freezer_fork,
.base_cftypes = files,
};
if (ss->early_init)
cgroup_init_subsys(ss);
에서 cgroup_init_subsys() 호출
cgroup.c::cgroup_init_subsys()
- start_kernel()-> ->cgroup_init_subsys()
static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
{
struct cgroup_subsys_state *css;
printk(KERN_INFO "Initializing cgroup subsys %s\n", ss->name);
mutex_lock(&cgroup_mutex);
- mutex_lock(&cgroup_mutex); -
static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
{
...
mutex_lock(&cgroup_mutex);
/* init base cftset */
cgroup_init_cftsets(ss);
cgroup.c::cgroup_init_cftsets()
static void __init_or_module cgroup_init_cftsets(struct cgroup_subsys *ss)
{
INIT_LIST_HEAD(&ss->cftsets);
/*
* base_cftset is embedded in subsys itself, no need to worry about
* deregistration.
*/
if (ss->base_cftypes) {
struct cftype *cft;
for (cft = ss->base_cftypes; cft->name[0] != '\0'; cft++)
cft->ss = ss;
ss->base_cftset.cfts = ss->base_cftypes;
list_add_tail(&ss->base_cftset.node, &ss->cftsets);
}
}
- [0]
- [1]
- [2]
cgroup.c::cgroup_init_subsys()
- retrun: c
static void __init cgroup_init_subsys(struct cgroup_subsys *ss)
{
...
/* init base cftset */
cgroup_init_cftsets(ss);
/* Create the top cgroup state for this subsystem */
list_add(&ss->sibling, &cgroup_dummy_root.subsys_list);
ss->root = &cgroup_dummy_root;
css = ss->css_alloc(cgroup_css(cgroup_dummy_top, ss));
/* We don't handle early failures gracefully */
BUG_ON(IS_ERR(css));
init_css(css, ss, cgroup_dummy_top);
cgroup.c::css_alloc()
static struct cgroup_subsys_state *
cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
{
struct task_group *parent = css_tg(parent_css);
struct task_group *tg;
if (!parent) {
/* This is early initialization for the top cgroup */
return &root_task_group.css;
}
tg = sched_create_group(parent);
if (IS_ERR(tg))
return ERR_PTR(-ENOMEM);
return &tg->css;
}
cgroup.c::cgroup_init_subsys()
/* Update the init_css_set to contain a subsys
* pointer to this state - since the subsystem is
* newly registered, all tasks and hence the
* init_css_set is in the subsystem's top cgroup. */
init_css_set.subsys[ss->subsys_id] = css;
need_forkexit_callback |= ss->fork || ss->exit;
/* At system boot, before all subsystems have been
* registered, no tasks have been forked, so we don't
* need to invoke fork callbacks here. */
BUG_ON(!list_empty(&init_task.tasks));
BUG_ON(online_css(css));
mutex_unlock(&cgroup_mutex);
/* this function shouldn't be used with modular subsystems, since they
* need to register a subsys_id, among other things */
BUG_ON(ss->module);
}
log
- log
2b35e70..d5933b6 master -> origin/master
Updating 2b35e70..d5933b6
Fast-forward
include/linux/cgroup.h | 30 ++++
include/linux/cgroup_subsys.h | 40 +++--
include/linux/debugobjects.h | 3 +-
include/linux/err.h | 5 +
include/linux/kconfig.h | 18 ++
include/linux/kernel.h | 1 +
include/linux/kmemleak.h | 1 +
include/linux/list.h | 13 ++
include/linux/lockdep.h | 4 +
include/linux/mutex.h | 20 +++
include/linux/page_cgroup.h | 1 +
include/linux/rcupdate.h | 17 ++
include/linux/sched.h | 4 +-
init/main.c | 10 +-
kernel/cgroup.c | 385 +++++++++++++++++++++++++++++++++++++++++-
kernel/cgroup_freezer.c | 1 +
kernel/locking/lockdep.c | 2 +
kernel/locking/mutex.c | 6 +-
kernel/sched/core.c | 39 ++++-
kernel/sched/cpuacct.c | 8 +
kernel/sched/sched.h | 9 +-
21 files changed, 584 insertions(+), 33 deletions(-)