23#include <glib/gstdio.h>
33#include <sys/eventfd.h>
40 FILE *
f = g_fopen(file,
"r");
43 gboolean found =
FALSE;
45 while(!found && fgets(line,
sizeof(line),
f))
47 unsigned long long total = 0;
48 if(sscanf(line,
"full avg10=%*f avg60=%*f avg300=%*f total=%llu", &total) == 1)
62 FILE *
f = g_fopen(
"/proc/self/cgroup",
"r");
66 while(fgets(line,
sizeof(line),
f))
69 if(!strncmp(line,
"0::", 3))
71 g_strlcpy(path, line + 3,
size);
72 char *newline = strchr(path,
'\n');
73 if(newline) *newline =
'\0';
83 return path[0] ==
'/' && path[1] !=
'\0';
90 char *slash = strrchr(path,
'/');
98 const int fd = open(file, O_RDWR | O_NONBLOCK | O_CLOEXEC);
102 if(write(fd, trigger, strlen(trigger) + 1) < 0)
113#if defined(__linux__)
128 snprintf(file,
sizeof(file),
"/sys/fs/cgroup%s/memory.pressure", path);
140#if defined(__linux__)
147 snprintf(trigger,
sizeof(trigger),
"full %" PRIu64
" %" PRIu64, stall_us, window_us);
150 const int system_fd =
_open_trigger(
"/proc/pressure/memory", trigger);
151 if(system_fd >= 0) fds[count++] = system_fd;
156 while(more && count < max_fds)
159 snprintf(file,
sizeof(file),
"/sys/fs/cgroup%s/memory.pressure", path);
161 if(fd >= 0) fds[count++] = fd;
182 for(
int i = 0;
i < watch->
count;
i++) close(watch->
fds[
i]);
191 for(
int i = 0;
i < watch->
count;
i++)
193 pfd[
n].fd = watch->
fds[
i];
194 pfd[
n].events = POLLPRI;
200 pfd[
n].events = POLLIN;
206 if(poll(pfd,
n, -1) < 0)
208 if(errno == EINTR)
continue;
211 if(pfd[stop].revents)
break;
213 gboolean fired =
FALSE;
214 for(
int i = 0;
i < stop;
i++)
216 if(pfd[
i].revents & POLLPRI) fired =
TRUE;
219 if(pfd[
i].revents & (POLLERR | POLLNVAL)) pfd[
i].fd = -1;
228 void (*stalled)(
void *user),
void *user)
230#if defined(__linux__)
239 if(watch->
count == 0)
248 watch->
stop_fd = eventfd(0, EFD_CLOEXEC);
270#if defined(__linux__)
275 if(write(w->
stop_fd, &wake,
sizeof(wake)) != (ssize_t)
sizeof(wake))
276 pthread_cancel(w->
thread);
277 pthread_join(w->
thread, NULL);
288#if defined(__linux__)
int levels(struct dt_imageio_module_data_t *data)
typedef void((*dt_cache_allocate_t)(void *userdata, dt_cache_entry_t *entry))
#define IS_NULL_PTR(p)
C is way too permissive with !=, == and if(var) checks, which can mean too many things depending on w...
static gboolean _read_full_total(const char *file, uint64_t *total_us)
int dt_memory_pressure_watch_levels(const dt_memory_pressure_watch_t *watch)
static int _triggers_open(int *fds, int max_fds, uint64_t stall_us, uint64_t window_us)
static void _watch_close(dt_memory_pressure_watch_t *watch)
static gboolean _cgroup_parent(char *path)
static void _own_cgroup_path(char *path, const size_t size)
static gboolean _cgroup_below_root(const char *path)
int dt_memory_pressure_read_full_stall(uint64_t *total_us, int max_levels)
static int _open_trigger(const char *file, const char *trigger)
void dt_memory_pressure_watch_stop(dt_memory_pressure_watch_t **watch)
static void * _watch_thread(void *arg)
dt_memory_pressure_watch_t * dt_memory_pressure_watch_start(uint64_t stall_us, uint64_t window_us, void(*stalled)(void *user), void *user)
#define DT_MEMORY_PRESSURE_MAX_LEVELS
unsigned __int64 uint64_t
void(* stalled)(void *user)
int fds[DT_MEMORY_PRESSURE_MAX_LEVELS]