Lines Matching +full:monitor +full:- +full:interval +full:- +full:ms
1 // SPDX-License-Identifier: GPL-2.0
3 * Data Access Monitor
45 * damon_is_registered_ops() - Check if a given damon_operations is registered.
63 * damon_register_ops() - Register a monitoring operations set to DAMON.
67 * damon_operations->id so that others can find and use them later.
75 if (ops->id >= NR_DAMON_OPS) in damon_register_ops()
76 return -EINVAL; in damon_register_ops()
79 if (__damon_is_registered_ops(ops->id)) { in damon_register_ops()
80 err = -EINVAL; in damon_register_ops()
83 damon_registered_ops[ops->id] = *ops; in damon_register_ops()
90 * damon_select_ops() - Select a monitoring operations to use with the context.
104 return -EINVAL; in damon_select_ops()
108 err = -EINVAL; in damon_select_ops()
110 ctx->ops = damon_registered_ops[id]; in damon_select_ops()
128 region->ar.start = start; in damon_new_region()
129 region->ar.end = end; in damon_new_region()
130 region->nr_accesses = 0; in damon_new_region()
131 INIT_LIST_HEAD(®ion->list); in damon_new_region()
133 region->age = 0; in damon_new_region()
134 region->last_nr_accesses = 0; in damon_new_region()
141 list_add_tail(&r->list, &t->regions_list); in damon_add_region()
142 t->nr_regions++; in damon_add_region()
147 list_del(&r->list); in damon_del_region()
148 t->nr_regions--; in damon_del_region()
170 return !(r->ar.end <= re->start || re->end <= r->ar.start); in damon_intersect()
187 if (r->ar.end != next->ar.start) { in damon_fill_regions_holes()
188 newr = damon_new_region(r->ar.end, next->ar.start); in damon_fill_regions_holes()
190 return -ENOMEM; in damon_fill_regions_holes()
198 * damon_set_regions() - Set regions of a target for given address ranges.
239 if (r->ar.start >= range->end) in damon_set_regions()
245 ALIGN_DOWN(range->start, in damon_set_regions()
247 ALIGN(range->end, DAMON_MIN_REGION)); in damon_set_regions()
249 return -ENOMEM; in damon_set_regions()
253 first->ar.start = ALIGN_DOWN(range->start, in damon_set_regions()
255 last->ar.end = ALIGN(range->end, DAMON_MIN_REGION); in damon_set_regions()
269 quota->total_charged_sz = 0; in damos_quota_init_priv()
270 quota->total_charged_ns = 0; in damos_quota_init_priv()
271 quota->esz = 0; in damos_quota_init_priv()
272 quota->charged_sz = 0; in damos_quota_init_priv()
273 quota->charged_from = 0; in damos_quota_init_priv()
274 quota->charge_target_from = NULL; in damos_quota_init_priv()
275 quota->charge_addr_from = 0; in damos_quota_init_priv()
288 scheme->pattern = *pattern; in damon_new_scheme()
289 scheme->action = action; in damon_new_scheme()
290 scheme->stat = (struct damos_stat){}; in damon_new_scheme()
291 INIT_LIST_HEAD(&scheme->list); in damon_new_scheme()
293 scheme->quota = *(damos_quota_init_priv(quota)); in damon_new_scheme()
295 scheme->wmarks = *wmarks; in damon_new_scheme()
296 scheme->wmarks.activated = true; in damon_new_scheme()
303 list_add_tail(&s->list, &ctx->schemes); in damon_add_scheme()
308 list_del(&s->list); in damon_del_scheme()
335 t->pid = NULL; in damon_new_target()
336 t->nr_regions = 0; in damon_new_target()
337 INIT_LIST_HEAD(&t->regions_list); in damon_new_target()
338 INIT_LIST_HEAD(&t->list); in damon_new_target()
345 list_add_tail(&t->list, &ctx->adaptive_targets); in damon_add_target()
350 return list_empty(&ctx->adaptive_targets); in damon_targets_empty()
355 list_del(&t->list); in damon_del_target()
375 return t->nr_regions; in damon_nr_regions()
386 ctx->attrs.sample_interval = 5 * 1000; in damon_new_ctx()
387 ctx->attrs.aggr_interval = 100 * 1000; in damon_new_ctx()
388 ctx->attrs.ops_update_interval = 60 * 1000 * 1000; in damon_new_ctx()
390 ktime_get_coarse_ts64(&ctx->last_aggregation); in damon_new_ctx()
391 ctx->last_ops_update = ctx->last_aggregation; in damon_new_ctx()
393 mutex_init(&ctx->kdamond_lock); in damon_new_ctx()
395 ctx->attrs.min_nr_regions = 10; in damon_new_ctx()
396 ctx->attrs.max_nr_regions = 1000; in damon_new_ctx()
398 INIT_LIST_HEAD(&ctx->adaptive_targets); in damon_new_ctx()
399 INIT_LIST_HEAD(&ctx->schemes); in damon_new_ctx()
408 if (ctx->ops.cleanup) { in damon_destroy_targets()
409 ctx->ops.cleanup(ctx); in damon_destroy_targets()
430 * damon_set_attrs() - Set attributes for the monitoring.
435 * Every time interval is in micro-seconds.
441 if (attrs->min_nr_regions < 3) in damon_set_attrs()
442 return -EINVAL; in damon_set_attrs()
443 if (attrs->min_nr_regions > attrs->max_nr_regions) in damon_set_attrs()
444 return -EINVAL; in damon_set_attrs()
446 ctx->attrs = *attrs; in damon_set_attrs()
451 * damon_set_schemes() - Set data access monitoring based operation schemes.
472 * damon_nr_running_ctxs() - Return number of currently running contexts.
497 if (ctx->attrs.min_nr_regions) in damon_region_sz_limit()
498 sz /= ctx->attrs.min_nr_regions; in damon_region_sz_limit()
508 * __damon_start() - Starts monitoring with given context.
517 int err = -EBUSY; in __damon_start()
519 mutex_lock(&ctx->kdamond_lock); in __damon_start()
520 if (!ctx->kdamond) { in __damon_start()
522 ctx->kdamond = kthread_run(kdamond_fn, ctx, "kdamond.%d", in __damon_start()
524 if (IS_ERR(ctx->kdamond)) { in __damon_start()
525 err = PTR_ERR(ctx->kdamond); in __damon_start()
526 ctx->kdamond = NULL; in __damon_start()
529 mutex_unlock(&ctx->kdamond_lock); in __damon_start()
535 * damon_start() - Starts the monitorings for a given group of contexts.
545 * returns -EBUSY.
558 return -EBUSY; in damon_start()
575 * __damon_stop() - Stops monitoring of a given context.
584 mutex_lock(&ctx->kdamond_lock); in __damon_stop()
585 tsk = ctx->kdamond; in __damon_stop()
588 mutex_unlock(&ctx->kdamond_lock); in __damon_stop()
593 mutex_unlock(&ctx->kdamond_lock); in __damon_stop()
595 return -EPERM; in __damon_stop()
599 * damon_stop() - Stops the monitorings for a given group of contexts.
619 * damon_check_reset_time_interval() - Check if a time interval is elapsed.
620 * @baseline: the time to check whether the interval has elapsed since
621 * @interval: the time interval (microseconds)
623 * See whether the given time interval has passed since the given baseline
626 * Return: true if the time interval has passed, or false otherwise.
629 unsigned long interval) in damon_check_reset_time_interval() argument
634 if ((timespec64_to_ns(&now) - timespec64_to_ns(baseline)) < in damon_check_reset_time_interval()
635 interval * 1000) in damon_check_reset_time_interval()
646 return damon_check_reset_time_interval(&ctx->last_aggregation, in kdamond_aggregate_interval_passed()
647 ctx->attrs.aggr_interval); in kdamond_aggregate_interval_passed()
663 r->last_nr_accesses = r->nr_accesses; in kdamond_reset_aggregated()
664 r->nr_accesses = 0; in kdamond_reset_aggregated()
678 return s->pattern.min_sz_region <= sz && in __damos_valid_target()
679 sz <= s->pattern.max_sz_region && in __damos_valid_target()
680 s->pattern.min_nr_accesses <= r->nr_accesses && in __damos_valid_target()
681 r->nr_accesses <= s->pattern.max_nr_accesses && in __damos_valid_target()
682 s->pattern.min_age_region <= r->age && in __damos_valid_target()
683 r->age <= s->pattern.max_age_region; in __damos_valid_target()
691 if (!ret || !s->quota.esz || !c->ops.get_scheme_score) in damos_valid_target()
694 return c->ops.get_scheme_score(c, t, r, s) >= s->quota.min_score; in damos_valid_target()
704 struct damos_quota *quota = &s->quota; in damon_do_apply_schemes()
709 if (!s->wmarks.activated) in damon_do_apply_schemes()
713 if (quota->esz && quota->charged_sz >= quota->esz) in damon_do_apply_schemes()
717 if (quota->charge_target_from) { in damon_do_apply_schemes()
718 if (t != quota->charge_target_from) in damon_do_apply_schemes()
721 quota->charge_target_from = NULL; in damon_do_apply_schemes()
722 quota->charge_addr_from = 0; in damon_do_apply_schemes()
725 if (quota->charge_addr_from && in damon_do_apply_schemes()
726 r->ar.end <= quota->charge_addr_from) in damon_do_apply_schemes()
729 if (quota->charge_addr_from && r->ar.start < in damon_do_apply_schemes()
730 quota->charge_addr_from) { in damon_do_apply_schemes()
731 sz = ALIGN_DOWN(quota->charge_addr_from - in damon_do_apply_schemes()
732 r->ar.start, DAMON_MIN_REGION); in damon_do_apply_schemes()
743 quota->charge_target_from = NULL; in damon_do_apply_schemes()
744 quota->charge_addr_from = 0; in damon_do_apply_schemes()
751 if (c->ops.apply_scheme) { in damon_do_apply_schemes()
752 if (quota->esz && in damon_do_apply_schemes()
753 quota->charged_sz + sz > quota->esz) { in damon_do_apply_schemes()
754 sz = ALIGN_DOWN(quota->esz - quota->charged_sz, in damon_do_apply_schemes()
761 sz_applied = c->ops.apply_scheme(c, t, r, s); in damon_do_apply_schemes()
763 quota->total_charged_ns += timespec64_to_ns(&end) - in damon_do_apply_schemes()
765 quota->charged_sz += sz; in damon_do_apply_schemes()
766 if (quota->esz && quota->charged_sz >= quota->esz) { in damon_do_apply_schemes()
767 quota->charge_target_from = t; in damon_do_apply_schemes()
768 quota->charge_addr_from = r->ar.end + 1; in damon_do_apply_schemes()
771 if (s->action != DAMOS_STAT) in damon_do_apply_schemes()
772 r->age = 0; in damon_do_apply_schemes()
775 s->stat.nr_tried++; in damon_do_apply_schemes()
776 s->stat.sz_tried += sz; in damon_do_apply_schemes()
778 s->stat.nr_applied++; in damon_do_apply_schemes()
779 s->stat.sz_applied += sz_applied; in damon_do_apply_schemes()
783 /* Shouldn't be called if quota->ms and quota->sz are zero */
789 if (!quota->ms) { in damos_set_effective_quota()
790 quota->esz = quota->sz; in damos_set_effective_quota()
794 if (quota->total_charged_ns) in damos_set_effective_quota()
795 throughput = quota->total_charged_sz * 1000000 / in damos_set_effective_quota()
796 quota->total_charged_ns; in damos_set_effective_quota()
799 esz = throughput * quota->ms; in damos_set_effective_quota()
801 if (quota->sz && quota->sz < esz) in damos_set_effective_quota()
802 esz = quota->sz; in damos_set_effective_quota()
803 quota->esz = esz; in damos_set_effective_quota()
813 struct damos_quota *quota = &s->quota; in kdamond_apply_schemes()
817 if (!s->wmarks.activated) in kdamond_apply_schemes()
820 if (!quota->ms && !quota->sz) in kdamond_apply_schemes()
824 if (time_after_eq(jiffies, quota->charged_from + in kdamond_apply_schemes()
826 quota->reset_interval))) { in kdamond_apply_schemes()
827 if (quota->esz && quota->charged_sz >= quota->esz) in kdamond_apply_schemes()
828 s->stat.qt_exceeds++; in kdamond_apply_schemes()
829 quota->total_charged_sz += quota->charged_sz; in kdamond_apply_schemes()
830 quota->charged_from = jiffies; in kdamond_apply_schemes()
831 quota->charged_sz = 0; in kdamond_apply_schemes()
835 if (!c->ops.get_scheme_score) in kdamond_apply_schemes()
839 memset(quota->histogram, 0, sizeof(quota->histogram)); in kdamond_apply_schemes()
844 score = c->ops.get_scheme_score( in kdamond_apply_schemes()
846 quota->histogram[score] += damon_sz_region(r); in kdamond_apply_schemes()
853 for (cumulated_sz = 0, score = max_score; ; score--) { in kdamond_apply_schemes()
854 cumulated_sz += quota->histogram[score]; in kdamond_apply_schemes()
855 if (cumulated_sz >= quota->esz || !score) in kdamond_apply_schemes()
858 quota->min_score = score; in kdamond_apply_schemes()
875 l->nr_accesses = (l->nr_accesses * sz_l + r->nr_accesses * sz_r) / in damon_merge_two_regions()
877 l->age = (l->age * sz_l + r->age * sz_r) / (sz_l + sz_r); in damon_merge_two_regions()
878 l->ar.end = r->ar.end; in damon_merge_two_regions()
886 * thres '->nr_accesses' diff threshold for the merge
895 if (abs(r->nr_accesses - r->last_nr_accesses) > thres) in damon_merge_regions_of()
896 r->age = 0; in damon_merge_regions_of()
898 r->age++; in damon_merge_regions_of()
900 if (prev && prev->ar.end == r->ar.start && in damon_merge_regions_of()
901 abs(prev->nr_accesses - r->nr_accesses) <= thres && in damon_merge_regions_of()
912 * threshold '->nr_accesses' diff threshold for the merge
933 * sz_r size of the first sub-region that will be made
940 new = damon_new_region(r->ar.start + sz_r, r->ar.end); in damon_split_region_at()
944 r->ar.end = new->ar.start; in damon_split_region_at()
946 new->age = r->age; in damon_split_region_at()
947 new->last_nr_accesses = r->last_nr_accesses; in damon_split_region_at()
962 for (i = 0; i < nr_subs - 1 && in damon_split_regions_of()
965 * Randomly select size of left sub-region to be at in damon_split_regions_of()
981 * Split every target region into randomly-sized small regions
983 * This function splits every target region into random-sized small regions if
985 * user-specified maximum number of regions. This is for maximizing the
1000 if (nr_regions > ctx->attrs.max_nr_regions / 2) in kdamond_split_regions()
1005 nr_regions < ctx->attrs.max_nr_regions / 3) in kdamond_split_regions()
1015 * Check whether it is time to check and apply the operations-related data
1022 return damon_check_reset_time_interval(&ctx->last_ops_update, in kdamond_need_update_operations()
1023 ctx->attrs.ops_update_interval); in kdamond_need_update_operations()
1041 if (!ctx->ops.target_valid) in kdamond_need_stop()
1045 if (ctx->ops.target_valid(t)) in kdamond_need_stop()
1063 return -EINVAL; in damos_wmark_metric_value()
1068 * watermark check in micro-seconds.
1074 if (scheme->wmarks.metric == DAMOS_WMARK_NONE) in damos_wmark_wait_us()
1077 metric = damos_wmark_metric_value(scheme->wmarks.metric); in damos_wmark_wait_us()
1079 if (metric > scheme->wmarks.high || scheme->wmarks.low > metric) { in damos_wmark_wait_us()
1080 if (scheme->wmarks.activated) in damos_wmark_wait_us()
1082 scheme->action, in damos_wmark_wait_us()
1083 metric > scheme->wmarks.high ? in damos_wmark_wait_us()
1085 scheme->wmarks.activated = false; in damos_wmark_wait_us()
1086 return scheme->wmarks.interval; in damos_wmark_wait_us()
1090 if ((scheme->wmarks.high >= metric && metric >= scheme->wmarks.mid) && in damos_wmark_wait_us()
1091 !scheme->wmarks.activated) in damos_wmark_wait_us()
1092 return scheme->wmarks.interval; in damos_wmark_wait_us()
1094 if (!scheme->wmarks.activated) in damos_wmark_wait_us()
1095 pr_debug("activate a scheme (%d)\n", scheme->action); in damos_wmark_wait_us()
1096 scheme->wmarks.activated = true; in damos_wmark_wait_us()
1102 /* See Documentation/timers/timers-howto.rst for the thresholds */ in kdamond_usleep()
1130 if (ctx->callback.after_wmarks_check && in kdamond_wait_activation()
1131 ctx->callback.after_wmarks_check(ctx)) in kdamond_wait_activation()
1134 return -EBUSY; in kdamond_wait_activation()
1148 pr_debug("kdamond (%d) starts\n", current->pid); in kdamond_fn()
1150 if (ctx->ops.init) in kdamond_fn()
1151 ctx->ops.init(ctx); in kdamond_fn()
1152 if (ctx->callback.before_start && ctx->callback.before_start(ctx)) in kdamond_fn()
1161 if (ctx->ops.prepare_access_checks) in kdamond_fn()
1162 ctx->ops.prepare_access_checks(ctx); in kdamond_fn()
1163 if (ctx->callback.after_sampling && in kdamond_fn()
1164 ctx->callback.after_sampling(ctx)) in kdamond_fn()
1167 kdamond_usleep(ctx->attrs.sample_interval); in kdamond_fn()
1169 if (ctx->ops.check_accesses) in kdamond_fn()
1170 max_nr_accesses = ctx->ops.check_accesses(ctx); in kdamond_fn()
1176 if (ctx->callback.after_aggregation && in kdamond_fn()
1177 ctx->callback.after_aggregation(ctx)) in kdamond_fn()
1182 if (ctx->ops.reset_aggregated) in kdamond_fn()
1183 ctx->ops.reset_aggregated(ctx); in kdamond_fn()
1187 if (ctx->ops.update) in kdamond_fn()
1188 ctx->ops.update(ctx); in kdamond_fn()
1198 if (ctx->callback.before_terminate) in kdamond_fn()
1199 ctx->callback.before_terminate(ctx); in kdamond_fn()
1200 if (ctx->ops.cleanup) in kdamond_fn()
1201 ctx->ops.cleanup(ctx); in kdamond_fn()
1203 pr_debug("kdamond (%d) finishes\n", current->pid); in kdamond_fn()
1204 mutex_lock(&ctx->kdamond_lock); in kdamond_fn()
1205 ctx->kdamond = NULL; in kdamond_fn()
1206 mutex_unlock(&ctx->kdamond_lock); in kdamond_fn()
1209 nr_running_ctxs--; in kdamond_fn()
1218 * struct damon_system_ram_region - System RAM resource address region of
1232 if (a->end - a->start < resource_size(res)) { in walk_system_ram()
1233 a->start = res->start; in walk_system_ram()
1234 a->end = res->end; in walk_system_ram()
1259 * damon_set_region_biggest_system_ram_default() - Set the region of the given
1279 return -EINVAL; in damon_set_region_biggest_system_ram_default()
1283 return -EINVAL; in damon_set_region_biggest_system_ram_default()
1295 return -ENOMEM; in damon_init()
1303 #include "core-test.h"