From: gh@us.ibm.com
To: linux-kernel@vger.kernel.org, ckrm-tech@lists.sourceforge.net
Subject: [patch 17/21] CKRM: Rule Based Classification Engine, bitvector support for classification info
Date: Thu, 05 May 2005 11:07:48 -0700 [thread overview]
Message-ID: <20050505180934.756643000@us.ibm.com> (raw)
In-Reply-To: 20050505180731.010896000@us.ibm.com
--
Content-Disposition: inline; filename=09-03-rbce_main-opt
Part 3 of 5 patches to support Rule Based Classification Engine for CKRM.
This patch provides some optimization by maintaining the classification
information in the vectors. No classification functionality yet.
Signed-Off-By: Hubertus Franke <frankeh@us.ibm.com>
Signed-Off-By: Chandra Seetharaman <sekharan@us.ibm.com>
Signed-Off-By: Shailabh Nagar <nagar@us.ibm.com>
Signed-Off-By: Vivek Kashyap <vivk@us.ibm.com>
Signed-Off-By: Gerrit Huizenga <gh@us.ibm.com>
rbce_bitvector.h | 146 +++++++++++++++++++++++++++++++++++++++++++++++
rbce_internal.h | 19 +++++-
rbce_main.c | 168 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 330 insertions(+), 3 deletions(-)
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_bitvector.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_bitvector.h 2005-05-05 09:38:05.000000000 -0700
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) Hubertus Franke, IBM Corp. 2003
+ *
+ * Bitvector package
+ *
+ * Latest version, more details at http://ckrm.sf.net
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ */
+
+#ifndef _RBCE_BITVECTOR_H
+#define _RBCE_BITVECTOR_H
+
+typedef struct {
+ int size; /* maxsize in longs */
+ unsigned long bits[0]; /* bit vector */
+} bitvector_t;
+
+#define BITS_2_LONGS(sz) (((sz)+BITS_PER_LONG-1)/BITS_PER_LONG)
+#define BITS_2_BYTES(sz) (((sz)+7)/8)
+
+#if 0
+#define CHECK_VEC(vec) (vec) /* check against NULL */
+#else
+#define CHECK_VEC(vec) (1) /* assume no problem */
+#endif
+
+#define CHECK_VEC_VOID(vec) do { if (!CHECK_VEC(vec)) return; } while(0)
+#define CHECK_VEC_RC(vec, val) \
+do { if (!CHECK_VEC(vec)) return (val); } while(0)
+
+inline static void bitvector_zero(bitvector_t * bitvec)
+{
+ int sz;
+
+ CHECK_VEC_VOID(bitvec);
+ sz = BITS_2_BYTES(bitvec->size);
+ memset(bitvec->bits, 0, sz);
+ return;
+}
+
+inline static unsigned long bitvector_bytes(unsigned long size)
+{
+ return sizeof(bitvector_t) + BITS_2_BYTES(size);
+}
+
+inline static void bitvector_init(bitvector_t * bitvec, unsigned long size)
+{
+ bitvec->size = size;
+ bitvector_zero(bitvec);
+ return;
+}
+
+inline static bitvector_t *bitvector_alloc(unsigned long size)
+{
+ bitvector_t *vec =
+ (bitvector_t *) kmalloc(bitvector_bytes(size), GFP_KERNEL);
+ if (vec) {
+ vec->size = size;
+ bitvector_zero(vec);
+ }
+ return vec;
+}
+
+inline static void bitvector_free(bitvector_t * bitvec)
+{
+ CHECK_VEC_VOID(bitvec);
+ kfree(bitvec);
+ return;
+}
+
+#define def_bitvec_op(name,mod1,op,mod2) \
+inline static int name(bitvector_t *res, bitvector_t *op1, \
+ bitvector_t *op2) \
+{ \
+ unsigned int i, size; \
+ \
+ CHECK_VEC_RC(res, 0); \
+ CHECK_VEC_RC(op1, 0); \
+ CHECK_VEC_RC(op2, 0); \
+ size = res->size; \
+ if (((size != (op1)->size) || (size != (op2)->size))) { \
+ return 0; \
+ } \
+ size = BITS_2_LONGS(size); \
+ for (i = 0; i < size; i++) { \
+ (res)->bits[i] = (mod1 (op1)->bits[i]) op \
+ (mod2 (op2)->bits[i]); \
+ } \
+ return 1; \
+}
+
+def_bitvec_op(bitvector_or,, |,);
+def_bitvec_op(bitvector_and,, &,);
+def_bitvec_op(bitvector_xor,, ^,);
+def_bitvec_op(bitvector_or_not,, |, ~);
+def_bitvec_op(bitvector_not_or, ~, |,);
+def_bitvec_op(bitvector_and_not,, &, ~);
+def_bitvec_op(bitvector_not_and, ~, &,);
+
+inline static void bitvector_set(int idx, bitvector_t * vec)
+{
+ set_bit(idx, vec->bits);
+ return;
+}
+
+inline static void bitvector_clear(int idx, bitvector_t * vec)
+{
+ clear_bit(idx, vec->bits);
+ return;
+}
+
+inline static int bitvector_test(int idx, bitvector_t * vec)
+{
+ return test_bit(idx, vec->bits);
+}
+
+#ifdef DEBUG
+inline static void bitvector_print(int flag, bitvector_t * vec)
+{
+ unsigned int i;
+ int sz;
+ extern int rbcedebug;
+
+ if ((rbcedebug & flag) == 0) {
+ return;
+ }
+ if (vec == NULL) {
+ printk("v<0>-NULL\n");
+ return;
+ }
+ printk("v<%d>-", sz = vec->size);
+ for (i = 0; i < sz; i++) {
+ printk("%c", test_bit(i, vec->bits) ? '1' : '0');
+ }
+ return;
+}
+#else
+#define bitvector_print(x, y)
+#endif
+
+#endif /* _RBCE_BITVECTOR_H */
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_internal.h
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/rbce_internal.h 2005-05-05 09:38:03.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_internal.h 2005-05-05 09:38:05.000000000 -0700
@@ -51,6 +51,8 @@ struct named_obj_hdr {
char *name;
};
+#include "rbce_bitvector.h"
+
#define GET_REF(x) ((x)->obj.referenced)
#define INC_REF(x) (GET_REF(x)++)
#define DEC_REF(x) (--GET_REF(x))
@@ -185,14 +187,25 @@ enum op_token {
TOKEN_OP_STATE = (__force op_token_t) (TOKEN_OP_GREATER_THAN+6),
};
-
/*
- * data structure rbce_private_data to hold the app_tag for a task.
- * Expands later.
+ * data structure rbce_private_data holds the bit vector 'eval' which
+ * specifies if rules and terms of rules are evaluated against the task
+ * and if they were evaluated, bit vector 'true' holds the result of that
+ * evaluation.
+ *
+ * This data structure is maintained in a task, and the bitvectors are
+ * updated only when needed.
+ *
+ * Each rule and each term of a rule has a corresponding bit in the vector.
*
*/
struct rbce_private_data {
+ int evaluate; /* whether to evaluate rules or not ? */
+ int rules_version; /* rules_version at last evaluation */
+ bitvector_t *eval;
+ bitvector_t *true;
char *app_tag;
+ char data[0]; /* bitvectors eval and true */
};
#define RBCE_DATA(tsk) ((struct rbce_private_data*)((tsk)->ce_data))
Index: linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_main.c
===================================================================
--- linux-2.6.12-rc3-ckrm5.orig/kernel/ckrm/rbce/rbce_main.c 2005-05-05 09:38:03.000000000 -0700
+++ linux-2.6.12-rc3-ckrm5/kernel/ckrm/rbce/rbce_main.c 2005-05-05 09:38:05.000000000 -0700
@@ -23,6 +23,7 @@
*/
#include "rbce_internal.h"
+#include "rbce_bitvector.h"
MODULE_DESCRIPTION(RBCE_MOD_DESCR);
MODULE_AUTHOR("Hubertus Franke, Chandra Seetharaman (IBM)");
@@ -57,14 +58,17 @@ int termop_2_vecidx[RBCE_RULE_INVALID] =
extern int errno;
int rbce_enabled = 1;
+const int use_persistent_state = 1;
static LIST_HEAD(class_list);
static struct list_head rules_list[CKRM_MAX_CLASSTYPES];
static int gl_num_rules;
static int gl_action, gl_num_terms;
+static int gl_bitmap_version, gl_action, gl_num_terms;
static int gl_allocated, gl_released;
static struct rbce_rule_term *gl_terms;
static int gl_rules_version;
+static bitvector_t *gl_mask_vecs[NUM_TERM_MASK_VECTOR];
static rwlock_t rbce_rwlock = RW_LOCK_UNLOCKED;
/*
* One lock to protect them all !!!
@@ -78,6 +82,8 @@ static rwlock_t rbce_rwlock = RW_LOCK_UN
/* ======================= Helper Functions ========================= */
+static void optimize_policy(void);
+
static inline struct rbce_rule *find_rule_name(const char *name)
{
struct named_obj_hdr *pos;
@@ -159,6 +165,8 @@ static int insert_rule(struct rbce_rule
}
gl_rules_version++;
list_add_tail(&rule->obj.link, insert);
+ if (rbce_enabled)
+ optimize_policy();
return 0;
}
@@ -337,9 +345,150 @@ static inline int __delete_rule(struct r
module_put(THIS_MODULE);
kfree(rule->obj.name);
kfree(rule);
+ if (rbce_enabled && (gl_action & POLICY_ACTION_PACK_TERMS))
+ optimize_policy();
return 0;
}
+/*
+ * Optimize the rule evaluation logic
+ *
+ * Caller must hold global_rwlock in write mode.
+ */
+static void optimize_policy(void)
+{
+ int i, ii;
+ struct rbce_rule *rule;
+ struct rbce_rule_term *terms;
+ int num_terms;
+ int bsize;
+ bitvector_t **mask_vecs;
+ int pack_terms = 0;
+ int redoall;
+
+ /*
+ * Due to dynamic rule addition/deletion of rules the term
+ * vector can get sparse. As a result the bitvectors grow as we don't
+ * reuse returned indices. If it becomes sparse enough we pack them
+ * closer.
+ */
+
+ pack_terms = (gl_action & POLICY_ACTION_PACK_TERMS);
+
+ if (pack_terms) {
+ int nsz = ALIGN((gl_num_terms - gl_released),
+ POLICY_INC_NUMTERMS);
+ int newidx = 0;
+ struct rbce_rule_term *newterms;
+
+ terms = gl_terms;
+ newterms =
+ kmalloc(nsz * sizeof(struct rbce_rule_term), GFP_ATOMIC);
+ if (newterms) {
+ for (ii = 0; ii < CKRM_MAX_CLASSTYPES; ii++) {
+ /* FIXME: check only for task class types */
+ list_for_each_entry_reverse(rule,
+ &rules_list[ii],
+ obj.link) {
+ rule->index = newidx++;
+ for (i = rule->num_terms; --i >= 0;) {
+ int idx = rule->terms[i];
+ newterms[newidx] = terms[idx];
+ rule->terms[i] = newidx++;
+ }
+ }
+ }
+ kfree(terms);
+ gl_allocated = nsz;
+ gl_released = 0;
+ gl_num_terms = newidx;
+ gl_terms = newterms;
+
+ gl_action &= ~POLICY_ACTION_PACK_TERMS;
+ gl_action |= POLICY_ACTION_NEW_VERSION;
+ }
+ }
+
+ num_terms = gl_num_terms;
+ bsize = gl_allocated / 8 + sizeof(bitvector_t);
+ mask_vecs = gl_mask_vecs;
+ terms = gl_terms;
+
+ if (gl_action & POLICY_ACTION_NEW_VERSION) {
+ /* allocate new mask vectors */
+ char *temp = kmalloc(NUM_TERM_MASK_VECTOR * bsize, GFP_ATOMIC);
+
+ if (!temp) {
+ return;
+ }
+ if (mask_vecs[0]) {/* index 0 has the alloc returned address */
+ kfree(mask_vecs[0]);
+ }
+ for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
+ mask_vecs[i] = (bitvector_t *) (temp + i * bsize);
+ bitvector_init(mask_vecs[i], gl_allocated);
+ }
+ gl_action &= ~POLICY_ACTION_NEW_VERSION;
+ gl_action |= POLICY_ACTION_REDO_ALL;
+ gl_bitmap_version++;
+ }
+
+ /* We do two things here at once
+ * 1) recompute the rulemask for each required rule
+ * we guarantee proper dependency order during creation time and
+ * by reversely running through this list.
+ * 2) recompute the mask for each term and rule, if required
+ */
+
+ redoall = gl_action & POLICY_ACTION_REDO_ALL;
+ gl_action &= ~POLICY_ACTION_REDO_ALL;
+
+ for (ii = 0; ii < CKRM_MAX_CLASSTYPES; ii++) {
+ /* FIXME: check only for task class types */
+ list_for_each_entry_reverse(rule, &rules_list[ii], obj.link) {
+ unsigned long termflag;
+
+ if (!redoall && !rule->do_opt)
+ continue;
+ termflag = 0;
+ for (i = rule->num_terms; --i >= 0;) {
+ int j, idx = rule->terms[i];
+ struct rbce_rule_term *term = &terms[idx];
+ int vecidx = termop_2_vecidx[term->op];
+
+ if (vecidx == -1) {
+ termflag |= term->u.deprule->termflag;
+ /* mark this term belonging to all
+ contexts of deprule */
+ for (j = 0; j < NUM_TERM_MASK_VECTOR;
+ j++) {
+ if (term->u.deprule->termflag
+ & (1 << j)) {
+ bitvector_set(idx,
+ mask_vecs
+ [j]);
+ }
+ }
+ } else {
+ termflag |= TERM_2_TERMFLAG(vecidx);
+ /* mark this term belonging to
+ a particular context */
+ bitvector_set(idx, mask_vecs[vecidx]);
+ }
+ }
+ for (i = 0; i < NUM_TERM_MASK_VECTOR; i++) {
+ if (termflag & (1 << i)) {
+ bitvector_set(rule->index,
+ mask_vecs[i]);
+ }
+ }
+ rule->termflag = termflag;
+ rule->do_opt = 0;
+ }
+ }
+ return;
+}
+
/* ======================= Rule related Functions ========================= */
/*
@@ -984,6 +1133,25 @@ struct rbce_private_data *create_private
return NULL;
}
+static inline
+void reset_evaluation(struct rbce_private_data *pdata,int termflag)
+{
+ /* reset TAG ruleterm evaluation results to pick up
+ * on next classification event
+ */
+ if (termflag >= NUM_TERM_MASK_VECTOR) {
+ printk(KERN_ERR "rbce:reset_evaluation: trying to access "
+ "past valid address\n");
+ return;
+ }
+ if (use_persistent_state && gl_mask_vecs[termflag]) {
+ bitvector_and_not( pdata->eval, pdata->eval,
+ gl_mask_vecs[termflag] );
+ bitvector_and_not( pdata->true, pdata->true,
+ gl_mask_vecs[termflag] );
+ }
+}
+
int rbce_set_tasktag(int pid, char *tag)
{
char *tp;
--
next prev parent reply other threads:[~2005-05-05 19:16 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2005-05-05 18:07 [patch 00/21] CKRM: Core patch set with Classification Engine, basic controllers gh
2005-05-05 18:07 ` [patch 01/21] CKRM: Core CKRM Event Callbacks gh
2005-05-05 18:07 ` [patch 02/21] CKRM: Processor Delay Accounting gh
2005-05-05 18:07 ` [patch 03/21] CKRM: Core infrastructure gh
2005-05-05 18:07 ` [patch 04/21] CKRM: Resource Control File System (rcfs) gh
2005-05-05 18:07 ` [patch 05/21] CKRM: Classtype definitions for task class gh
2005-05-05 18:07 ` [patch 06/21] CKRM: Classtype definitions for socket class gh
2005-05-05 18:07 ` [patch 07/21] CKRM: Numtasks Controller gh
2005-05-05 18:07 ` [patch 08/21] CKRM: Documentation gh
2005-05-05 18:07 ` [patch 09/21] CKRM: Add missing read_unlock gh
2005-05-05 18:07 ` [patch 10/21] CKRM: Move Callbacks from listenaq to socketclass gh
2005-05-05 18:07 ` [patch 11/21] CKRM: Change ipaddr_port syntax gh
2005-05-05 18:07 ` [patch 12/21] CKRM: Check to see if my guarantee is set to DONTCARE gh
2005-05-05 18:07 ` [patch 13/21] CKRM: Minor cosmetic cleanups in numtasks controller gh
2005-05-05 18:07 ` [patch 14/21] CKRM: undo removal of check in numtasks_put_ref_local gh
2005-05-05 18:07 ` [patch 15/21] CKRM: Rule Based Classification Engine, stub rcfs support gh
2005-05-05 18:07 ` [patch 16/21] CKRM: Rule Based Classification Engine, basic " gh
2005-05-05 18:07 ` gh [this message]
2005-05-05 18:07 ` [patch 18/21] CKRM: Rule Based Classification Engine, full CE gh
2005-05-05 18:07 ` [patch 19/21] CKRM: Rule Based Classification Engine, more advanced classification engine gh
2005-05-05 18:07 ` [patch 20/21] CKRM: Clean up typo in printk message gh
2005-05-05 18:07 ` [patch 21/21] CKRM: Fix for compiler warnings gh
2005-05-08 12:49 ` Domen Puncer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20050505180934.756643000@us.ibm.com \
--to=gh@us.ibm.com \
--cc=ckrm-tech@lists.sourceforge.net \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.