From patchwork Wed Apr 18 08:35:23 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Anton Vorontsov X-Patchwork-Id: 7912 Return-Path: X-Original-To: patchwork@peony.canonical.com Delivered-To: patchwork@peony.canonical.com Received: from fiordland.canonical.com (fiordland.canonical.com [91.189.94.145]) by peony.canonical.com (Postfix) with ESMTP id 6102623E42 for ; Wed, 18 Apr 2012 08:36:39 +0000 (UTC) Received: from mail-iy0-f180.google.com (mail-iy0-f180.google.com [209.85.210.180]) by fiordland.canonical.com (Postfix) with ESMTP id 0E547A18839 for ; Wed, 18 Apr 2012 08:36:38 +0000 (UTC) Received: by iage36 with SMTP id e36so13882061iag.11 for ; Wed, 18 Apr 2012 01:36:38 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=x-forwarded-to:x-forwarded-for:delivered-to:received-spf:date:from :to:cc:subject:message-id:references:mime-version:content-type :content-disposition:in-reply-to:user-agent:x-gm-message-state; bh=WmLL6G4xUaWIBAo6q4eYqlJeFR/Nqd5sX2x1Us1X8as=; b=l18czuLnNzdI11HjiDTKq/PKtnI029goGxfUxjhXvS9+8kXqcWfMbZgX2vdnj6loTi DmjZzwjfbVEBAOQBa32JRr9ZFYJBpnrAI570tOwmyJopXu1CQP3Tot40Al108sQFUuem cr6YR4vCDCkYST86foxA7HX9TaP29suLPhGxL07eq8kJOMtkO1RZV6MTPTiTFaB3QfOy uy8AnF9SjQAh1qa4hajoRzGvWIfGUZ8EC7rHOpl92lWX4iyGqXF/NZmav9SBofORsJHd S0/p1+3oYbQP+H9n8QTvdcYOo3qndilFAdQ/+dLYpH6XNCNi+rwFXj36V1WOPtuaHKFx w7TQ== Received: by 10.50.185.233 with SMTP id ff9mr12168806igc.55.1334738198481; Wed, 18 Apr 2012 01:36:38 -0700 (PDT) X-Forwarded-To: linaro-patchwork@canonical.com X-Forwarded-For: patch@linaro.org linaro-patchwork@canonical.com Delivered-To: patches@linaro.org Received: by 10.231.137.198 with SMTP id x6csp202465ibt; Wed, 18 Apr 2012 01:36:38 -0700 (PDT) Received: by 10.60.2.198 with SMTP id 6mr1727017oew.34.1334738197932; Wed, 18 Apr 2012 01:36:37 -0700 (PDT) Received: from mail-ob0-f178.google.com (mail-ob0-f178.google.com [209.85.214.178]) by mx.google.com with ESMTPS id rz10si11597678obc.119.2012.04.18.01.36.37 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 18 Apr 2012 01:36:37 -0700 (PDT) Received-SPF: neutral (google.com: 209.85.214.178 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) client-ip=209.85.214.178; Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.214.178 is neither permitted nor denied by best guess record for domain of anton.vorontsov@linaro.org) smtp.mail=anton.vorontsov@linaro.org Received: by obbwc18 with SMTP id wc18so1145887obb.37 for ; Wed, 18 Apr 2012 01:36:37 -0700 (PDT) Received: by 10.182.169.41 with SMTP id ab9mr1810101obc.4.1334738197665; Wed, 18 Apr 2012 01:36:37 -0700 (PDT) Received: from localhost ([69.199.155.45]) by mx.google.com with ESMTPS id yw3sm26217615obb.7.2012.04.18.01.36.35 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 18 Apr 2012 01:36:36 -0700 (PDT) Date: Wed, 18 Apr 2012 01:35:23 -0700 From: Anton Vorontsov To: Pekka Enberg Cc: Leonid Moiseichuk , John Stultz , linux-mm@kvack.org, linux-kernel@vger.kernel.org, linaro-kernel@lists.linaro.org, patches@linaro.org Subject: [PATCH 2/2] vmevent: Implement greater-than attribute and one-shot mode Message-ID: <20120418083523.GB31556@lizard> References: <20120418083208.GA24904@lizard> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20120418083208.GA24904@lizard> User-Agent: Mutt/1.5.21 (2010-09-15) X-Gm-Message-State: ALoCoQnAVUYAj+uj5esodYJqADYjzoR08y22RtNvLPWxJKPC60VhODuGCt44sOPVGktOwue0uTc+ This patch implements a new event type, it will trigger whenever a value becomes greater than user-specified threshold, it complements the 'less-then' trigger type. Also, let's implement the one-shot mode for the events, when set, userspace will only receive one notification per crossing the boundaries. Now when both LT and GT are set on the same level, the event type works as a cross event type: it triggers whenever a value crosses the threshold from a lesser values side to a greater values side, and vice versa. We use the event types in an userspace low-memory killer: we get a notification when memory becomes low, so we start freeing memory by killing unneeded processes, and we get notification when memory hits the threshold from another side, so we know that we freed enough of memory. Signed-off-by: Anton Vorontsov --- include/linux/vmevent.h | 13 ++++++++++ mm/vmevent.c | 44 +++++++++++++++++++++++++++++----- tools/testing/vmevent/vmevent-test.c | 22 +++++++++++++---- 3 files changed, 68 insertions(+), 11 deletions(-) diff --git a/include/linux/vmevent.h b/include/linux/vmevent.h index 64357e4..ca97cf0 100644 --- a/include/linux/vmevent.h +++ b/include/linux/vmevent.h @@ -22,6 +22,19 @@ enum { * Sample value is less than user-specified value */ VMEVENT_ATTR_STATE_VALUE_LT = (1UL << 0), + /* + * Sample value is greater than user-specified value + */ + VMEVENT_ATTR_STATE_VALUE_GT = (1UL << 1), + /* + * One-shot mode. + */ + VMEVENT_ATTR_STATE_ONE_SHOT = (1UL << 2), + + /* Saved state, used internally by the kernel for one-shot mode. */ + __VMEVENT_ATTR_STATE_VALUE_WAS_LT = (1UL << 30), + /* Saved state, used internally by the kernel for one-shot mode. */ + __VMEVENT_ATTR_STATE_VALUE_WAS_GT = (1UL << 31), }; struct vmevent_attr { diff --git a/mm/vmevent.c b/mm/vmevent.c index 9ed6aca..3cce215 100644 --- a/mm/vmevent.c +++ b/mm/vmevent.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -83,16 +84,47 @@ static bool vmevent_match(struct vmevent_watch *watch) for (i = 0; i < config->counter; i++) { struct vmevent_attr *attr = &config->attrs[i]; - u64 value; + u32 state = attr->state; + bool attr_lt = state & VMEVENT_ATTR_STATE_VALUE_LT; + bool attr_gt = state & VMEVENT_ATTR_STATE_VALUE_GT; - if (!attr->state) + if (!state) continue; - value = vmevent_sample_attr(watch, attr); - - if (attr->state & VMEVENT_ATTR_STATE_VALUE_LT) { - if (value < attr->value) + if (attr_lt || attr_gt) { + bool one_shot = state & VMEVENT_ATTR_STATE_ONE_SHOT; + u32 was_lt_mask = __VMEVENT_ATTR_STATE_VALUE_WAS_LT; + u32 was_gt_mask = __VMEVENT_ATTR_STATE_VALUE_WAS_GT; + u64 value = vmevent_sample_attr(watch, attr); + bool lt = value < attr->value; + bool gt = value > attr->value; + bool was_lt = state & was_lt_mask; + bool was_gt = state & was_gt_mask; + bool ret = false; + + if ((lt || gt) && !one_shot) return true; + + if (attr_lt && lt && was_lt) { + return false; + } else if (attr_gt && gt && was_gt) { + return false; + } else if (lt) { + state |= was_lt_mask; + state &= ~was_gt_mask; + if (attr_lt) + ret = true; + } else if (gt) { + state |= was_gt_mask; + state &= ~was_lt_mask; + if (attr_gt) + ret = true; + } else { + state &= ~was_lt_mask; + state &= ~was_gt_mask; + } + attr->state = state; + return ret; } } diff --git a/tools/testing/vmevent/vmevent-test.c b/tools/testing/vmevent/vmevent-test.c index 534f827..fec7b57 100644 --- a/tools/testing/vmevent/vmevent-test.c +++ b/tools/testing/vmevent/vmevent-test.c @@ -33,20 +33,32 @@ int main(int argc, char *argv[]) config = (struct vmevent_config) { .sample_period_ns = 1000000000L, - .counter = 4, + .counter = 6, .attrs = { - [0] = { + { .type = VMEVENT_ATTR_NR_FREE_PAGES, .state = VMEVENT_ATTR_STATE_VALUE_LT, .value = phys_pages, }, - [1] = { + { + .type = VMEVENT_ATTR_NR_FREE_PAGES, + .state = VMEVENT_ATTR_STATE_VALUE_GT, + .value = phys_pages, + }, + { + .type = VMEVENT_ATTR_NR_FREE_PAGES, + .state = VMEVENT_ATTR_STATE_VALUE_LT | + VMEVENT_ATTR_STATE_VALUE_GT | + VMEVENT_ATTR_STATE_ONE_SHOT, + .value = phys_pages / 2, + }, + { .type = VMEVENT_ATTR_NR_AVAIL_PAGES, }, - [2] = { + { .type = VMEVENT_ATTR_NR_SWAP_PAGES, }, - [3] = { + { .type = 0xffff, /* invalid */ }, },