get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 48586,
    "url": "http://patches.dpdk.org/api/patches/48586/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20181207114048.2324-1-jgrajcia@cisco.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": "<20181207114048.2324-1-jgrajcia@cisco.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20181207114048.2324-1-jgrajcia@cisco.com",
    "date": "2018-12-07T11:40:48",
    "name": "[v2] eal_interrupts: add option for pending callback unregister",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "3dbdf090a9c93b42a27685c4226d61953e26d452",
    "submitter": {
        "id": 1169,
        "url": "http://patches.dpdk.org/api/people/1169/?format=api",
        "name": "Jakub Grajciar -X (jgrajcia - PANTHEON TECH SRO at Cisco)",
        "email": "jgrajcia@cisco.com"
    },
    "delegate": null,
    "mbox": "http://patches.dpdk.org/project/dpdk/patch/20181207114048.2324-1-jgrajcia@cisco.com/mbox/",
    "series": [
        {
            "id": 2694,
            "url": "http://patches.dpdk.org/api/series/2694/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=2694",
            "date": "2018-12-07T11:40:48",
            "name": "[v2] eal_interrupts: add option for pending callback unregister",
            "version": 2,
            "mbox": "http://patches.dpdk.org/series/2694/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/48586/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/48586/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 [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id EFE595F17;\n\tFri,  7 Dec 2018 12:41:11 +0100 (CET)",
            "from alln-iport-5.cisco.com (alln-iport-5.cisco.com\n\t[173.37.142.92]) by dpdk.org (Postfix) with ESMTP id 5A5355F11\n\tfor <dev@dpdk.org>; Fri,  7 Dec 2018 12:41:10 +0100 (CET)",
            "from alln-core-3.cisco.com ([173.36.13.136])\n\tby alln-iport-5.cisco.com with ESMTP/TLS/DHE-RSA-AES256-GCM-SHA384;\n\t07 Dec 2018 11:41:09 +0000",
            "from XCH-RCD-017.cisco.com (xch-rcd-017.cisco.com [173.37.102.27])\n\tby alln-core-3.cisco.com (8.15.2/8.15.2) with ESMTPS id\n\twB7Bf85j022866\n\t(version=TLSv1.2 cipher=AES256-SHA bits=256 verify=FAIL)\n\tfor <dev@dpdk.org>; Fri, 7 Dec 2018 11:41:09 GMT",
            "from ja-VirtualBox.cisco.com (10.61.207.89) by\n\tXCH-RCD-017.cisco.com\n\t(173.37.102.27) with Microsoft SMTP Server (TLS) id 15.0.1395.4;\n\tFri, 7 Dec 2018 05:41:07 -0600"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n\td=cisco.com; i=@cisco.com; l=6090; q=dns/txt; s=iport;\n\tt=1544182870; x=1545392470;\n\th=from:to:cc:subject:date:message-id:mime-version;\n\tbh=Nitn30Ide9mg/RB8uTyFdZOoifKeyEfbYjC5OuZTiG0=;\n\tb=d49XhOqTJ4dcfFguiEHOamojB6OpgR5kI3bs3jI7Zi7TeC7I0fr9FnSl\n\tYfArfx6unDo/VP/9gtOOQA8koq98fifATcVSM/wBGHkZj3cBgcSbIcOR2\n\t/p3H3bCKEPHyY7xmKxOFHkOwmDPQvHF4NYbUq1abGDbzSP61cAruReQxU o=;",
        "X-IronPort-Anti-Spam-Filtered": "true",
        "X-IronPort-Anti-Spam-Result": "A0ADAACNWwpc/4gNJK1jGQEBAQEBAQEBAQEBAQcBAQEBAQGBUQQBAQEBAQsBggOBaCcKjAmMEIstji8UgWYLAQGEbIMbIjQJDQEDAQECAQECbSiFalKBPg4FgyGBdQ2ldjOFQIRvh3BFg2oXgUA/gRGEUwGDJ4VzAokzlzQJkUALGJE4IwmYSAIRFIFGOIFVTSMVO4JsgicMC44ePgEBMYooAYEeAQE",
        "X-IronPort-AV": "E=Sophos;i=\"5.56,326,1539648000\"; d=\"scan'208\";a=\"209095848\"",
        "From": "Jakub Grajciar <jgrajcia@cisco.com>",
        "To": "<dev@dpdk.org>",
        "CC": "Jakub Grajciar <jgrajcia@cisco.com>",
        "Date": "Fri, 7 Dec 2018 12:40:48 +0100",
        "Message-ID": "<20181207114048.2324-1-jgrajcia@cisco.com>",
        "X-Mailer": "git-send-email 2.17.1",
        "MIME-Version": "1.0",
        "Content-Type": "text/plain",
        "X-Originating-IP": "[10.61.207.89]",
        "X-ClientProxiedBy": "xch-rtp-008.cisco.com (64.101.220.148) To\n\tXCH-RCD-017.cisco.com (173.37.102.27)",
        "X-Outbound-SMTP-Client": "173.37.102.27, xch-rcd-017.cisco.com",
        "X-Outbound-Node": "alln-core-3.cisco.com",
        "Subject": "[dpdk-dev] [PATCH v2] eal_interrupts: add option for pending\n\tcallback unregister",
        "X-BeenThere": "dev@dpdk.org",
        "X-Mailman-Version": "2.1.15",
        "Precedence": "list",
        "List-Id": "DPDK patches and discussions <dev.dpdk.org>",
        "List-Unsubscribe": "<https://mails.dpdk.org/options/dev>,\n\t<mailto:dev-request@dpdk.org?subject=unsubscribe>",
        "List-Archive": "<http://mails.dpdk.org/archives/dev/>",
        "List-Post": "<mailto:dev@dpdk.org>",
        "List-Help": "<mailto:dev-request@dpdk.org?subject=help>",
        "List-Subscribe": "<https://mails.dpdk.org/listinfo/dev>,\n\t<mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "use case: if callback is used to receive message form socket,\nand the message received is disconnect/error, this callback needs\nto be unregistered, but cannot because it is still active.\n\nWith this patch it is possible to mark the callback to be\nunregistered once the interrupt process is done with this\ninterrupt source.\n\nSigned-off-by: Jakub Grajciar <jgrajcia@cisco.com>\n---\n .../common/include/rte_interrupts.h           | 30 +++++++\n lib/librte_eal/linuxapp/eal/eal_interrupts.c  | 83 ++++++++++++++++++-\n 2 files changed, 111 insertions(+), 2 deletions(-)",
    "diff": "diff --git a/lib/librte_eal/common/include/rte_interrupts.h b/lib/librte_eal/common/include/rte_interrupts.h\nindex d751a6378..3946742ad 100644\n--- a/lib/librte_eal/common/include/rte_interrupts.h\n+++ b/lib/librte_eal/common/include/rte_interrupts.h\n@@ -24,6 +24,13 @@ struct rte_intr_handle;\n /** Function to be registered for the specific interrupt */\n typedef void (*rte_intr_callback_fn)(void *cb_arg);\n \n+/**\n+ * Function to call after a callback is unregistered.\n+ * Can be used to close fd and free cb_arg.\n+ */\n+typedef void (*rte_intr_unregister_callback_fn)(struct rte_intr_handle *intr_handle,\n+\t\t\t\t\t\tvoid *cb_arg);\n+\n #include \"rte_eal_interrupts.h\"\n \n /**\n@@ -61,6 +68,29 @@ int rte_intr_callback_register(const struct rte_intr_handle *intr_handle,\n int rte_intr_callback_unregister(const struct rte_intr_handle *intr_handle,\n \t\t\t\trte_intr_callback_fn cb, void *cb_arg);\n \n+/**\n+ * It unregisters the callback according to the specified interrupt handle,\n+ * after it's no longer acive. Failes if source is not active.\n+ *\n+ * @param intr_handle\n+ *  pointer to the interrupt handle.\n+ * @param cb\n+ *  callback address.\n+ * @param cb_arg\n+ *  address of parameter for callback, (void *)-1 means to remove all\n+ *  registered which has the same callback address.\n+ * @param ucb_fn\n+ *  callback to call before cb is unregistered (optional).\n+ *  can be used to close fd and free cb_arg.\n+ *\n+ * @return\n+ *  - On success, return the number of callback entities marked for remove.\n+ *  - On failure, a negative value.\n+ */\n+int rte_intr_callback_unregister_pending(const struct rte_intr_handle *intr_handle,\n+\t\t\t\trte_intr_callback_fn cb_fn, void *cb_arg,\n+\t\t\t\trte_intr_unregister_callback_fn ucb_fn);\n+\n /**\n  * It enables the interrupt for the specified handle.\n  *\ndiff --git a/lib/librte_eal/linuxapp/eal/eal_interrupts.c b/lib/librte_eal/linuxapp/eal/eal_interrupts.c\nindex cbac451e1..144ac4c22 100644\n--- a/lib/librte_eal/linuxapp/eal/eal_interrupts.c\n+++ b/lib/librte_eal/linuxapp/eal/eal_interrupts.c\n@@ -76,6 +76,8 @@ struct rte_intr_callback {\n \tTAILQ_ENTRY(rte_intr_callback) next;\n \trte_intr_callback_fn cb_fn;  /**< callback address */\n \tvoid *cb_arg;                /**< parameter for callback */\n+\tuint8_t pending_delete;      /**< delete after callback is called */\n+\trte_intr_unregister_callback_fn ucb_fn; /**< fn to call before cb is deleted */\n };\n \n struct rte_intr_source {\n@@ -472,6 +474,8 @@ rte_intr_callback_register(const struct rte_intr_handle *intr_handle,\n \t}\n \tcallback->cb_fn = cb;\n \tcallback->cb_arg = cb_arg;\n+\tcallback->pending_delete = 0;\n+\tcallback->ucb_fn = NULL;\n \n \trte_spinlock_lock(&intr_lock);\n \n@@ -518,6 +522,57 @@ rte_intr_callback_register(const struct rte_intr_handle *intr_handle,\n \treturn ret;\n }\n \n+int\n+rte_intr_callback_unregister_pending(const struct rte_intr_handle *intr_handle,\n+\t\t\t\trte_intr_callback_fn cb_fn, void *cb_arg,\n+\t\t\t\trte_intr_unregister_callback_fn ucb_fn)\n+{\n+\tint ret;\n+\tstruct rte_intr_source *src;\n+\tstruct rte_intr_callback *cb, *next;\n+\n+\t/* do parameter checking first */\n+\tif (intr_handle == NULL || intr_handle->fd < 0) {\n+\t\tRTE_LOG(ERR, EAL,\n+\t\t\"Unregistering with invalid input parameter\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\trte_spinlock_lock(&intr_lock);\n+\n+\t/* check if the insterrupt source for the fd is existent */\n+\tTAILQ_FOREACH(src, &intr_sources, next)\n+\t\tif (src->intr_handle.fd == intr_handle->fd)\n+\t\t\tbreak;\n+\n+\t/* No interrupt source registered for the fd */\n+\tif (src == NULL) {\n+\t\tret = -ENOENT;\n+\n+\t/* only usable if the source is active */\n+\t} else if (src->active == 0) {\n+\t\treturn -EAGAIN;\n+\n+\t} else {\n+\t\tret = 0;\n+\n+\t\t/* walk through the callbacks and mark all that match. */\n+\t\tfor (cb = TAILQ_FIRST(&src->callbacks); cb != NULL; cb = next) {\n+\t\t\tnext = TAILQ_NEXT(cb, next);\n+\t\t\tif (cb->cb_fn == cb_fn && (cb_arg == (void *)-1 ||\n+\t\t\t\t\tcb->cb_arg == cb_arg)) {\n+\t\t\t\tcb->pending_delete = 1;\n+\t\t\t\tcb->ucb_fn = ucb_fn;\n+\t\t\t\tret++;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\trte_spinlock_unlock(&intr_lock);\n+\n+\treturn ret;\n+}\n+\n int\n rte_intr_callback_unregister(const struct rte_intr_handle *intr_handle,\n \t\t\trte_intr_callback_fn cb_fn, void *cb_arg)\n@@ -698,7 +753,7 @@ static int\n eal_intr_process_interrupts(struct epoll_event *events, int nfds)\n {\n \tbool call = false;\n-\tint n, bytes_read;\n+\tint n, bytes_read, rv;\n \tstruct rte_intr_source *src;\n \tstruct rte_intr_callback *cb, *next;\n \tunion rte_intr_read_buffer buf;\n@@ -823,9 +878,33 @@ eal_intr_process_interrupts(struct epoll_event *events, int nfds)\n \t\t\t\trte_spinlock_lock(&intr_lock);\n \t\t\t}\n \t\t}\n-\n \t\t/* we done with that interrupt source, release it. */\n \t\tsrc->active = 0;\n+\n+\t\trv = 0;\n+\n+\t\t/* check if any callback are supposed to be removed */\n+\t\tfor (cb = TAILQ_FIRST(&src->callbacks); cb != NULL; cb = next) {\n+\t\t\tnext = TAILQ_NEXT(cb, next);\n+\t\t\tif (cb->pending_delete) {\n+\t\t\t\tTAILQ_REMOVE(&src->callbacks, cb, next);\n+\t\t\t\tif (cb->ucb_fn)\n+\t\t\t\t\tcb->ucb_fn(&src->intr_handle, cb->cb_arg);\n+\t\t\t\tfree(cb);\n+\t\t\t\trv++;\n+\t\t\t}\n+\t\t}\n+\n+\t\t/* all callbacks for that source are removed. */\n+\t\tif (TAILQ_EMPTY(&src->callbacks)) {\n+\t\t\tTAILQ_REMOVE(&intr_sources, src, next);\n+\t\t\tfree(src);\n+\t\t}\n+\n+\t\t/* notify the pipe fd waited by epoll_wait to rebuild the wait list */\n+\t\tif (rv >= 0 && write(intr_pipe.writefd, \"1\", 1) < 0)\n+\t\t\treturn -EPIPE;\n+\n \t\trte_spinlock_unlock(&intr_lock);\n \t}\n \n",
    "prefixes": [
        "v2"
    ]
}