+#endif /* HAVE_GETMNTENT_R && HAVE_STATVFS */
+}
+\f
+#define SYSTEM_STATS_INTERVAL (5 * 1000) /* In milliseconds. */
+
+static struct ovs_mutex mutex = OVS_MUTEX_INITIALIZER;
+static pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
+static struct latch latch OVS_GUARDED_BY(mutex);
+static bool enabled;
+static bool started OVS_GUARDED_BY(mutex);
+static struct smap *system_stats OVS_GUARDED_BY(mutex);
+
+static void *system_stats_thread_func(void *);
+static void discard_stats(void);
+
+/* Enables or disables system stats collection, according to 'enable'. */
+void
+system_stats_enable(bool enable)
+{
+ if (enabled != enable) {
+ ovs_mutex_lock(&mutex);
+ if (enable) {
+ if (!started) {
+ xpthread_create(NULL, NULL, system_stats_thread_func, NULL);
+ latch_init(&latch);
+ started = true;
+ }
+ discard_stats();
+ xpthread_cond_signal(&cond);
+ }
+ enabled = enable;
+ ovs_mutex_unlock(&mutex);
+ }
+}
+
+/* Tries to obtain a new snapshot of system stats every SYSTEM_STATS_INTERVAL
+ * milliseconds.
+ *
+ * When a new snapshot is available (which only occurs if system stats are
+ * enabled), returns it as an smap owned by the caller. The caller must use
+ * both smap_destroy() and free() to completely free the returned data.
+ *
+ * When no new snapshot is available, returns NULL. */
+struct smap *
+system_stats_run(void)
+{
+ struct smap *stats = NULL;
+
+ ovs_mutex_lock(&mutex);
+ if (system_stats) {
+ latch_poll(&latch);
+
+ if (enabled) {
+ stats = system_stats;
+ system_stats = NULL;
+ } else {
+ discard_stats();
+ }
+ }
+ ovs_mutex_unlock(&mutex);
+
+ return stats;