162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/* delayacct.h - per-task delay accounting
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Copyright (C) Shailabh Nagar, IBM Corp. 2006
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef _LINUX_DELAYACCT_H
862306a36Sopenharmony_ci#define _LINUX_DELAYACCT_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <uapi/linux/taskstats.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci#ifdef CONFIG_TASK_DELAY_ACCT
1362306a36Sopenharmony_cistruct task_delay_info {
1462306a36Sopenharmony_ci	raw_spinlock_t	lock;
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	/* For each stat XXX, add following, aligned appropriately
1762306a36Sopenharmony_ci	 *
1862306a36Sopenharmony_ci	 * struct timespec XXX_start, XXX_end;
1962306a36Sopenharmony_ci	 * u64 XXX_delay;
2062306a36Sopenharmony_ci	 * u32 XXX_count;
2162306a36Sopenharmony_ci	 *
2262306a36Sopenharmony_ci	 * Atomicity of updates to XXX_delay, XXX_count protected by
2362306a36Sopenharmony_ci	 * single lock above (split into XXX_lock if contention is an issue).
2462306a36Sopenharmony_ci	 */
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	/*
2762306a36Sopenharmony_ci	 * XXX_count is incremented on every XXX operation, the delay
2862306a36Sopenharmony_ci	 * associated with the operation is added to XXX_delay.
2962306a36Sopenharmony_ci	 * XXX_delay contains the accumulated delay time in nanoseconds.
3062306a36Sopenharmony_ci	 */
3162306a36Sopenharmony_ci	u64 blkio_start;
3262306a36Sopenharmony_ci	u64 blkio_delay;	/* wait for sync block io completion */
3362306a36Sopenharmony_ci	u64 swapin_start;
3462306a36Sopenharmony_ci	u64 swapin_delay;	/* wait for swapin */
3562306a36Sopenharmony_ci	u32 blkio_count;	/* total count of the number of sync block */
3662306a36Sopenharmony_ci				/* io operations performed */
3762306a36Sopenharmony_ci	u32 swapin_count;	/* total count of swapin */
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci	u64 freepages_start;
4062306a36Sopenharmony_ci	u64 freepages_delay;	/* wait for memory reclaim */
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	u64 thrashing_start;
4362306a36Sopenharmony_ci	u64 thrashing_delay;	/* wait for thrashing page */
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	u64 compact_start;
4662306a36Sopenharmony_ci	u64 compact_delay;	/* wait for memory compact */
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	u64 wpcopy_start;
4962306a36Sopenharmony_ci	u64 wpcopy_delay;	/* wait for write-protect copy */
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci	u64 irq_delay;	/* wait for IRQ/SOFTIRQ */
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	u32 freepages_count;	/* total count of memory reclaim */
5462306a36Sopenharmony_ci	u32 thrashing_count;	/* total count of thrash waits */
5562306a36Sopenharmony_ci	u32 compact_count;	/* total count of memory compact */
5662306a36Sopenharmony_ci	u32 wpcopy_count;	/* total count of write-protect copy */
5762306a36Sopenharmony_ci	u32 irq_count;	/* total count of IRQ/SOFTIRQ */
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci#endif
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci#include <linux/sched.h>
6262306a36Sopenharmony_ci#include <linux/slab.h>
6362306a36Sopenharmony_ci#include <linux/jump_label.h>
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci#ifdef CONFIG_TASK_DELAY_ACCT
6662306a36Sopenharmony_ciDECLARE_STATIC_KEY_FALSE(delayacct_key);
6762306a36Sopenharmony_ciextern int delayacct_on;	/* Delay accounting turned on/off */
6862306a36Sopenharmony_ciextern struct kmem_cache *delayacct_cache;
6962306a36Sopenharmony_ciextern void delayacct_init(void);
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ciextern void __delayacct_tsk_init(struct task_struct *);
7262306a36Sopenharmony_ciextern void __delayacct_tsk_exit(struct task_struct *);
7362306a36Sopenharmony_ciextern void __delayacct_blkio_start(void);
7462306a36Sopenharmony_ciextern void __delayacct_blkio_end(struct task_struct *);
7562306a36Sopenharmony_ciextern int delayacct_add_tsk(struct taskstats *, struct task_struct *);
7662306a36Sopenharmony_ciextern __u64 __delayacct_blkio_ticks(struct task_struct *);
7762306a36Sopenharmony_ciextern void __delayacct_freepages_start(void);
7862306a36Sopenharmony_ciextern void __delayacct_freepages_end(void);
7962306a36Sopenharmony_ciextern void __delayacct_thrashing_start(bool *in_thrashing);
8062306a36Sopenharmony_ciextern void __delayacct_thrashing_end(bool *in_thrashing);
8162306a36Sopenharmony_ciextern void __delayacct_swapin_start(void);
8262306a36Sopenharmony_ciextern void __delayacct_swapin_end(void);
8362306a36Sopenharmony_ciextern void __delayacct_compact_start(void);
8462306a36Sopenharmony_ciextern void __delayacct_compact_end(void);
8562306a36Sopenharmony_ciextern void __delayacct_wpcopy_start(void);
8662306a36Sopenharmony_ciextern void __delayacct_wpcopy_end(void);
8762306a36Sopenharmony_ciextern void __delayacct_irq(struct task_struct *task, u32 delta);
8862306a36Sopenharmony_ci
8962306a36Sopenharmony_cistatic inline void delayacct_tsk_init(struct task_struct *tsk)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	/* reinitialize in case parent's non-null pointer was dup'ed*/
9262306a36Sopenharmony_ci	tsk->delays = NULL;
9362306a36Sopenharmony_ci	if (delayacct_on)
9462306a36Sopenharmony_ci		__delayacct_tsk_init(tsk);
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/* Free tsk->delays. Called from bad fork and __put_task_struct
9862306a36Sopenharmony_ci * where there's no risk of tsk->delays being accessed elsewhere
9962306a36Sopenharmony_ci */
10062306a36Sopenharmony_cistatic inline void delayacct_tsk_free(struct task_struct *tsk)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	if (tsk->delays)
10362306a36Sopenharmony_ci		kmem_cache_free(delayacct_cache, tsk->delays);
10462306a36Sopenharmony_ci	tsk->delays = NULL;
10562306a36Sopenharmony_ci}
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_cistatic inline void delayacct_blkio_start(void)
10862306a36Sopenharmony_ci{
10962306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
11062306a36Sopenharmony_ci		return;
11162306a36Sopenharmony_ci
11262306a36Sopenharmony_ci	if (current->delays)
11362306a36Sopenharmony_ci		__delayacct_blkio_start();
11462306a36Sopenharmony_ci}
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_cistatic inline void delayacct_blkio_end(struct task_struct *p)
11762306a36Sopenharmony_ci{
11862306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
11962306a36Sopenharmony_ci		return;
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	if (p->delays)
12262306a36Sopenharmony_ci		__delayacct_blkio_end(p);
12362306a36Sopenharmony_ci}
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_cistatic inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
12662306a36Sopenharmony_ci{
12762306a36Sopenharmony_ci	if (tsk->delays)
12862306a36Sopenharmony_ci		return __delayacct_blkio_ticks(tsk);
12962306a36Sopenharmony_ci	return 0;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic inline void delayacct_freepages_start(void)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
13562306a36Sopenharmony_ci		return;
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci	if (current->delays)
13862306a36Sopenharmony_ci		__delayacct_freepages_start();
13962306a36Sopenharmony_ci}
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_cistatic inline void delayacct_freepages_end(void)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
14462306a36Sopenharmony_ci		return;
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci	if (current->delays)
14762306a36Sopenharmony_ci		__delayacct_freepages_end();
14862306a36Sopenharmony_ci}
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_cistatic inline void delayacct_thrashing_start(bool *in_thrashing)
15162306a36Sopenharmony_ci{
15262306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
15362306a36Sopenharmony_ci		return;
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	if (current->delays)
15662306a36Sopenharmony_ci		__delayacct_thrashing_start(in_thrashing);
15762306a36Sopenharmony_ci}
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_cistatic inline void delayacct_thrashing_end(bool *in_thrashing)
16062306a36Sopenharmony_ci{
16162306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
16262306a36Sopenharmony_ci		return;
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	if (current->delays)
16562306a36Sopenharmony_ci		__delayacct_thrashing_end(in_thrashing);
16662306a36Sopenharmony_ci}
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_cistatic inline void delayacct_swapin_start(void)
16962306a36Sopenharmony_ci{
17062306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
17162306a36Sopenharmony_ci		return;
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	if (current->delays)
17462306a36Sopenharmony_ci		__delayacct_swapin_start();
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic inline void delayacct_swapin_end(void)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
18062306a36Sopenharmony_ci		return;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	if (current->delays)
18362306a36Sopenharmony_ci		__delayacct_swapin_end();
18462306a36Sopenharmony_ci}
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_cistatic inline void delayacct_compact_start(void)
18762306a36Sopenharmony_ci{
18862306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
18962306a36Sopenharmony_ci		return;
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	if (current->delays)
19262306a36Sopenharmony_ci		__delayacct_compact_start();
19362306a36Sopenharmony_ci}
19462306a36Sopenharmony_ci
19562306a36Sopenharmony_cistatic inline void delayacct_compact_end(void)
19662306a36Sopenharmony_ci{
19762306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
19862306a36Sopenharmony_ci		return;
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	if (current->delays)
20162306a36Sopenharmony_ci		__delayacct_compact_end();
20262306a36Sopenharmony_ci}
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_cistatic inline void delayacct_wpcopy_start(void)
20562306a36Sopenharmony_ci{
20662306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
20762306a36Sopenharmony_ci		return;
20862306a36Sopenharmony_ci
20962306a36Sopenharmony_ci	if (current->delays)
21062306a36Sopenharmony_ci		__delayacct_wpcopy_start();
21162306a36Sopenharmony_ci}
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_cistatic inline void delayacct_wpcopy_end(void)
21462306a36Sopenharmony_ci{
21562306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
21662306a36Sopenharmony_ci		return;
21762306a36Sopenharmony_ci
21862306a36Sopenharmony_ci	if (current->delays)
21962306a36Sopenharmony_ci		__delayacct_wpcopy_end();
22062306a36Sopenharmony_ci}
22162306a36Sopenharmony_ci
22262306a36Sopenharmony_cistatic inline void delayacct_irq(struct task_struct *task, u32 delta)
22362306a36Sopenharmony_ci{
22462306a36Sopenharmony_ci	if (!static_branch_unlikely(&delayacct_key))
22562306a36Sopenharmony_ci		return;
22662306a36Sopenharmony_ci
22762306a36Sopenharmony_ci	if (task->delays)
22862306a36Sopenharmony_ci		__delayacct_irq(task, delta);
22962306a36Sopenharmony_ci}
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci#else
23262306a36Sopenharmony_cistatic inline void delayacct_init(void)
23362306a36Sopenharmony_ci{}
23462306a36Sopenharmony_cistatic inline void delayacct_tsk_init(struct task_struct *tsk)
23562306a36Sopenharmony_ci{}
23662306a36Sopenharmony_cistatic inline void delayacct_tsk_free(struct task_struct *tsk)
23762306a36Sopenharmony_ci{}
23862306a36Sopenharmony_cistatic inline void delayacct_blkio_start(void)
23962306a36Sopenharmony_ci{}
24062306a36Sopenharmony_cistatic inline void delayacct_blkio_end(struct task_struct *p)
24162306a36Sopenharmony_ci{}
24262306a36Sopenharmony_cistatic inline int delayacct_add_tsk(struct taskstats *d,
24362306a36Sopenharmony_ci					struct task_struct *tsk)
24462306a36Sopenharmony_ci{ return 0; }
24562306a36Sopenharmony_cistatic inline __u64 delayacct_blkio_ticks(struct task_struct *tsk)
24662306a36Sopenharmony_ci{ return 0; }
24762306a36Sopenharmony_cistatic inline int delayacct_is_task_waiting_on_io(struct task_struct *p)
24862306a36Sopenharmony_ci{ return 0; }
24962306a36Sopenharmony_cistatic inline void delayacct_freepages_start(void)
25062306a36Sopenharmony_ci{}
25162306a36Sopenharmony_cistatic inline void delayacct_freepages_end(void)
25262306a36Sopenharmony_ci{}
25362306a36Sopenharmony_cistatic inline void delayacct_thrashing_start(bool *in_thrashing)
25462306a36Sopenharmony_ci{}
25562306a36Sopenharmony_cistatic inline void delayacct_thrashing_end(bool *in_thrashing)
25662306a36Sopenharmony_ci{}
25762306a36Sopenharmony_cistatic inline void delayacct_swapin_start(void)
25862306a36Sopenharmony_ci{}
25962306a36Sopenharmony_cistatic inline void delayacct_swapin_end(void)
26062306a36Sopenharmony_ci{}
26162306a36Sopenharmony_cistatic inline void delayacct_compact_start(void)
26262306a36Sopenharmony_ci{}
26362306a36Sopenharmony_cistatic inline void delayacct_compact_end(void)
26462306a36Sopenharmony_ci{}
26562306a36Sopenharmony_cistatic inline void delayacct_wpcopy_start(void)
26662306a36Sopenharmony_ci{}
26762306a36Sopenharmony_cistatic inline void delayacct_wpcopy_end(void)
26862306a36Sopenharmony_ci{}
26962306a36Sopenharmony_cistatic inline void delayacct_irq(struct task_struct *task, u32 delta)
27062306a36Sopenharmony_ci{}
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci#endif /* CONFIG_TASK_DELAY_ACCT */
27362306a36Sopenharmony_ci
27462306a36Sopenharmony_ci#endif
275