get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/11696/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 11696,
    "url": "http://patches.dpdk.org/api/patches/11696/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/1458827804-25496-1-git-send-email-pablo.de.lara.guarch@intel.com/",
    "project": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/projects/1/?format=api",
        "name": "DPDK",
        "link_name": "dpdk",
        "list_id": "dev.dpdk.org",
        "list_email": "dev@dpdk.org",
        "web_url": "http://core.dpdk.org",
        "scm_url": "git://dpdk.org/dpdk",
        "webscm_url": "http://git.dpdk.org/dpdk",
        "list_archive_url": "https://inbox.dpdk.org/dev",
        "list_archive_url_format": "https://inbox.dpdk.org/dev/{}",
        "commit_url_format": ""
    },
    "msgid": "<1458827804-25496-1-git-send-email-pablo.de.lara.guarch@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1458827804-25496-1-git-send-email-pablo.de.lara.guarch@intel.com",
    "date": "2016-03-24T13:56:44",
    "name": "[dpdk-dev] hash: fix to support multi process",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "7c422f61f39df7edd86a9fb03b7198263b5aa3d5",
    "submitter": {
        "id": 9,
        "url": "http://patches.dpdk.org/api/people/9/?format=api",
        "name": "De Lara Guarch, Pablo",
        "email": "pablo.de.lara.guarch@intel.com"
    },
    "delegate": {
        "id": 1,
        "url": "http://patches.dpdk.org/api/users/1/?format=api",
        "username": "tmonjalo",
        "first_name": "Thomas",
        "last_name": "Monjalon",
        "email": "thomas@monjalon.net"
    },
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/1458827804-25496-1-git-send-email-pablo.de.lara.guarch@intel.com/mbox/",
    "series": [],
    "comments": "http://patches.dpdk.org/api/patches/11696/comments/",
    "check": "pending",
    "checks": "http://patches.dpdk.org/api/patches/11696/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@dpdk.org",
        "Delivered-To": "patchwork@dpdk.org",
        "Received": [
            "from [92.243.14.124] (localhost [IPv6:::1])\n\tby dpdk.org (Postfix) with ESMTP id 9AFB22BF5;\n\tThu, 24 Mar 2016 14:53:57 +0100 (CET)",
            "from mga02.intel.com (mga02.intel.com [134.134.136.20])\n\tby dpdk.org (Postfix) with ESMTP id 4AAF72BE3\n\tfor <dev@dpdk.org>; Thu, 24 Mar 2016 14:53:56 +0100 (CET)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby orsmga101.jf.intel.com with ESMTP; 24 Mar 2016 06:53:55 -0700",
            "from sie-lab-212-116.ir.intel.com (HELO localhost.ir.intel.com)\n\t([10.237.212.116])\n\tby fmsmga001.fm.intel.com with ESMTP; 24 Mar 2016 06:53:54 -0700"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.24,385,1455004800\"; d=\"scan'208\";a=\"930917983\"",
        "From": "Pablo de Lara <pablo.de.lara.guarch@intel.com>",
        "To": "dev@dpdk.org",
        "Cc": "bruce.richardson@intel.com, edreddy@gmail.com,\n\tPablo de Lara <pablo.de.lara.guarch@intel.com>",
        "Date": "Thu, 24 Mar 2016 13:56:44 +0000",
        "Message-Id": "<1458827804-25496-1-git-send-email-pablo.de.lara.guarch@intel.com>",
        "X-Mailer": "git-send-email 2.5.0",
        "Subject": "[dpdk-dev] [PATCH] hash: fix to support multi process",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "patches and discussions about DPDK <dev.dpdk.org>",
        "List-Unsubscribe": "<http://dpdk.org/ml/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://dpdk.org/ml/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<http://dpdk.org/ml/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Hash library used a function pointer to choose a different\nkey compare function, depending on the key size.\nAs a result, multiple processes could not use the same hash table,\nas the function addresses vary from one process to another.\n\nInstead, a jump table is used, so each process has its own\nfunction addresses, accessing this table with an index stored\nin the hash table (note that using a custom key compare function\nis not supported in multi-process mode).\n\nFixes: 48a399119619 (\"hash: replace with cuckoo hash implementation\")\n\nSigned-off-by: Pablo de Lara <pablo.de.lara.guarch@intel.com>\n---\n doc/guides/rel_notes/release_16_04.rst |  5 ++\n lib/librte_hash/rte_cuckoo_hash.c      | 85 ++++++++++++++++++++++++++--------\n 2 files changed, 71 insertions(+), 19 deletions(-)",
    "diff": "diff --git a/doc/guides/rel_notes/release_16_04.rst b/doc/guides/rel_notes/release_16_04.rst\nindex 2785b29..c4359dd 100644\n--- a/doc/guides/rel_notes/release_16_04.rst\n+++ b/doc/guides/rel_notes/release_16_04.rst\n@@ -351,6 +351,11 @@ Libraries\n   Fix crc32c hash functions to return a valid crc32c value for data lengths\n   not multiple of 4 bytes.\n \n+* **hash: Fixed hash library to support multi-process mode.**\n+\n+  Fix hash library to support multi-process mode, using a jump table,\n+  instead of storing a function pointer to the key compare function.\n+\n * **librte_port: Fixed segmentation fault for ring and ethdev writer nodrop.**\n \n   Fixed core dump issue on txq and swq when dropless is set to yes.\ndiff --git a/lib/librte_hash/rte_cuckoo_hash.c b/lib/librte_hash/rte_cuckoo_hash.c\nindex 71b5b76..38c19ab 100644\n--- a/lib/librte_hash/rte_cuckoo_hash.c\n+++ b/lib/librte_hash/rte_cuckoo_hash.c\n@@ -102,6 +102,41 @@ EAL_REGISTER_TAILQ(rte_hash_tailq)\n \n #define LCORE_CACHE_SIZE\t\t8\n \n+/*\n+ * All different options to select a key compare function,\n+ * based on the key size and custom function.\n+ */\n+enum cmp_jump_table_case {\n+\tKEY_CUSTOM = 0,\n+\tKEY_16_BYTES,\n+\tKEY_32_BYTES,\n+\tKEY_48_BYTES,\n+\tKEY_64_BYTES,\n+\tKEY_80_BYTES,\n+\tKEY_96_BYTES,\n+\tKEY_112_BYTES,\n+\tKEY_128_BYTES,\n+\tKEY_OTHER_BYTES,\n+\tNUM_KEY_CMP_CASES,\n+};\n+\n+/*\n+ * Table storing all different key compare functions\n+ * (multi-process supported)\n+ */\n+rte_hash_cmp_eq_t cmp_jump_table[NUM_KEY_CMP_CASES] = {\n+\tNULL,\n+\trte_hash_k16_cmp_eq,\n+\trte_hash_k32_cmp_eq,\n+\trte_hash_k48_cmp_eq,\n+\trte_hash_k64_cmp_eq,\n+\trte_hash_k80_cmp_eq,\n+\trte_hash_k96_cmp_eq,\n+\trte_hash_k112_cmp_eq,\n+\trte_hash_k128_cmp_eq,\n+\tmemcmp\n+};\n+\n struct lcore_cache {\n \tunsigned len; /**< Cache len */\n \tvoid *objs[LCORE_CACHE_SIZE]; /**< Cache objects */\n@@ -115,7 +150,10 @@ struct rte_hash {\n \tuint32_t key_len;               /**< Length of hash key. */\n \trte_hash_function hash_func;    /**< Function used to calculate hash. */\n \tuint32_t hash_func_init_val;    /**< Init value used by hash_func. */\n-\trte_hash_cmp_eq_t rte_hash_cmp_eq; /**< Function used to compare keys. */\n+\trte_hash_cmp_eq_t rte_hash_custom_cmp_eq;\n+\t/**< Custom function used to compare keys. */\n+\tenum cmp_jump_table_case cmp_jump_table_idx;\n+\t/**< Indicates which compare function to use. */\n \tuint32_t bucket_bitmask;        /**< Bitmask for getting bucket index\n \t\t\t\t\t\tfrom hash signature. */\n \tuint32_t key_entry_size;         /**< Size of each key entry. */\n@@ -187,7 +225,16 @@ rte_hash_find_existing(const char *name)\n \n void rte_hash_set_cmp_func(struct rte_hash *h, rte_hash_cmp_eq_t func)\n {\n-\th->rte_hash_cmp_eq = func;\n+\th->rte_hash_custom_cmp_eq = func;\n+}\n+\n+static inline int\n+rte_hash_cmp_eq(const void *key1, const void *key2, const struct rte_hash *h)\n+{\n+\tif (h->cmp_jump_table_idx == KEY_CUSTOM)\n+\t\treturn h->rte_hash_custom_cmp_eq(key1, key2, h->key_len);\n+\telse\n+\t\treturn cmp_jump_table[h->cmp_jump_table_idx](key1, key2, h->key_len);\n }\n \n struct rte_hash *\n@@ -292,35 +339,35 @@ rte_hash_create(const struct rte_hash_parameters *params)\n \t/* Select function to compare keys */\n \tswitch (params->key_len) {\n \tcase 16:\n-\t\th->rte_hash_cmp_eq = rte_hash_k16_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_16_BYTES;\n \t\tbreak;\n \tcase 32:\n-\t\th->rte_hash_cmp_eq = rte_hash_k32_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_32_BYTES;\n \t\tbreak;\n \tcase 48:\n-\t\th->rte_hash_cmp_eq = rte_hash_k48_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_48_BYTES;\n \t\tbreak;\n \tcase 64:\n-\t\th->rte_hash_cmp_eq = rte_hash_k64_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_64_BYTES;\n \t\tbreak;\n \tcase 80:\n-\t\th->rte_hash_cmp_eq = rte_hash_k80_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_80_BYTES;\n \t\tbreak;\n \tcase 96:\n-\t\th->rte_hash_cmp_eq = rte_hash_k96_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_96_BYTES;\n \t\tbreak;\n \tcase 112:\n-\t\th->rte_hash_cmp_eq = rte_hash_k112_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_112_BYTES;\n \t\tbreak;\n \tcase 128:\n-\t\th->rte_hash_cmp_eq = rte_hash_k128_cmp_eq;\n+\t\th->cmp_jump_table_idx = KEY_128_BYTES;\n \t\tbreak;\n \tdefault:\n \t\t/* If key is not multiple of 16, use generic memcmp */\n-\t\th->rte_hash_cmp_eq = memcmp;\n+\t\th->cmp_jump_table_idx = KEY_OTHER_BYTES;\n \t}\n #else\n-\th->rte_hash_cmp_eq = memcmp;\n+\th->cmp_jump_table_idx = KEY_OTHER_BYTES;\n #endif\n \n \tsnprintf(ring_name, sizeof(ring_name), \"HT_%s\", params->name);\n@@ -594,7 +641,7 @@ __rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key,\n \t\t\t\tprim_bkt->signatures[i].alt == alt_hash) {\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tprim_bkt->key_idx[i] * h->key_entry_size);\n-\t\t\tif (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {\n+\t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n \t\t\t\t/* Enqueue index of free slot back in the ring. */\n \t\t\t\tenqueue_slot_back(h, cached_free_slots, slot_id);\n \t\t\t\t/* Update data */\n@@ -614,7 +661,7 @@ __rte_hash_add_key_with_hash(const struct rte_hash *h, const void *key,\n \t\t\t\tsec_bkt->signatures[i].current == alt_hash) {\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tsec_bkt->key_idx[i] * h->key_entry_size);\n-\t\t\tif (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {\n+\t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n \t\t\t\t/* Enqueue index of free slot back in the ring. */\n \t\t\t\tenqueue_slot_back(h, cached_free_slots, slot_id);\n \t\t\t\t/* Update data */\n@@ -725,7 +772,7 @@ __rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key,\n \t\t\t\tbkt->signatures[i].sig != NULL_SIGNATURE) {\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tbkt->key_idx[i] * h->key_entry_size);\n-\t\t\tif (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {\n+\t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n \t\t\t\tif (data != NULL)\n \t\t\t\t\t*data = k->pdata;\n \t\t\t\t/*\n@@ -748,7 +795,7 @@ __rte_hash_lookup_with_hash(const struct rte_hash *h, const void *key,\n \t\t\t\tbkt->signatures[i].alt == sig) {\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tbkt->key_idx[i] * h->key_entry_size);\n-\t\t\tif (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {\n+\t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n \t\t\t\tif (data != NULL)\n \t\t\t\t\t*data = k->pdata;\n \t\t\t\t/*\n@@ -840,7 +887,7 @@ __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key,\n \t\t\t\tbkt->signatures[i].sig != NULL_SIGNATURE) {\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tbkt->key_idx[i] * h->key_entry_size);\n-\t\t\tif (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {\n+\t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n \t\t\t\tremove_entry(h, bkt, i);\n \n \t\t\t\t/*\n@@ -863,7 +910,7 @@ __rte_hash_del_key_with_hash(const struct rte_hash *h, const void *key,\n \t\t\t\tbkt->signatures[i].sig != NULL_SIGNATURE) {\n \t\t\tk = (struct rte_hash_key *) ((char *)keys +\n \t\t\t\t\tbkt->key_idx[i] * h->key_entry_size);\n-\t\t\tif (h->rte_hash_cmp_eq(key, k->key, h->key_len) == 0) {\n+\t\t\tif (rte_hash_cmp_eq(key, k->key, h) == 0) {\n \t\t\t\tremove_entry(h, bkt, i);\n \n \t\t\t\t/*\n@@ -980,7 +1027,7 @@ lookup_stage3(unsigned idx, const struct rte_hash_key *key_slot, const void * co\n \tunsigned hit;\n \tunsigned key_idx;\n \n-\thit = !h->rte_hash_cmp_eq(key_slot->key, keys[idx], h->key_len);\n+\thit = !rte_hash_cmp_eq(key_slot->key, keys[idx], h);\n \tif (data != NULL)\n \t\tdata[idx] = key_slot->pdata;\n \n",
    "prefixes": [
        "dpdk-dev"
    ]
}