kernel/cgroup/rstat.c

Source file repositories/reference/linux-study-clean/kernel/cgroup/rstat.c

File Facts

System
Linux kernel
Corpus path
kernel/cgroup/rstat.c
Extension
.c
Size
22124 bytes
Lines
772
Domain
Core OS
Bucket
Scheduler, Processes, Timers, Sync, And Syscalls
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (!parent) {
			rstatc->updated_next = css;
			break;
		}

		prstatc = css_rstat_cpu(parent, cpu);
		rstatc->updated_next = prstatc->updated_children;
		prstatc->updated_children = css;

		css = parent;
	}
}

static void css_process_update_tree(struct cgroup_subsys *ss, int cpu)
{
	struct llist_head *lhead = ss_lhead_cpu(ss, cpu);
	struct llist_node *lnode;

	while ((lnode = llist_del_first_init(lhead))) {
		struct css_rstat_cpu *rstatc;

		/*
		 * smp_mb() is needed here (more specifically in between
		 * init_llist_node() and per-cpu stats flushing) if the
		 * guarantee is required by a rstat user where etiher the
		 * updater should add itself on the lockless list or the
		 * flusher flush the stats updated by the updater who have
		 * observed that they are already on the list. The
		 * corresponding barrier pair for this one should be before
		 * __css_rstat_updated() by the user.
		 *
		 * For now, there aren't any such user, so not adding the
		 * barrier here but if such a use-case arise, please add
		 * smp_mb() here.
		 */

		rstatc = container_of(lnode, struct css_rstat_cpu, lnode);
		__css_process_update_tree(rstatc->owner, cpu);
	}
}

/**
 * css_rstat_push_children - push children css's into the given list
 * @head: current head of the list (= subtree root)
 * @child: first child of the root
 * @cpu: target cpu
 * Return: A new singly linked list of css's to be flushed
 *
 * Iteratively traverse down the css_rstat_cpu updated tree level by
 * level and push all the parents first before their next level children
 * into a singly linked list via the rstat_flush_next pointer built from the
 * tail backward like "pushing" css's into a stack. The root is pushed by
 * the caller.
 */
static struct cgroup_subsys_state *css_rstat_push_children(
		struct cgroup_subsys_state *head,
		struct cgroup_subsys_state *child, int cpu)
{
	struct cgroup_subsys_state *cnext = child;	/* Next head of child css level */
	struct cgroup_subsys_state *ghead = NULL;	/* Head of grandchild css level */
	struct cgroup_subsys_state *parent, *grandchild;
	struct css_rstat_cpu *crstatc;

	child->rstat_flush_next = NULL;

	/*
	 * The subsystem rstat lock must be held for the whole duration from
	 * here as the rstat_flush_next list is being constructed to when
	 * it is consumed later in css_rstat_flush().
	 */
	lockdep_assert_held(ss_rstat_lock(head->ss));

	/*
	 * Notation: -> updated_next pointer
	 *	     => rstat_flush_next pointer
	 *
	 * Assuming the following sample updated_children lists:
	 *  P: C1 -> C2 -> P
	 *  C1: G11 -> G12 -> C1
	 *  C2: G21 -> G22 -> C2
	 *
	 * After 1st iteration:
	 *  head => C2 => C1 => NULL
	 *  ghead => G21 => G11 => NULL
	 *
	 * After 2nd iteration:
	 *  head => G12 => G11 => G22 => G21 => C2 => C1 => NULL
	 */
next_level:
	while (cnext) {

Annotation

Implementation Notes