Skip to content

Latest commit

 

History

History
558 lines (446 loc) · 17.4 KB

a10c_115.md

File metadata and controls

558 lines (446 loc) · 17.4 KB
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);

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(-)