1#include <mem/nofail.h>
2#include <mem/page_zeroer.h>
3#include <smp/domain.h>
4#include <smp/perdomain.h>
5
6static enum daemon_thread_command page_zeroer_ts_thread(void *a, void *b) {
7 cc_ignore(a, b);
8 return DAEMON_THREAD_COMMAND_DEFAULT;
9}
10
11static enum daemon_thread_command page_zeroer_bg_thread(void *a, void *b) {
12 cc_ignore(a, b);
13 return DAEMON_THREAD_COMMAND_DEFAULT;
14}
15
16static struct daemon_work pz_ts_work =
17 DAEMON_WORK_FROM(page_zeroer_ts_thread, WORK_ARGS(NULL, NULL));
18
19static struct daemon_work pz_bg_work =
20 DAEMON_WORK_FROM(page_zeroer_bg_thread, WORK_ARGS(NULL, NULL));
21
22static void page_zeroer_perdomain_init(struct page_zeroer *pz,
23 domain_id_t domain) {
24 struct cpu_mask cmask;
25 cpu_mask_init(m: &cmask, nbits: global.core_count);
26 size_t threads = global.domains[domain]->num_cores / 4;
27 if (!threads)
28 threads = 1;
29
30 domain_set_cpu_mask(mask: &cmask, domain: global.domains[domain]);
31 struct daemon_attributes attrs = {
32 .thread_cpu_mask = cmask,
33 .max_timesharing_threads = threads,
34 .min_timesharing_threads = threads,
35 .flags = DAEMON_FLAG_HAS_WORKQUEUE | DAEMON_FLAG_HAS_NAME,
36 };
37
38 struct workqueue_attributes wqattrs = {
39 .max_workers = threads,
40 .min_workers = threads,
41 .spawn_delay = 0,
42 .idle_check = WORKQUEUE_DEFAULT_IDLE_CHECK,
43 .worker_cpu_mask = cmask,
44 .worker_niceness = 0,
45 .flags = WORKQUEUE_FLAG_STATIC_WORKERS | WORKQUEUE_FLAG_ON_DEMAND |
46 WORKQUEUE_FLAG_NAMED | WORKQUEUE_FLAG_NO_WORKER_GC,
47 };
48
49 nofail(pz->daemon =
50 daemon_create(("page_zeroer_daemon_%zu", domain), &attrs,
51 &pz_ts_work, &pz_bg_work, &wqattrs));
52}
53
54PERDOMAIN_DEFINE(struct page_zeroer, page_zeroers, page_zeroer_perdomain_init);
55