cmogstored 1.8.1 - use default system stack size
[cmogstored.git] / notify.c
blobfa260408516f5e2dd310b6b5ea537a892e2f3b8a
1 /*
2 * Copyright (C) 2012-2020 all contributors <cmogstored-public@yhbt.net>
3 * License: GPL-3.0+ <https://www.gnu.org/licenses/gpl-3.0.txt>
4 */
5 #include "cmogstored.h"
7 static int notes[MOG_NOTIFY_MAX];
8 static struct mog_fd *notify_mfd;
9 static time_t usage_file_updated_at;
10 static time_t usage_file_interval = 10;
11 struct mog_queue *mog_notify_queue;
13 void mog_notify_init(void)
15 const char *interval = getenv("MOG_DISK_USAGE_INTERVAL");
17 if (interval) {
18 int i = atoi(interval);
20 if (i > 0)
21 usage_file_interval = (time_t)i;
24 assert(mog_notify_queue == NULL && "notify queue already initialized");
25 assert(notify_mfd == NULL && "notify_mfd already initialized");
27 mog_notify_queue = mog_queue_new();
28 notify_mfd = mog_selfwake_new();
29 if (notify_mfd) {
30 struct mog_selfwake *notify = &notify_mfd->as.selfwake;
31 assert(notify->writer && "notify writer not initialized");
32 notify->queue = mog_notify_queue;
33 mog_idleq_add(notify->queue, notify_mfd, MOG_QEV_RD);
37 static void global_mkusage(void)
39 mog_mkusage_all();
40 usage_file_updated_at = time(NULL);
43 static inline bool note_xchg(enum mog_notification note, int from, int to)
45 return __sync_bool_compare_and_swap(&notes[note], from, to);
48 static void note_run(void)
50 if (note_xchg(MOG_NOTIFY_DEVICE_REFRESH, 1, 0))
51 global_mkusage();
53 if (note_xchg(MOG_NOTIFY_AIO_THREADS, 1, 0))
54 mog_svc_aio_threads_handler();
57 /* drain the pipe and process notifications */
58 static void note_queue_step(struct mog_fd *mfd)
60 mog_selfwake_drain(mfd);
61 note_run();
62 mog_idleq_push(mfd->as.selfwake.queue, mfd, MOG_QEV_RD);
65 static void notify_queue_step(struct mog_fd *mfd)
67 switch (mfd->fd_type) {
68 case MOG_FD_TYPE_SELFWAKE: note_queue_step(mfd); return;
69 case MOG_FD_TYPE_IOSTAT: mog_iostat_queue_step(mfd); return;
70 default:
71 assert(0 && mfd->fd_type && "bad fd_type in queue");
75 /* this is the main loop of cmogstored */
76 void mog_notify_wait(bool need_usage_file)
78 time_t next = usage_file_updated_at + usage_file_interval;
79 time_t now = time(NULL);
80 time_t timeout = next - now;
81 struct mog_fd *mfd;
83 if (next <= now)
84 global_mkusage();
87 * epoll_wait() with timeout==0 can avoid some slow paths,
88 * so take anything that's already ready before sleeping
90 while ((mfd = mog_idleq_wait(mog_notify_queue, 0)))
91 notify_queue_step(mfd);
93 if (need_usage_file == false)
94 timeout = -1;
95 else if (timeout > 0)
96 timeout *= 1000;
97 else
98 timeout = 0;
100 mfd = mog_idleq_wait_intr(mog_notify_queue, timeout);
101 if (mfd)
102 notify_queue_step(mfd);
103 else
105 * errno == EINTR, but epoll_pwait on some Linux v5.0+/v5.1+
106 * fails to return EINTR. This should be fixed in Linux,
107 * soon:
108 * <20190427093319.sgicqik2oqkez3wk@dcvr>
109 * <20190507043954.9020-1-deepa.kernel@gmail.com>
111 note_run();
114 /* this is async-signal safe */
115 void mog_notify(enum mog_notification note)
117 switch (note) {
118 case MOG_NOTIFY_DEVICE_REFRESH:
119 case MOG_NOTIFY_AIO_THREADS:
120 note_xchg(note, 0, 1);
121 mog_selfwake_interrupt();
122 break;
123 case MOG_NOTIFY_SIGNAL: break;
124 default: assert(0 && "bad note passed");
126 mog_selfwake_trigger(notify_mfd);