+static void
+set_flags_of_children(ckrm_mem_res_t *parres, unsigned int flag)
+{
+ ckrm_mem_res_t *childres;
+ ckrm_core_class_t *child = NULL;
+
+ parres->reclaim_flags |= flag;
+ ckrm_lock_hier(parres->core);
+ while ((child = ckrm_get_next_child(parres->core, child)) != NULL) {
+ childres = ckrm_get_res_class(child, mem_rcbs.resid,
+ ckrm_mem_res_t);
+ set_flags_of_children(childres, flag);
+ }
+ ckrm_unlock_hier(parres->core);
+ return;
+}
+
+// FIXME: more attention is needed to this function
+static unsigned int
+set_usage_flags(ckrm_mem_res_t *res)
+{
+ int tot_usage, cls_usage, range, guar;
+
+ if (res->pg_limit == CKRM_SHARE_DONTCARE) {
+ // No limit is set for the class. don't bother it
+ res->reclaim_flags = 0;
+ return res->reclaim_flags;
+ }
+
+ tot_usage = atomic_read(&res->pg_total);
+ cls_usage = tot_usage - res->pg_lent;
+ guar = (res->pg_guar > 0) ? res->pg_guar : 0;
+ range = res->pg_limit - guar;
+
+ if ((tot_usage > (guar + ((110 * range) / 100))) &&
+ (res->pg_lent > (guar + ((25 * range) / 100)))) {
+ set_flags_of_children(res, CLS_PARENT_OVER);
+ }
+
+ if (cls_usage > (guar + ((110 * range) / 100))) {
+ res->reclaim_flags |= CLS_OVER_110;
+ } else if (cls_usage > (guar + range)) {
+ res->reclaim_flags |= CLS_OVER_100;
+ } else if (cls_usage > (guar + ((3 * range) / 4))) {
+ res->reclaim_flags |= CLS_OVER_75;
+ } else if (cls_usage > (guar + (range / 2))) {
+ res->reclaim_flags |= CLS_OVER_50;
+ } else if (cls_usage > (guar + (range / 4))) {
+ res->reclaim_flags |= CLS_OVER_25;
+ } else if (cls_usage > guar) {
+ res->reclaim_flags |= CLS_OVER_GUAR;
+ } else {
+ res->reclaim_flags = 0;
+ }
+ return res->reclaim_flags;
+}
+
+/*
+ * The functions ckrm_setup_reclamation(), ckrm_teardown_reclamation(),
+ * ckrm_get_reclaim_bits() and the macro ckrm_kick_page() along with the
+ * macros CLS_* define how the pages are reclaimed.
+ * Keeping this logic thru these interface eliminate the necessity to
+ * change the reclaimation code in VM if we want to change the logic.
+ */
+unsigned int
+ckrm_setup_reclamation(void)
+{
+ ckrm_mem_res_t *res;
+ unsigned int ret = 0;
+
+ spin_lock(&ckrm_mem_lock);
+ set_ckrm_tot_pages();
+ ckrm_mem_root_class->pg_guar = ckrm_tot_lru_pages;
+ ckrm_mem_root_class->pg_unused = ckrm_tot_lru_pages;
+ ckrm_mem_root_class->pg_limit = ckrm_tot_lru_pages;
+ recalc_and_propagate(ckrm_mem_root_class, NULL);
+ list_for_each_entry(res, &ckrm_memclass_list, mcls_list) {
+ ret |= set_usage_flags(res);
+ }
+ spin_unlock(&ckrm_mem_lock);
+ return ret;
+}
+
+void
+ckrm_teardown_reclamation(void)
+{
+ ckrm_mem_res_t *res;
+ spin_lock(&ckrm_mem_lock);
+ list_for_each_entry(res, &ckrm_memclass_list, mcls_list) {
+ res->reclaim_flags = 0;
+ }
+ spin_unlock(&ckrm_mem_lock);
+}
+
+void
+ckrm_get_reclaim_bits(unsigned int *flags, unsigned int *extract)