1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef _LINUX_MM_PAGE_IDLE_H
3#define _LINUX_MM_PAGE_IDLE_H
4
5#include <linux/bitops.h>
6#include <linux/page-flags.h>
7#include <linux/page_ext.h>
8
9#ifdef CONFIG_PAGE_IDLE_FLAG
10
11#ifndef CONFIG_64BIT
12/*
13 * If there is not enough space to store Idle and Young bits in page flags, use
14 * page ext flags instead.
15 */
16static inline bool folio_test_young(struct folio *folio)
17{
18	struct page_ext *page_ext = page_ext_get(&folio->page);
19	bool page_young;
20
21	if (unlikely(!page_ext))
22		return false;
23
24	page_young = test_bit(PAGE_EXT_YOUNG, &page_ext->flags);
25	page_ext_put(page_ext);
26
27	return page_young;
28}
29
30static inline void folio_set_young(struct folio *folio)
31{
32	struct page_ext *page_ext = page_ext_get(&folio->page);
33
34	if (unlikely(!page_ext))
35		return;
36
37	set_bit(PAGE_EXT_YOUNG, &page_ext->flags);
38	page_ext_put(page_ext);
39}
40
41static inline bool folio_test_clear_young(struct folio *folio)
42{
43	struct page_ext *page_ext = page_ext_get(&folio->page);
44	bool page_young;
45
46	if (unlikely(!page_ext))
47		return false;
48
49	page_young = test_and_clear_bit(PAGE_EXT_YOUNG, &page_ext->flags);
50	page_ext_put(page_ext);
51
52	return page_young;
53}
54
55static inline bool folio_test_idle(struct folio *folio)
56{
57	struct page_ext *page_ext = page_ext_get(&folio->page);
58	bool page_idle;
59
60	if (unlikely(!page_ext))
61		return false;
62
63	page_idle =  test_bit(PAGE_EXT_IDLE, &page_ext->flags);
64	page_ext_put(page_ext);
65
66	return page_idle;
67}
68
69static inline void folio_set_idle(struct folio *folio)
70{
71	struct page_ext *page_ext = page_ext_get(&folio->page);
72
73	if (unlikely(!page_ext))
74		return;
75
76	set_bit(PAGE_EXT_IDLE, &page_ext->flags);
77	page_ext_put(page_ext);
78}
79
80static inline void folio_clear_idle(struct folio *folio)
81{
82	struct page_ext *page_ext = page_ext_get(&folio->page);
83
84	if (unlikely(!page_ext))
85		return;
86
87	clear_bit(PAGE_EXT_IDLE, &page_ext->flags);
88	page_ext_put(page_ext);
89}
90#endif /* !CONFIG_64BIT */
91
92#else /* !CONFIG_PAGE_IDLE_FLAG */
93
94static inline bool folio_test_young(struct folio *folio)
95{
96	return false;
97}
98
99static inline void folio_set_young(struct folio *folio)
100{
101}
102
103static inline bool folio_test_clear_young(struct folio *folio)
104{
105	return false;
106}
107
108static inline bool folio_test_idle(struct folio *folio)
109{
110	return false;
111}
112
113static inline void folio_set_idle(struct folio *folio)
114{
115}
116
117static inline void folio_clear_idle(struct folio *folio)
118{
119}
120
121#endif /* CONFIG_PAGE_IDLE_FLAG */
122
123static inline bool page_is_young(struct page *page)
124{
125	return folio_test_young(page_folio(page));
126}
127
128static inline void set_page_young(struct page *page)
129{
130	folio_set_young(page_folio(page));
131}
132
133static inline bool test_and_clear_page_young(struct page *page)
134{
135	return folio_test_clear_young(page_folio(page));
136}
137
138static inline bool page_is_idle(struct page *page)
139{
140	return folio_test_idle(page_folio(page));
141}
142
143static inline void set_page_idle(struct page *page)
144{
145	folio_set_idle(page_folio(page));
146}
147#endif /* _LINUX_MM_PAGE_IDLE_H */
148