-/* Paths to relevant cgroup data/control files */
-#define CGROUP_MEMORY_DIRECTORY "/sys/fs/cgroup/memory"
-#define CGROUP_DATA_PATH CGROUP_MEMORY_DIRECTORY "/memory.usage_in_bytes"
-#define CGROUP_CTRL_PATH CGROUP_MEMORY_DIRECTORY "/cgroup.event_control"
-
-/* RAM page size in bytes
- *
- * Configuration is defined in terms of (memnotify style) page counts.
- *
- * Conversion to/from byte counts used in cgroups interface are done via:
- * - mempressure_bytes_to_pages()
- * - mempressure_pages_to_bytes()
- */
-#define PAGE_SIZE ((unsigned long)sysconf(_SC_PAGESIZE))
-
-/* ========================================================================= *
- * Types
- * ========================================================================= */
-
-/** Structure for holding for /dev/mempressure compatible limit data */
-typedef struct
-{
- /** Estimate of number of non-discardable RAM pages */
- gint mnl_used;
-} mempressure_limit_t;
+#define PSI_MEMORY_PATH "/proc/pressure/memory"
/* ========================================================================= *
* Prototypes
@@ -68,38 +46,18 @@ typedef struct
* UTILITY
* ------------------------------------------------------------------------- */
-static int mempressure_bytes_to_pages(uint64_t bytes);
-static uint64_t mempressure_pages_to_bytes(int pages);
static guint mempressure_iowatch_add (int fd, bool close_on_unref, GIOCondition cnd, GIOFunc io_cb, gpointer aptr);
+static bool mempressure_streq (const char *s1, const char *s2);
/* ------------------------------------------------------------------------- *
- * MEMPRESSURE_LIMIT
- * ------------------------------------------------------------------------- */
-
-static void mempressure_limit_clear (mempressure_limit_t *self);
-static bool mempressure_limit_is_valid(const mempressure_limit_t *self);
-static int mempressure_limit_repr (const mempressure_limit_t *self, char *data, size_t size);
-static bool mempressure_limit_parse (mempressure_limit_t *self, const char *data);
-static bool mempressure_limit_exceeded(const mempressure_limit_t *self, const mempressure_limit_t *status);
-
-/* ------------------------------------------------------------------------- *
- * MEMPRESSURE_STATUS
+ * MEMPRESSURE_PSI
* ------------------------------------------------------------------------- */
-static memnotify_level_t mempressure_status_evaluate_level(void);
-static bool mempressure_status_update_level (void);
-static void mempressure_status_show_triggers (void);
-
-/* ------------------------------------------------------------------------- *
- * MEMPRESSURE_CGROUP
- * ------------------------------------------------------------------------- */
+static bool mempressure_psi_is_available (void);
+static gboolean mempressure_psi_event_cb (GIOChannel *chn, GIOCondition cnd, gpointer aptr);
+static void mempressure_psi_quit (void);
+static bool mempressure_psi_init (void);
-static bool mempressure_cgroup_is_available (void);
-static gboolean mempressure_cgroup_event_cb (GIOChannel *chn, GIOCondition cnd, gpointer aptr);
-static void mempressure_cgroup_quit (void);
-static bool mempressure_cgroup_init (void);
-static void mempressure_cgroup_update_thresholds(void);
-static bool mempressure_cgroup_update_status (void);
/* ------------------------------------------------------------------------- *
* MEMPRESSURE_SETTING
@@ -127,22 +85,6 @@ void g_module_unload (GModule *module);
* UTILITY
* ========================================================================= */
-/* Convert kernel reported byte count to page count used in configuration
- */
-static int mempressure_bytes_to_pages(uint64_t bytes)
-{
- return (int)(bytes / PAGE_SIZE);
-}
-
-/* Convert configuration page count to bytes for use in kernel interface
- */
-static uint64_t mempressure_pages_to_bytes(int pages)
-{
- if( pages < 0 )
- pages = 0;
- return PAGE_SIZE * (uint64_t)pages;
-}
-
/** Add a glib I/O notification for a file descriptor
*/
static guint
@@ -170,350 +112,258 @@ mempressure_iowatch_add(int fd, bool close_on_unref,
return wid;
}
-/* ========================================================================= *
- * MEMPRESSURE_LIMIT
- * ========================================================================= */
-
-/** Reset limit object values
- */
-static void
-mempressure_limit_clear(mempressure_limit_t *self)
-{
- self->mnl_used = 0;
-}
-
-/** Limit validity predicate
- */
-static bool
-mempressure_limit_is_valid(const mempressure_limit_t *self)
-{
- return self->mnl_used > 0;
-}
-
-/** Convert limit object values to /dev/mempressure compatible ascii form
- */
-static int
-mempressure_limit_repr(const mempressure_limit_t *self, char *data, size_t size)
-{
- int res = snprintf(data, size, "used %d", self->mnl_used);
- return res;
-}
-
-/** Parse limit object from /sys/fs/cgroup/memory/memory.usage_in_bytes format
- */
-static bool
-mempressure_limit_parse(mempressure_limit_t *self, const char *data)
-{
- char *end = 0;
- uint64_t val = strtoull(data, &end, 10);
- bool res = end > data && *end == 0;
-
- if( !res )
- mce_log(LL_ERR, "parse error: '%s' is not a number", data);
- else
- self->mnl_used = mempressure_bytes_to_pages(val);
-
- return res;
-}
-
-/** Check if limit object values are exceeded by given state data
+/* Null tolerant string equality predicate
+ *
+ * @param s1 string
+ * @param s2 string
+ *
+ * @return true if both s1 and s2 are null or same string, false otherwise
*/
-static bool
-mempressure_limit_exceeded(const mempressure_limit_t *self,
- const mempressure_limit_t *status)
+static bool mempressure_streq(const char *s1, const char *s2)
{
- return (mempressure_limit_is_valid(self) &&
- self->mnl_used <= status->mnl_used);
+ return (s1 && s2) ? !strcmp(s1, s2) : (s1 == s2);
}
/* ========================================================================= *
* MEMPRESSURE_STATUS
* ========================================================================= */
-/** Configuration limits for normal/warning/critical levels */
-static mempressure_limit_t mempressure_limit[] =
-{
- [MEMNOTIFY_LEVEL_NORMAL] = {
- .mnl_used = 0,
- },
- [MEMNOTIFY_LEVEL_WARNING] = {
- // values come from config - disabled by default
- .mnl_used = 0,
- },
- [MEMNOTIFY_LEVEL_CRITICAL] = {
- // values come from config - disabled by default
- .mnl_used = 0,
- },
-};
-
-/** Cached status read from kernel device */
-static mempressure_limit_t mempressure_status =
-{
- .mnl_used = 0,
-};
+/** Configuration */
+static gint mempressure_window = MCE_DEFAULT_MEMPRESSURE_WINDOW;
+static gint mempressure_warning_stall = MCE_DEFAULT_MEMPRESSURE_WARNING_STALL;
+static char* mempressure_warning_type = NULL;
+static gint mempressure_critical_stall = MCE_DEFAULT_MEMPRESSURE_CRITICAL_STALL;
+static char* mempressure_critical_type = NULL;
/** Cached memory use level */
static memnotify_level_t mempressure_level = MEMNOTIFY_LEVEL_UNKNOWN;
-/** Check current memory status against triggering levels
- */
-static memnotify_level_t
-mempressure_status_evaluate_level(void)
-{
- memnotify_level_t res = MEMNOTIFY_LEVEL_UNKNOWN;
-
- if( mempressure_limit_is_valid(&mempressure_status) ) {
- res = MEMNOTIFY_LEVEL_NORMAL;
-
- for( memnotify_level_t lev = MEMNOTIFY_LEVEL_NORMAL + 1;
- lev < G_N_ELEMENTS(mempressure_limit); ++lev ) {
- if( mempressure_limit_exceeded(mempressure_limit+lev, &mempressure_status) )
- res = lev;
- }
- }
-
- return res;
-}
+/* ========================================================================= *
+ * MEMPRESSURE_PSI
+ * ========================================================================= */
-/** Re-evaluate memory use level and broadcast changes via datapipe
+/** Probe if the required PSI sysfs files are present
*/
static bool
-mempressure_status_update_level(void)
+mempressure_psi_is_available(void)
{
- memnotify_level_t prev = mempressure_level;
- mempressure_level = mempressure_status_evaluate_level();
-
- if( mempressure_level == prev )
- goto EXIT;
+ return access(PSI_MEMORY_PATH, R_OK) == 0;
+}
- mce_log(LL_WARN, "mempressure_level: %s -> %s",
- memnotify_level_repr(prev),
- memnotify_level_repr(mempressure_level));
+static int mempressure_psi_warning_fd = -1;
+static int mempressure_psi_critical_fd = -1;
+static guint mempressure_psi_warn_event_id = 0;
+static guint mempressure_psi_crit_event_id = 0;
+static guint mempressure_psi_warn_timeout = 0;
+static guint mempressure_psi_crit_timeout = 0;
- datapipe_exec_full(&memnotify_level_pipe,
- GINT_TO_POINTER(mempressure_level));
+static void
+mempressure_psi_update_level(void)
+{
+ memnotify_level_t prev = mempressure_level;
-EXIT:
+ if ( mempressure_psi_crit_timeout != 0 ) {
+ mempressure_level = MEMNOTIFY_LEVEL_CRITICAL;
+ } else if ( mempressure_psi_warn_timeout != 0 ) {
+ mempressure_level = MEMNOTIFY_LEVEL_WARNING;
+ } else {
+ mempressure_level = MEMNOTIFY_LEVEL_NORMAL;
+ }
+ if ( prev != mempressure_level ) {
+ mce_log(LL_INFO, "mempressure_level: %s -> %s",
+ memnotify_level_repr(prev),
+ memnotify_level_repr(mempressure_level));
- return mempressure_level != MEMNOTIFY_LEVEL_UNKNOWN;
+ datapipe_exec_full(&memnotify_level_pipe,
+ GINT_TO_POINTER(mempressure_level));
+ }
}
-/** Log current memory level configuration for debugging purposes
- */
-static void
-mempressure_status_show_triggers(void)
+static gboolean
+mempressure_psi_timeout_cb(gpointer user_data)
{
- if( mce_log_p(LL_DEBUG) ) {
- for( size_t i = 0; i < G_N_ELEMENTS(mempressure_limit); ++i ) {
- char tmp[256];
- mempressure_limit_repr(mempressure_limit+i, tmp, sizeof tmp);
- mce_log(LL_DEBUG, "%s: %s", memnotify_level_repr(i), tmp);
- }
+ if( user_data == NULL ) {
+ mce_log(LL_ERR, "null timeout argument");
+ goto EXIT;
}
-}
-
-/* ========================================================================= *
- * MEMPRESSURE_CGROUP
- * ========================================================================= */
-
-/** File descriptor for CGROUP_DATA_PATH */
-static int mempressure_cgroup_data_fd = -1;
-
-/** File descriptor for CGROUP_CTRL_PATH */
-static int mempressure_cgroup_ctrl_fd = -1;
-/** Eventfd for receiving notifications about threshold crossings */
-static int mempressure_cgroup_event_fd = -1;
+ int fd = *((int*)user_data);
+ if ( fd == mempressure_psi_warning_fd ) {
+ mce_log(LL_DEBUG, "PSI warning event timeout");
+ mempressure_psi_warn_timeout = 0;
+ } else if ( fd == mempressure_psi_critical_fd ) {
+ mce_log(LL_DEBUG, "PSI critical event timeout");
+ mempressure_psi_crit_timeout = 0;
+ } else {
+ mce_log(LL_CRIT, "unknown fd in timeout callback");
+ goto EXIT;
+ }
-/** I/O watch for mempressure_cgroup_event_fd */
-static guint mempressure_cgroup_event_id = 0;
+ mempressure_psi_update_level();
-/** Probe if the required cgroup sysfs files are present
- */
-static bool
-mempressure_cgroup_is_available(void)
-{
- return (access(CGROUP_DATA_PATH, R_OK) == 0 &&
- access(CGROUP_CTRL_PATH, W_OK) == 0);
+EXIT:
+ return G_SOURCE_REMOVE;
}
-/** Input watch callback for cgroup memory threshold crossings
+/** Input watch callback for PSI events
*/
static gboolean
-mempressure_cgroup_event_cb(GIOChannel *chn, GIOCondition cnd, gpointer aptr)
+mempressure_psi_event_cb(GIOChannel *chn, GIOCondition cnd, gpointer aptr)
{
- (void) chn;
- (void) aptr;
+ (void)chn;
+ (void)aptr;
gboolean ret = G_SOURCE_REMOVE;
- if( !mempressure_cgroup_event_id )
- goto EXIT;
-
- if( mempressure_cgroup_event_fd == -1 )
- goto EXIT;
-
- if( mempressure_cgroup_data_fd == -1 )
- goto EXIT;
-
- mce_log(LL_DEBUG, "eventfd iowatch notify");
-
- if( cnd & ~G_IO_IN ) {
+ if( cnd & ~G_IO_PRI ) {
mce_log(LL_ERR, "unexpected input watch condition");
goto EXIT;
}
-
- uint64_t count = 0;
- ssize_t rc = read(mempressure_cgroup_event_fd, &count, sizeof count);
-
- if( rc == 0 ) {
- mce_log(LL_ERR, "eventfd eof");
+ if( aptr == NULL ) {
+ mce_log(LL_ERR, "null watch argument");
goto EXIT;
}
- if( rc == -1 ) {
- if( errno == EINTR || errno == EAGAIN )
- ret = G_SOURCE_CONTINUE;
- else
- mce_log(LL_ERR, "eventfd error: %m");
+ int fd = *((int*)aptr);
+
+ if (fd != mempressure_psi_warning_fd && fd != mempressure_psi_critical_fd) {
+ mce_log(LL_CRIT, "unknown fd in iowatch callback");
goto EXIT;
}
- if( mempressure_cgroup_update_status() )
- ret = G_SOURCE_CONTINUE;
-
- /* Update level anyway -> if we disable iowatch due to
- * read/parse errors, the level gets reset to 'unknown'.
- */
- mempressure_status_update_level();
+ if (fd == mempressure_psi_warning_fd) {
+ mce_log(LL_DEBUG, "warning PSI event");
+ if (mempressure_psi_warn_timeout != 0) {
+ g_source_remove(mempressure_psi_warn_timeout);
+ }
+ mempressure_psi_warn_timeout = g_timeout_add((mempressure_window / 1000) * 2,
+ mempressure_psi_timeout_cb, aptr);
+ } else {
+ assert(fd == mempressure_psi_critical_fd);
+ mce_log(LL_DEBUG, "critical PSI event");
+ if (mempressure_psi_crit_timeout != 0) {
+ g_source_remove(mempressure_psi_crit_timeout);
+ }
+ mempressure_psi_crit_timeout = g_timeout_add((mempressure_window / 1000) * 2,
+ mempressure_psi_timeout_cb, aptr);
+ }
+ mempressure_psi_update_level();
+ ret = G_SOURCE_CONTINUE;
EXIT:
- if( ret == G_SOURCE_REMOVE && mempressure_cgroup_event_id ) {
- mempressure_cgroup_event_id = 0;
+ if( ret == G_SOURCE_REMOVE &&
+ (mempressure_psi_warn_event_id || mempressure_psi_crit_event_id) ){
+ mempressure_psi_warn_event_id = 0;
+ mempressure_psi_crit_event_id = 0;
mce_log(LL_CRIT, "disabling eventfd iowatch");
}
return ret;
}
-/** Stop cgroup memory tracking
- */
static void
-mempressure_cgroup_quit(void)
+mempressure_psi_quit(void)
{
- if( mempressure_cgroup_event_id ) {
- mce_log(LL_DEBUG, "remove eventfd iowatch");
- g_source_remove(mempressure_cgroup_event_id),
- mempressure_cgroup_event_id = 0;
+ if ( mempressure_psi_warn_timeout != 0 ) {
+ g_source_remove(mempressure_psi_warn_timeout);
}
-
- if( mempressure_cgroup_event_fd != -1 ) {
- mce_log(LL_DEBUG, "close eventfd");
- close(mempressure_cgroup_event_fd),
- mempressure_cgroup_event_fd = -1;
+ if ( mempressure_psi_crit_timeout != 0 ) {
+ g_source_remove(mempressure_psi_crit_timeout);
}
-
- if( mempressure_cgroup_ctrl_fd != -1 ) {
- mce_log(LL_DEBUG, "close %s", CGROUP_CTRL_PATH);
- close(mempressure_cgroup_ctrl_fd),
- mempressure_cgroup_ctrl_fd = -1;
+ if( mempressure_psi_warn_event_id ) {
+ mce_log(LL_DEBUG, "remove warnong eventfd iowatch");
+ g_source_remove(mempressure_psi_warn_event_id),
+ mempressure_psi_warn_event_id = 0;
}
-
- if( mempressure_cgroup_data_fd != -1 ) {
- mce_log(LL_DEBUG, "close %s", CGROUP_DATA_PATH);
- close(mempressure_cgroup_data_fd),
- mempressure_cgroup_data_fd = -1;
+ if( mempressure_psi_crit_event_id ) {
+ mce_log(LL_DEBUG, "remove critical eventfd iowatch");
+ g_source_remove(mempressure_psi_crit_event_id),
+ mempressure_psi_crit_event_id = 0;
+ }
+ if ( mempressure_psi_warning_fd ) {
+ if ( close( mempressure_psi_warning_fd ) < 0) {
+ mce_log(LL_ERR, "close failed");
+ }
+ mempressure_psi_warning_fd = 0;
+ }
+ if ( mempressure_psi_critical_fd ) {
+ if ( close( mempressure_psi_critical_fd ) < 0) {
+ mce_log(LL_ERR, "close failed");
+ }
+ mempressure_psi_critical_fd = 0;
}
}
-/** Start cgroup memory tracking
- */
static bool
-mempressure_cgroup_init(void)
+mempressure_psi_init(void)
{
bool res = false;
- /* Check threshold configuration */
- for( int i = MEMNOTIFY_LEVEL_WARNING; i <= MEMNOTIFY_LEVEL_CRITICAL; ++i ) {
- if( !mempressure_limit_is_valid(&mempressure_limit[i]) ) {
- mce_log(LL_WARN, "mempressure '%s' threshold is not defined",
- memnotify_level_repr(i));
- goto EXIT;
- }
- }
-
/* Get file descriptors */
- mce_log(LL_DEBUG, "create eventfd");
- if( (mempressure_cgroup_event_fd = eventfd(0, 0)) == -1 ) {
- mce_log(LL_ERR, "create eventfd: %m");
+ mce_log(LL_DEBUG, "open %s for warning threshold", PSI_MEMORY_PATH);
+ if( (mempressure_psi_warning_fd = open(PSI_MEMORY_PATH, O_RDWR | O_NONBLOCK)) == -1 ) {
+ mce_log(LL_ERR, "%s: open: %m", PSI_MEMORY_PATH);
goto EXIT;
}
- mce_log(LL_DEBUG, "open %s", CGROUP_DATA_PATH);
- if( (mempressure_cgroup_data_fd = open(CGROUP_DATA_PATH, O_RDONLY)) == -1 ) {
- mce_log(LL_ERR, "%s: open: %m", CGROUP_DATA_PATH);
+ mce_log(LL_DEBUG, "open %s for critical threshold", PSI_MEMORY_PATH);
+ if( (mempressure_psi_critical_fd = open(PSI_MEMORY_PATH, O_RDWR | O_NONBLOCK)) == -1 ) {
+ mce_log(LL_ERR, "%s: open: %m", PSI_MEMORY_PATH);
goto EXIT;
}
- mce_log(LL_DEBUG, "open %s", CGROUP_CTRL_PATH);
- if( (mempressure_cgroup_ctrl_fd = open(CGROUP_CTRL_PATH, O_WRONLY)) == -1 ) {
- mce_log(LL_ERR, "%s: open: %m", CGROUP_CTRL_PATH);
+ // setup thresholds
+ char buf[1024];
+ snprintf(buf, sizeof buf,
+ "%s %d %d",
+ mempressure_warning_type, mempressure_warning_stall, mempressure_window);
+
+ mce_log(LL_DEBUG, "warning threshold: %s", buf);
+
+ if (write(mempressure_psi_warning_fd, buf, strlen(buf) + 1) < 0) {
+ mce_log(LL_ERR, "%s: write: %m", PSI_MEMORY_PATH);
goto EXIT;
}
- /* Program notification limits */
- for( int i = MEMNOTIFY_LEVEL_WARNING; i <= MEMNOTIFY_LEVEL_CRITICAL; ++i ) {
- int pages = mempressure_limit[i].mnl_used;
- uint64_t bytes = mempressure_pages_to_bytes(pages);
+ snprintf(buf, sizeof buf,
+ "%s %d %d",
+ mempressure_critical_type, mempressure_critical_stall, mempressure_window);
- mce_log(LL_DEBUG, "mempressure %s threshold %" PRIu64 "",
- memnotify_level_repr(i), bytes);
+ mce_log(LL_DEBUG, "critical threshold: %s", buf);
- char data[256];
- snprintf(data, sizeof data, "%d %d %" PRIu64 "\n",
- mempressure_cgroup_event_fd, mempressure_cgroup_data_fd, bytes);
- if( write(mempressure_cgroup_ctrl_fd, data, strlen(data)) == -1 ) {
- mce_log(LL_ERR, "%s: write: %m", CGROUP_CTRL_PATH);
- goto EXIT;
- }
+ if (write(mempressure_psi_critical_fd, buf, strlen(buf) + 1) < 0) {
+ mce_log(LL_ERR, "%s: write: %m", PSI_MEMORY_PATH);
+ goto EXIT;
}
- /* Control fd is not needed after threshold setup is done */
- mce_log(LL_DEBUG, "close %s", CGROUP_CTRL_PATH);
- close(mempressure_cgroup_ctrl_fd),
- mempressure_cgroup_ctrl_fd = -1;
-
/* Setup notification iowatch */
- mce_log(LL_DEBUG, "add eventfd iowatch");
- mempressure_cgroup_event_id =
- mempressure_iowatch_add(mempressure_cgroup_event_fd, false, G_IO_IN,
- mempressure_cgroup_event_cb, NULL);
- if( !mempressure_cgroup_event_id ) {
- mce_log(LL_ERR, "failed to add eventfd iowatch");
+ mce_log(LL_DEBUG, "add warning fd iowatch");
+ mempressure_psi_warn_event_id =
+ mempressure_iowatch_add(mempressure_psi_warning_fd, false, G_IO_PRI,
+ mempressure_psi_event_cb, &mempressure_psi_warning_fd);
+ if( !mempressure_psi_warn_event_id ) {
+ mce_log(LL_ERR, "failed to add warning fd iowatch");
goto EXIT;
}
- /* Evaluate and publish current state */
- if( !mempressure_cgroup_update_status() )
+ mce_log(LL_DEBUG, "add critical fd iowatch");
+ mempressure_psi_crit_event_id =
+ mempressure_iowatch_add(mempressure_psi_critical_fd, false, G_IO_PRI,
+ mempressure_psi_event_cb, &mempressure_psi_critical_fd);
+ if( !mempressure_psi_crit_event_id ) {
+ mce_log(LL_ERR, "failed to add critical fd iowatch");
goto EXIT;
-
- if( !mempressure_status_update_level() )
- goto EXIT;
-
- /* Initialization was successfully completed and we have broadcast
- * a valid pressure level on memnotify_level_pipe - which should
- * act as a signal for furthre to be loaded alternate memory pressure
- * plugins to remain inactive.
- */
+ }
res = true;
+ mempressure_level = MEMNOTIFY_LEVEL_NORMAL;
EXIT:
// all or nothing
if( !res )
- mempressure_cgroup_quit();
+ mempressure_psi_quit();
return res;
}
@@ -521,70 +371,34 @@ mempressure_cgroup_init(void)
/** Set kernel side triggering levels and update current status
*/
static void
-mempressure_cgroup_update_thresholds(void)
+mempressure_psi_update_thresholds(void)
{
/* TODO: Is there some way to remove trigger thresholds?
*
* Meanwhile do a full reinitialization to get rid of old thresholds.
*/
- mempressure_cgroup_quit();
- mempressure_cgroup_init();
-}
-
-/** Read current memory use status from kernel side
- */
-static bool
-mempressure_cgroup_update_status(void)
-{
- bool res = false;
-
- if( mempressure_cgroup_data_fd == -1 ) {
- mce_log(LL_ERR, "data file not opened");
- goto EXIT;
- }
-
- if( lseek(mempressure_cgroup_data_fd, 0, SEEK_SET) == -1 ) {
- mce_log(LL_ERR, "failed to rewind data file: %m");
- goto EXIT;
- }
-
- errno = 0;
-
- char tmp[256];
- int done = read(mempressure_cgroup_data_fd, tmp, sizeof tmp - 1);
- if( done <= 0 ) {
- mce_log(LL_ERR, "failed to read data file: %m");
- goto EXIT;
- }
-
- tmp[done] = 0;
- tmp[strcspn(tmp, "\n")] = 0;
-
- mce_log(LL_DEBUG, "status from data file: %s", tmp);
-
- if( !mempressure_limit_parse(&mempressure_status, tmp) ) {
- mce_log(LL_ERR, "failed to parse status");
- goto EXIT;
- }
-
- res = true;
-
-EXIT:
- if( !res )
- mempressure_limit_clear(&mempressure_status);
-
- return res;
+ mempressure_psi_quit();
+ mempressure_psi_init();
}
/* ========================================================================= *
* MEMPRESSURE_SETTING
* ========================================================================= */
-/** GConf notification id for mempressure.warning.used level */
-static guint mempressure_setting_warning_used_id = 0;
+/** GConf notification id for mempressure.window */
+static guint mempressure_setting_window_id = 0;
+
+/** GConf notification id for mempressure.warning.stall time */
+static guint mempressure_setting_warning_stall_id = 0;
+
+/** GConf notification id for mempressure.warning.type */
+static guint mempressure_setting_warning_type_id = 0;
-/** GConf notification id for mempressure.critical.used level */
-static guint mempressure_setting_critical_used_id = 0;
+/** GConf notification id for mempressure.critical.stall time */
+static guint mempressure_setting_critical_stall_id = 0;
+
+/** GConf notification id for mempressure.critical.type */
+static guint mempressure_setting_critical_type_id = 0;
/** GConf callback for mempressure related settings
*
@@ -605,23 +419,47 @@ mempressure_setting_cb(GConfClient *const gcc, const guint id,
if (gcv == NULL) {
mce_log(LL_WARN, "GConf Key `%s' has been unset",
gconf_entry_get_key(entry));
- }
- else if( id == mempressure_setting_warning_used_id ) {
- gint old = mempressure_limit[MEMNOTIFY_LEVEL_WARNING].mnl_used;
+ } else if ( id == mempressure_setting_window_id ) {
+ gint old = mempressure_window;
gint val = gconf_value_get_int(gcv);
if( old != val ) {
- mce_log(LL_DEBUG, "mempressure.warning.used: %d -> %d", old, val);
- mempressure_limit[MEMNOTIFY_LEVEL_WARNING].mnl_used = val;
- mempressure_cgroup_update_thresholds();
+ mce_log(LL_DEBUG, "mempressure.window: %d -> %d", old, val);
+ mempressure_window = val;
+ mempressure_psi_update_thresholds();
}
- }
- else if( id == mempressure_setting_critical_used_id ) {
- gint old = mempressure_limit[MEMNOTIFY_LEVEL_CRITICAL].mnl_used;
+ } else if ( id == mempressure_setting_warning_stall_id ) {
+ gint old = mempressure_warning_stall;
+ gint val = gconf_value_get_int(gcv);
+ if( old != val ) {
+ mce_log(LL_DEBUG, "mempressure.warning.stall: %d -> %d", old, val);
+ mempressure_warning_stall = val;
+ mempressure_psi_update_thresholds();
+ }
+ } else if ( id == mempressure_setting_warning_type_id ) {
+ char* old = mempressure_warning_type;
+ const char* val = gconf_value_get_string(gcv);
+ if( !mempressure_streq(old, val) ) {
+ mce_log(LL_DEBUG, "mempressure.warning.type: %s -> %s", old, val);
+ g_free(mempressure_warning_type);
+ mempressure_warning_type = g_strdup(val);
+ mempressure_psi_update_thresholds();
+ }
+ } else if ( id == mempressure_setting_critical_stall_id ) {
+ gint old = mempressure_critical_stall;
gint val = gconf_value_get_int(gcv);
if( old != val ) {
- mce_log(LL_DEBUG, "mempressure.critical.used: %d -> %d", old, val);
- mempressure_limit[MEMNOTIFY_LEVEL_CRITICAL].mnl_used = val;
- mempressure_cgroup_update_thresholds();
+ mce_log(LL_DEBUG, "mempressure.critical.stall: %d -> %d", old, val);
+ mempressure_critical_stall = val;
+ mempressure_psi_update_thresholds();
+ }
+ } else if ( id == mempressure_setting_critical_type_id ) {
+ char* old = mempressure_critical_type;
+ const char* val = gconf_value_get_string(gcv);
+ if( !mempressure_streq(old, val) ) {
+ mce_log(LL_DEBUG, "mempressure.critical.type: %s -> %s", old, val);
+ g_free(mempressure_critical_type);
+ mempressure_critical_type = g_strdup(val);
+ mempressure_psi_update_thresholds();
}
}
else {
@@ -635,36 +473,79 @@ mempressure_setting_cb(GConfClient *const gcc, const guint id,
*/
static void mempressure_setting_init(void)
{
- /* mempressure.warning.used level */
- mce_setting_notifier_add(MCE_SETTING_MEMNOTIFY_WARNING_PATH,
- MCE_SETTING_MEMNOTIFY_WARNING_USED,
+ mce_setting_notifier_add(MCE_SETTING_MEMPRESSURE_PATH,
+ MCE_SETTING_MEMPRESSURE_WINDOW,
mempressure_setting_cb,
- &mempressure_setting_warning_used_id);
+ &mempressure_setting_window_id);
- mce_setting_get_int(MCE_SETTING_MEMNOTIFY_WARNING_USED,
- &mempressure_limit[MEMNOTIFY_LEVEL_WARNING].mnl_used);
+ mce_setting_get_int(MCE_SETTING_MEMPRESSURE_WINDOW,
+ &mempressure_window);
- /* mempressure.critical.used level */
- mce_setting_notifier_add(MCE_SETTING_MEMNOTIFY_CRITICAL_PATH,
- MCE_SETTING_MEMNOTIFY_CRITICAL_USED,
+ mce_setting_notifier_add(MCE_SETTING_MEMPRESSURE_WARNING_PATH,
+ MCE_SETTING_MEMPRESSURE_WARNING_STALL,
mempressure_setting_cb,
- &mempressure_setting_critical_used_id);
+ &mempressure_setting_warning_stall_id);
- mce_setting_get_int(MCE_SETTING_MEMNOTIFY_CRITICAL_USED,
- &mempressure_limit[MEMNOTIFY_LEVEL_CRITICAL].mnl_used);
+ mce_setting_get_int(MCE_SETTING_MEMPRESSURE_WARNING_STALL,
+ &mempressure_warning_stall);
- mempressure_status_show_triggers();
+ mce_setting_notifier_add(MCE_SETTING_MEMPRESSURE_WARNING_PATH,
+ MCE_SETTING_MEMPRESSURE_WARNING_TYPE,
+ mempressure_setting_cb,
+ &mempressure_setting_warning_type_id);
+
+ mce_setting_get_string(MCE_SETTING_MEMPRESSURE_WARNING_TYPE,
+ &mempressure_warning_type);
+
+ if ( mempressure_warning_type == NULL ) {
+ mempressure_warning_type = g_strdup(MCE_DEFAULT_MEMPRESSURE_WARNING_TYPE);
+ }
+
+ mce_setting_notifier_add(MCE_SETTING_MEMPRESSURE_CRITICAL_PATH,
+ MCE_SETTING_MEMPRESSURE_CRITICAL_STALL,
+ mempressure_setting_cb,
+ &mempressure_setting_critical_stall_id);
+
+ mce_setting_get_int(MCE_SETTING_MEMPRESSURE_CRITICAL_STALL,
+ &mempressure_critical_stall);
+
+ mce_setting_notifier_add(MCE_SETTING_MEMPRESSURE_CRITICAL_PATH,
+ MCE_SETTING_MEMPRESSURE_CRITICAL_TYPE,
+ mempressure_setting_cb,
+ &mempressure_setting_critical_type_id);
+
+ mce_setting_get_string(MCE_SETTING_MEMPRESSURE_CRITICAL_TYPE,
+ &mempressure_critical_type);
+
+ if ( mempressure_critical_type == NULL ) {
+ mempressure_critical_type = g_strdup(MCE_DEFAULT_MEMPRESSURE_CRITICAL_TYPE);
+ }
}
/** Stop tracking setting changes
*/
static void mempressure_setting_quit(void)
{
- mce_setting_notifier_remove(mempressure_setting_warning_used_id),
- mempressure_setting_warning_used_id = 0;
+ mce_setting_notifier_remove(mempressure_setting_window_id),
+ mempressure_setting_window_id = 0;
+
+ mce_setting_notifier_remove(mempressure_setting_warning_stall_id),
+ mempressure_setting_warning_stall_id = 0;
+
+ mce_setting_notifier_remove(mempressure_setting_warning_type_id),
+ mempressure_setting_warning_type_id = 0;
+
+ g_free(mempressure_warning_type);
+ mempressure_warning_type = NULL;
+
+ mce_setting_notifier_remove(mempressure_setting_critical_stall_id),
+ mempressure_setting_critical_stall_id = 0;
+
+ mce_setting_notifier_remove(mempressure_setting_critical_type_id),
+ mempressure_setting_critical_type_id = 0;
- mce_setting_notifier_remove(mempressure_setting_critical_used_id),
- mempressure_setting_critical_used_id = 0;
+ g_free(mempressure_critical_type);
+ mempressure_critical_type = NULL;
}
/* ========================================================================= *
@@ -674,7 +555,7 @@ static void mempressure_setting_quit(void)
static void
mempressure_plugin_quit(void)
{
- mempressure_cgroup_quit();
+ mempressure_psi_quit();
mempressure_setting_quit();
}
@@ -685,7 +566,7 @@ mempressure_plugin_init(void)
mempressure_setting_init();
- if( !mempressure_cgroup_init() )
+ if ( !mempressure_psi_init() )
goto EXIT;
success = true;
@@ -721,8 +602,8 @@ G_MODULE_EXPORT const gchar *g_module_check_init(GModule *module)
}
/* Check if required sysfs files are present */
- if( !mempressure_cgroup_is_available() ) {
- mce_log(LL_WARN, "mempressure cgroup interface not available");
+ if( !mempressure_psi_is_available() ) {
+ mce_log(LL_WARN, "mempressure psi interface not available");
goto EXIT;
}
diff --git a/modules/mempressure.h b/modules/mempressure.h
new file mode 100644
index 0000000..3272dbf
--- /dev/null
+++ b/modules/mempressure.h
@@ -0,0 +1,58 @@
+/**
+ * @file mempressure.h
+ * Memory use tracking and notification plugin for the Mode Control Entity
+ *
+ * Copyright (C) 2014-2019 Jolla Ltd.
+ *
+ * @author Simo Piiroinen
+ *
+ * mce is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License
+ * version 2.1 as published by the Free Software Foundation.
+ *
+ * mce is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with mce. If not, see .
+ */
+
+#ifndef MEMPRESSURE_H_
+# define MEMPRESSURE_H_
+
+/* ========================================================================= *
+ * Settings
+ * ========================================================================= */
+
+/** Prefix for mempressure setting keys */
+# define MCE_SETTING_MEMPRESSURE_PATH "/system/osso/dsm/mempressure"
+
+/** PSI tracking window [us] */
+# define MCE_SETTING_MEMPRESSURE_WINDOW MCE_SETTING_MEMPRESSURE_PATH"/window"
+# define MCE_DEFAULT_MEMPRESSURE_WINDOW 1000000
+
+/** Memnotify warning level configuration */
+# define MCE_SETTING_MEMPRESSURE_WARNING_PATH MCE_SETTING_MEMPRESSURE_PATH"/warning"
+
+/** Warning threshold stall stall time [us] */
+# define MCE_SETTING_MEMPRESSURE_WARNING_STALL MCE_SETTING_MEMPRESSURE_PATH"/warning/stall"
+# define MCE_DEFAULT_MEMPRESSURE_WARNING_STALL 100000
+
+/** Warning threshold type (some or full) */
+# define MCE_SETTING_MEMPRESSURE_WARNING_TYPE MCE_SETTING_MEMPRESSURE_PATH"/warning/type"
+# define MCE_DEFAULT_MEMPRESSURE_WARNING_TYPE "some"
+
+/** Memnotify critical level configuration */
+# define MCE_SETTING_MEMPRESSURE_CRITICAL_PATH MCE_SETTING_MEMPRESSURE_PATH"/critical"
+
+/** Critical threshold for stall time [us] */
+# define MCE_SETTING_MEMPRESSURE_CRITICAL_STALL MCE_SETTING_MEMPRESSURE_PATH"/critical/stall"
+# define MCE_DEFAULT_MEMPRESSURE_CRITICAL_STALL 150000
+
+/** Critica threshold type (some or full) */
+# define MCE_SETTING_MEMPRESSURE_CRITICAL_TYPE MCE_SETTING_MEMPRESSURE_PATH"/critical/type"
+# define MCE_DEFAULT_MEMPRESSURE_CRITICAL_TYPE "full"
+
+#endif /* MEMPRESSURE_H_ */