get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 77255,
    "url": "http://patches.dpdk.org/api/patches/77255/?format=api",
    "web_url": "http://patches.dpdk.org/project/dpdk/patch/20200911002207.31813-3-dmitry.kozliuk@gmail.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": "<20200911002207.31813-3-dmitry.kozliuk@gmail.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/20200911002207.31813-3-dmitry.kozliuk@gmail.com",
    "date": "2020-09-11T00:22:07",
    "name": "[2/2] eal/windows: implement alarm API",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "2e3e93bfe202ca78c0ab1149188832d197efa741",
    "submitter": {
        "id": 1581,
        "url": "http://patches.dpdk.org/api/people/1581/?format=api",
        "name": "Dmitry Kozlyuk",
        "email": "dmitry.kozliuk@gmail.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/20200911002207.31813-3-dmitry.kozliuk@gmail.com/mbox/",
    "series": [
        {
            "id": 12114,
            "url": "http://patches.dpdk.org/api/series/12114/?format=api",
            "web_url": "http://patches.dpdk.org/project/dpdk/list/?series=12114",
            "date": "2020-09-11T00:22:05",
            "name": "eal/windows: implement alarms",
            "version": 1,
            "mbox": "http://patches.dpdk.org/series/12114/mbox/"
        }
    ],
    "comments": "http://patches.dpdk.org/api/patches/77255/comments/",
    "check": "success",
    "checks": "http://patches.dpdk.org/api/patches/77255/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<dev-bounces@dpdk.org>",
        "X-Original-To": "patchwork@inbox.dpdk.org",
        "Delivered-To": "patchwork@inbox.dpdk.org",
        "Received": [
            "from dpdk.org (dpdk.org [92.243.14.124])\n\tby inbox.dpdk.org (Postfix) with ESMTP id C4C02A04B5;\n\tFri, 11 Sep 2020 02:22:30 +0200 (CEST)",
            "from [92.243.14.124] (localhost [127.0.0.1])\n\tby dpdk.org (Postfix) with ESMTP id DC9301C0D2;\n\tFri, 11 Sep 2020 02:22:19 +0200 (CEST)",
            "from mail-lj1-f195.google.com (mail-lj1-f195.google.com\n [209.85.208.195]) by dpdk.org (Postfix) with ESMTP id 5ABFA1C0B9\n for <dev@dpdk.org>; Fri, 11 Sep 2020 02:22:17 +0200 (CEST)",
            "by mail-lj1-f195.google.com with SMTP id r24so10543237ljm.3\n for <dev@dpdk.org>; Thu, 10 Sep 2020 17:22:17 -0700 (PDT)",
            "from localhost.localdomain (broadband-37-110-65-23.ip.moscow.rt.ru.\n [37.110.65.23])\n by smtp.gmail.com with ESMTPSA id b16sm132765ljh.34.2020.09.10.17.22.15\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 10 Sep 2020 17:22:16 -0700 (PDT)"
        ],
        "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n h=from:to:cc:subject:date:message-id:in-reply-to:references\n :mime-version:content-transfer-encoding;\n bh=yuu7Kw1EK66acJ0QzG8ewB4p6dl1GZgrMVfFFAY4gHg=;\n b=Ay+0WAvAxjrJrY5CcYgFESGPvj+dg/FehTt5XEtJ7VvPH9i7k0KNsOrYV34O+12ZVE\n urD1eboljKB2LieNJfS28l6x97D168yGaHgBQ7TTi+hveUsCpXEJi21brw42aqb3qslK\n qcN0raLzKmfvIaK+/mQMn+HH/8XyRRN3QHZ7hHoirndQQP4dBfULdW5+A7Z6Yi/Ckqhs\n dQv1Vj6meQJ6MML55n5r8SD2bUzjjOWVunfpAQVROTjUb7MSW9OVbyp0aDQhigi2gTU9\n oSY0vjkyCH0VmNL7+2zNY/0bXoAlsHaTtHQcWoedeUfKpHz14hn56/ObZHaoa2d6+pVk\n zjSQ==",
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20161025;\n h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to\n :references:mime-version:content-transfer-encoding;\n bh=yuu7Kw1EK66acJ0QzG8ewB4p6dl1GZgrMVfFFAY4gHg=;\n b=CzStsTU3+VHzJzIHw9dEQcKOabrrz2oM7hUrWGiOhrSfGLffvQ+4RT9E3G/ITlScgk\n wJfqglu/HHrDN5rlUvAm2qtA28JBhzXkzyKvKXQyPDQP6Gv5i+wVT6h0p+6KuWFWxwz3\n PuXtrVIRrrqZ2IQSwZf8daGKkeYxTWcF+X1YT8k7hK8Tru3eXJBHht0b38ffUyvildhH\n uwVo+NxsB/sjdvA/4JrXG5GjW/kVjngPU0ioAJl1ntJfyurR3Ey1nbDQV0Jta6xD9+/A\n k1Ue2XnlxhSDLylykJMXwnd4/AODJWA4uVRq1NDvELgj4fVEOEx3QRRbhcosWyHGjZPy\n FLLw==",
        "X-Gm-Message-State": "AOAM533u1M1NFb/IxUGPpzGGLQ81Xm1uqU7wt8tFiguoRTDN8kikWI39\n pdXxOHrE8vIH9qa2DJ/UblXgfN43lTsLww==",
        "X-Google-Smtp-Source": "\n ABdhPJyFCFyuxLFBqCIY+0GYQ5QTAXeoMMbQtXtVmg3V7PwAEwrtVYXjlMmy0MnTUXIYvQc2wsmtSA==",
        "X-Received": "by 2002:a2e:b5d9:: with SMTP id g25mr5423882ljn.335.1599783736653;\n Thu, 10 Sep 2020 17:22:16 -0700 (PDT)",
        "From": "Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>",
        "To": "dev@dpdk.org",
        "Cc": "Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>,\n Narcisa Ana Maria Vasile <navasile@linux.microsoft.com>,\n Dmitry Malloy <dmitrym@microsoft.com>,\n Pallavi Kadam <pallavi.kadam@intel.com>",
        "Date": "Fri, 11 Sep 2020 03:22:07 +0300",
        "Message-Id": "<20200911002207.31813-3-dmitry.kozliuk@gmail.com>",
        "X-Mailer": "git-send-email 2.25.4",
        "In-Reply-To": "<20200911002207.31813-1-dmitry.kozliuk@gmail.com>",
        "References": "<20200911002207.31813-1-dmitry.kozliuk@gmail.com>",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "Subject": "[dpdk-dev] [PATCH 2/2] eal/windows: implement alarm API",
        "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 <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 <mailto:dev-request@dpdk.org?subject=subscribe>",
        "Errors-To": "dev-bounces@dpdk.org",
        "Sender": "\"dev\" <dev-bounces@dpdk.org>"
    },
    "content": "Implementation is based on waitable timers Win32 API. When timer is set,\na callback and its argument are supplied to the OS, while timer handle\nis stored in EAL alarm list. When timer expires, OS wakes up the\ninterrupt thread and runs the callback. Upon completion it removes the\nalarm.\n\nWaitable timers must be set from the thread their callback will run in,\neal_intr_thread_schedule() provides a way to schedule asyncronuous code\nexecution in the interrupt thread. Alarm module builds synchronous timer\nsetup on top of it.\n\nWindows alarms are not a type of DPDK interrupt handle and do not\ninteract with interrupt module beyond executing in the same thread.\n\nSigned-off-by: Dmitry Kozlyuk <dmitry.kozliuk@gmail.com>\n---\n lib/librte_eal/rte_eal_exports.def |   2 +\n lib/librte_eal/windows/eal_alarm.c | 219 +++++++++++++++++++++++++++++\n lib/librte_eal/windows/meson.build |   1 +\n 3 files changed, 222 insertions(+)\n create mode 100644 lib/librte_eal/windows/eal_alarm.c",
    "diff": "diff --git a/lib/librte_eal/rte_eal_exports.def b/lib/librte_eal/rte_eal_exports.def\nindex 9baca0110..b6abb5ae1 100644\n--- a/lib/librte_eal/rte_eal_exports.def\n+++ b/lib/librte_eal/rte_eal_exports.def\n@@ -14,6 +14,8 @@ EXPORTS\n \trte_devargs_insert\n \trte_devargs_next\n \trte_devargs_remove\n+\trte_eal_alarm_set\n+\trte_eal_alarm_cancel\n \trte_eal_get_configuration\n \trte_eal_has_hugepages\n \trte_eal_has_pci\ndiff --git a/lib/librte_eal/windows/eal_alarm.c b/lib/librte_eal/windows/eal_alarm.c\nnew file mode 100644\nindex 000000000..3b262793a\n--- /dev/null\n+++ b/lib/librte_eal/windows/eal_alarm.c\n@@ -0,0 +1,219 @@\n+/* SPDX-License-Identifier: BSD-3-Clause\n+ * Copyright (c) 2020 Dmitry Kozlyuk\n+ */\n+\n+#include <stdatomic.h>\n+#include <stdbool.h>\n+\n+#include <rte_alarm.h>\n+#include <rte_spinlock.h>\n+\n+#include <rte_eal_trace.h>\n+\n+#include \"eal_windows.h\"\n+\n+enum alarm_state {\n+\tALARM_ARMED,\n+\tALARM_TRIGGERED,\n+\tALARM_CANCELLED\n+};\n+\n+struct alarm_entry {\n+\tLIST_ENTRY(alarm_entry) next;\n+\trte_eal_alarm_callback cb_fn;\n+\tvoid *cb_arg;\n+\tHANDLE timer;\n+\tatomic_uint state;\n+};\n+\n+static LIST_HEAD(alarm_list, alarm_entry) alarm_list = LIST_HEAD_INITIALIZER();\n+\n+static rte_spinlock_t alarm_lock = RTE_SPINLOCK_INITIALIZER;\n+\n+static int intr_thread_exec(void (*func)(void *arg), void *arg);\n+\n+static void\n+alarm_remove_unsafe(struct alarm_entry *ap)\n+{\n+\tLIST_REMOVE(ap, next);\n+\tCloseHandle(ap->timer);\n+\tfree(ap);\n+}\n+\n+static void\n+alarm_callback(void *arg, DWORD low __rte_unused, DWORD high __rte_unused)\n+{\n+\tstruct alarm_entry *ap = arg;\n+\tunsigned int state = ALARM_ARMED;\n+\n+\tif (!atomic_compare_exchange_strong(\n+\t\t\t&ap->state, &state, ALARM_TRIGGERED))\n+\t\treturn;\n+\n+\tap->cb_fn(ap->cb_arg);\n+\n+\trte_spinlock_lock(&alarm_lock);\n+\talarm_remove_unsafe(ap);\n+\trte_spinlock_unlock(&alarm_lock);\n+}\n+\n+struct alarm_task {\n+\tstruct alarm_entry *entry;\n+\tLARGE_INTEGER deadline;\n+\tint ret;\n+};\n+\n+static void\n+alarm_set(void *arg)\n+{\n+\tstruct alarm_task *task = arg;\n+\n+\tBOOL ret = SetWaitableTimer(\n+\t\ttask->entry->timer, &task->deadline,\n+\t\t0, alarm_callback, task->entry, FALSE);\n+\ttask->ret = ret ? 0 : (-1);\n+}\n+\n+int\n+rte_eal_alarm_set(uint64_t us, rte_eal_alarm_callback cb_fn, void *cb_arg)\n+{\n+\tstruct alarm_entry *ap;\n+\tHANDLE timer;\n+\tFILETIME ft;\n+\tstruct alarm_task task;\n+\tint ret;\n+\n+\t/* Calculate deadline ASAP, unit of measure = 100ns. */\n+\tGetSystemTimePreciseAsFileTime(&ft);\n+\ttask.deadline.LowPart = ft.dwLowDateTime;\n+\ttask.deadline.HighPart = ft.dwHighDateTime;\n+\ttask.deadline.QuadPart += 10 * us;\n+\n+\tap = calloc(1, sizeof(*ap));\n+\tif (ap == NULL) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot allocate alarm entry\\n\");\n+\t\tret = -ENOMEM;\n+\t\tgoto exit;\n+\t}\n+\n+\ttimer = CreateWaitableTimer(NULL, FALSE, NULL);\n+\tif (timer == NULL) {\n+\t\tRTE_LOG_WIN32_ERR(\"CreateWaitableTimer()\");\n+\t\tret = -EINVAL;\n+\t\tgoto fail;\n+\t}\n+\n+\tap->timer = timer;\n+\tap->cb_fn = cb_fn;\n+\tap->cb_arg = cb_arg;\n+\ttask.entry = ap;\n+\n+\t/* Waitable timer must be set in the same thread that will\n+\t * do an alertable wait for the alarm to trigger, that is,\n+\t * in the interrupt thread. Setting can fail, so do it synchronously.\n+\t */\n+\tret = intr_thread_exec(alarm_set, &task);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot setup alarm in interrupt thread\\n\");\n+\t\tgoto fail;\n+\t}\n+\n+\tret = task.ret;\n+\tif (ret < 0)\n+\t\tgoto fail;\n+\n+\trte_spinlock_lock(&alarm_lock);\n+\tLIST_INSERT_HEAD(&alarm_list, ap, next);\n+\trte_spinlock_unlock(&alarm_lock);\n+\n+\tgoto exit;\n+\n+fail:\n+\tif (timer != NULL)\n+\t\tCloseHandle(timer);\n+\tif (ap != NULL)\n+\t\tfree(ap);\n+\n+exit:\n+\trte_eal_trace_alarm_set(us, cb_fn, cb_arg, ret);\n+\treturn ret;\n+}\n+\n+static bool\n+alarm_matches(const struct alarm_entry *ap,\n+\trte_eal_alarm_callback cb_fn, void *cb_arg)\n+{\n+\tbool any_arg = cb_arg == (void *)(-1);\n+\treturn (ap->cb_fn == cb_fn) && (any_arg || ap->cb_arg == cb_arg);\n+}\n+\n+int\n+rte_eal_alarm_cancel(rte_eal_alarm_callback cb_fn, void *cb_arg)\n+{\n+\tstruct alarm_entry *ap;\n+\tunsigned int state;\n+\tint removed;\n+\tbool executing;\n+\n+\tremoved = 0;\n+\tdo {\n+\t\texecuting = false;\n+\n+\t\trte_spinlock_lock(&alarm_lock);\n+\n+\t\tLIST_FOREACH(ap, &alarm_list, next) {\n+\t\t\tif (!alarm_matches(ap, cb_fn, cb_arg))\n+\t\t\t\tcontinue;\n+\n+\t\t\tstate = ALARM_ARMED;\n+\t\t\tif (atomic_compare_exchange_strong(\n+\t\t\t\t\t&ap->state, &state, ALARM_CANCELLED)) {\n+\t\t\t\talarm_remove_unsafe(ap);\n+\t\t\t\tremoved++;\n+\t\t\t} else if (state == ALARM_TRIGGERED)\n+\t\t\t\texecuting = true;\n+\t\t}\n+\n+\t\trte_spinlock_unlock(&alarm_lock);\n+\t} while (executing);\n+\n+\trte_eal_trace_alarm_cancel(cb_fn, cb_arg, removed);\n+\treturn removed;\n+}\n+\n+struct intr_task {\n+\tvoid (*func)(void *arg);\n+\tvoid *arg;\n+\trte_spinlock_t lock; /* unlocked at task completion */\n+};\n+\n+static void\n+intr_thread_entry(void *arg)\n+{\n+\tstruct intr_task *task = arg;\n+\ttask->func(task->arg);\n+\trte_spinlock_unlock(&task->lock);\n+}\n+\n+static int\n+intr_thread_exec(void (*func)(void *arg), void *arg)\n+{\n+\tstruct intr_task task;\n+\tint ret;\n+\n+\ttask.func = func;\n+\ttask.arg = arg;\n+\trte_spinlock_init(&task.lock);\n+\n+\t/* Make timers more precise by synchronizing in userspace. */\n+\trte_spinlock_lock(&task.lock);\n+\tret = eal_intr_thread_schedule(intr_thread_entry, &task);\n+\tif (ret < 0) {\n+\t\tRTE_LOG(ERR, EAL, \"Cannot schedule task to interrupt thread\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\t/* Wait for the task to complete. */\n+\trte_spinlock_lock(&task.lock);\n+\treturn 0;\n+}\ndiff --git a/lib/librte_eal/windows/meson.build b/lib/librte_eal/windows/meson.build\nindex b690bc6b0..3b2faf29e 100644\n--- a/lib/librte_eal/windows/meson.build\n+++ b/lib/librte_eal/windows/meson.build\n@@ -5,6 +5,7 @@ subdir('include')\n \n sources += files(\n \t'eal.c',\n+\t'eal_alarm.c',\n \t'eal_debug.c',\n \t'eal_file.c',\n \t'eal_hugepages.c',\n",
    "prefixes": [
        "2/2"
    ]
}