[U-Boot] [PATCH v5 06/19] hashtable: support multiple env contexts

AKASHI Takahiro takahiro.akashi at linaro.org
Thu Sep 5 08:21:20 UTC 2019


With this patch, variable's context is always honored in all operations,
FIND/ENTER (including delete).

Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
---
 include/search.h |  6 +++++-
 lib/hashtable.c  | 14 +++++++++++---
 2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/include/search.h b/include/search.h
index 0469a852e07c..202cf652de5f 100644
--- a/include/search.h
+++ b/include/search.h
@@ -25,13 +25,16 @@ enum env_action {
 	ENV_ENTER,
 };
 
+struct env_context;
+
 /** struct env_entry - An entry in the environment hashtable */
 struct env_entry {
 	const char *key;
 	char *data;
 	int (*callback)(const char *name, const char *value, enum env_op op,
-		int flags);
+			int flags);
 	int flags;
+	struct env_context *ctx;
 };
 
 /*
@@ -45,6 +48,7 @@ struct hsearch_data {
 	struct env_entry_node *table;
 	unsigned int size;
 	unsigned int filled;
+	struct env_context *ctx;
 /*
  * Callback function which will check whether the given change for variable
  * "item" to "newval" may be applied or not, and possibly apply such change.
diff --git a/lib/hashtable.c b/lib/hashtable.c
index 2caab0a4c6d3..8fe017470256 100644
--- a/lib/hashtable.c
+++ b/lib/hashtable.c
@@ -231,6 +231,7 @@ static inline int _compare_and_overwrite_entry(struct env_entry item,
 		unsigned int idx)
 {
 	if (htab->table[idx].used == hval
+	    && (item.ctx && (item.ctx == htab->table[idx].entry.ctx))
 	    && strcmp(item.key, htab->table[idx].entry.key) == 0) {
 		/* Overwrite existing value? */
 		if (action == ENV_ENTER && item.data) {
@@ -247,8 +248,9 @@ static inline int _compare_and_overwrite_entry(struct env_entry item,
 
 			/* If there is a callback, call it */
 			if (htab->table[idx].entry.callback &&
-			    htab->table[idx].entry.callback(item.key,
-			    item.data, env_op_overwrite, flag)) {
+			    htab->table[idx].entry.callback(item.key, item.data,
+							    env_op_overwrite,
+							    flag)) {
 				debug("callback() rejected setting variable "
 					"%s, skipping it!\n", item.key);
 				__set_errno(EINVAL);
@@ -340,6 +342,9 @@ int hsearch_r(struct env_entry item, enum env_action action,
 			if (idx == hval)
 				break;
 
+			if (htab->table[idx].used == USED_FREE)
+				break;
+
 			if (htab->table[idx].used == USED_DELETED
 			    && !first_deleted)
 				first_deleted = idx;
@@ -381,6 +386,7 @@ int hsearch_r(struct env_entry item, enum env_action action,
 			*retval = NULL;
 			return 0;
 		}
+		htab->table[idx].entry.ctx = item.ctx;
 
 		++htab->filled;
 
@@ -403,7 +409,7 @@ int hsearch_r(struct env_entry item, enum env_action action,
 		/* If there is a callback, call it */
 		if (htab->table[idx].entry.callback &&
 		    htab->table[idx].entry.callback(item.key, item.data,
-		    env_op_create, flag)) {
+						    env_op_create, flag)) {
 			debug("callback() rejected setting variable "
 				"%s, skipping it!\n", item.key);
 			_hdelete(item.key, htab, &htab->table[idx].entry, idx);
@@ -454,6 +460,7 @@ int hdelete_r(const char *key, struct hsearch_data *htab, int flag)
 
 	debug("hdelete: DELETE key \"%s\"\n", key);
 
+	e.ctx = htab->ctx;
 	e.key = (char *)key;
 
 	idx = hsearch_r(e, ENV_FIND, &ep, htab, 0);
@@ -928,6 +935,7 @@ int himport_r(struct hsearch_data *htab,
 			continue;
 
 		/* enter into hash table */
+		e.ctx = htab->ctx;
 		e.key = name;
 		e.data = value;
 
-- 
2.21.0



More information about the U-Boot mailing list