get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

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

{
    "id": 7325,
    "url": "https://patches.dpdk.org/api/patches/7325/?format=api",
    "web_url": "https://patches.dpdk.org/project/dpdk/patch/1443623388-29104-5-git-send-email-ian.betts@intel.com/",
    "project": {
        "id": 1,
        "url": "https://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": "<1443623388-29104-5-git-send-email-ian.betts@intel.com>",
    "list_archive_url": "https://inbox.dpdk.org/dev/1443623388-29104-5-git-send-email-ian.betts@intel.com",
    "date": "2015-09-30T14:29:47",
    "name": "[dpdk-dev,v1,4/5] examples: add pthread-shim in performance-thread sample app",
    "commit_ref": null,
    "pull_url": null,
    "state": "superseded",
    "archived": true,
    "hash": "eae1da4ffe52c21384014556a1c25ae6ab054758",
    "submitter": {
        "id": 340,
        "url": "https://patches.dpdk.org/api/people/340/?format=api",
        "name": "ibetts",
        "email": "ian.betts@intel.com"
    },
    "delegate": null,
    "mbox": "https://patches.dpdk.org/project/dpdk/patch/1443623388-29104-5-git-send-email-ian.betts@intel.com/mbox/",
    "series": [],
    "comments": "https://patches.dpdk.org/api/patches/7325/comments/",
    "check": "pending",
    "checks": "https://patches.dpdk.org/api/patches/7325/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 E6CA68DB5;\n\tWed, 30 Sep 2015 16:30:10 +0200 (CEST)",
            "from mga14.intel.com (mga14.intel.com [192.55.52.115])\n\tby dpdk.org (Postfix) with ESMTP id C4FBD8D9F\n\tfor <dev@dpdk.org>; Wed, 30 Sep 2015 16:30:07 +0200 (CEST)",
            "from fmsmga001.fm.intel.com ([10.253.24.23])\n\tby fmsmga103.fm.intel.com with ESMTP; 30 Sep 2015 07:29:55 -0700",
            "from irvmail001.ir.intel.com ([163.33.26.43])\n\tby fmsmga001.fm.intel.com with ESMTP; 30 Sep 2015 07:29:54 -0700",
            "from sivswdev01.ir.intel.com (sivswdev01.ir.intel.com\n\t[10.237.217.45])\n\tby irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id\n\tt8UETsN4003364; Wed, 30 Sep 2015 15:29:54 +0100",
            "from sivswdev01.ir.intel.com (localhost [127.0.0.1])\n\tby sivswdev01.ir.intel.com with ESMTP id t8UETsO9029230;\n\tWed, 30 Sep 2015 15:29:54 +0100",
            "(from ibetts@localhost)\n\tby sivswdev01.ir.intel.com with  id t8UETsEn029225;\n\tWed, 30 Sep 2015 15:29:54 +0100"
        ],
        "X-ExtLoop1": "1",
        "X-IronPort-AV": "E=Sophos;i=\"5.17,612,1437462000\"; d=\"scan'208\";a=\"800564745\"",
        "From": "ibetts <ian.betts@intel.com>",
        "To": "dev@dpdk.org",
        "Date": "Wed, 30 Sep 2015 15:29:47 +0100",
        "Message-Id": "<1443623388-29104-5-git-send-email-ian.betts@intel.com>",
        "X-Mailer": "git-send-email 1.7.4.1",
        "In-Reply-To": "<1443623388-29104-1-git-send-email-ian.betts@intel.com>",
        "References": "<1443623388-29104-1-git-send-email-ian.betts@intel.com>",
        "Cc": "Ian Betts <ian.betts@intel.com>",
        "Subject": "[dpdk-dev] [PATCH v1 4/5] examples: add pthread-shim in\n\tperformance-thread sample app",
        "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": "From: Ian Betts <ian.betts@intel.com>\n\nThis commit adds a simple pthread_shim example for the\ncooperative included with this patchset.\n\nThe shim demonstrates a way in which legacy code writtem for\npthreads could be adapted to lighweight threads.\n\nSigned-off-by: Ian Betts <ian.betts@intel.com>\n---\n examples/performance-thread/pthread_shim/Makefile  |  61 ++\n examples/performance-thread/pthread_shim/main.c    | 287 +++++++++\n .../performance-thread/pthread_shim/pthread_shim.c | 717 +++++++++++++++++++++\n .../performance-thread/pthread_shim/pthread_shim.h | 113 ++++\n 4 files changed, 1178 insertions(+)\n create mode 100644 examples/performance-thread/pthread_shim/Makefile\n create mode 100644 examples/performance-thread/pthread_shim/main.c\n create mode 100644 examples/performance-thread/pthread_shim/pthread_shim.c\n create mode 100644 examples/performance-thread/pthread_shim/pthread_shim.h",
    "diff": "diff --git a/examples/performance-thread/pthread_shim/Makefile b/examples/performance-thread/pthread_shim/Makefile\nnew file mode 100644\nindex 0000000..953dc42\n--- /dev/null\n+++ b/examples/performance-thread/pthread_shim/Makefile\n@@ -0,0 +1,60 @@\n+#   BSD LICENSE\n+#\n+#   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+#   All rights reserved.\n+#\n+#   Redistribution and use in source and binary forms, with or without\n+#   modification, are permitted provided that the following conditions\n+#   are met:\n+#\n+#     * Redistributions of source code must retain the above copyright\n+#       notice, this list of conditions and the following disclaimer.\n+#     * Redistributions in binary form must reproduce the above copyright\n+#       notice, this list of conditions and the following disclaimer in\n+#       the documentation and/or other materials provided with the\n+#       distribution.\n+#     * Neither the name of Intel Corporation nor the names of its\n+#       contributors may be used to endorse or promote products derived\n+#       from this software without specific prior written permission.\n+#\n+#   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+#   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+#   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+#   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+#   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+#   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+#   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+#   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+#   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+#   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+#   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+\n+ifeq ($(RTE_SDK),)\n+$(error \"Please define RTE_SDK environment variable\")\n+endif\n+\n+# Default target, can be overriden by command line or environment\n+RTE_TARGET ?= x86_64-native-linuxapp-gcc\n+\n+include $(RTE_SDK)/mk/rte.vars.mk\n+\n+# binary name\n+APP = lthread_pthread_shim\n+\n+# all source are stored in SRCS-y\n+SRCS-y := main.c  pthread_shim.c\n+INCLUDES := -I$(RTE_SDK)/$(RTE_TARGET)/include -I$(SRCDIR)\n+include $(RTE_SDK)/examples/performance-thread/common/common.mk\n+\n+CFLAGS=    -g -O3 $(USER_FLAGS) $(INCLUDES)\n+CFLAGS += $(WERROR_FLAGS)\n+\n+LDFLAGS += -lpthread\n+\n+# workaround for a gcc bug with noreturn attribute\n+# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603\n+ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y)\n+CFLAGS_main.o += -Wno-return-type\n+endif\n+\n+include $(RTE_SDK)/mk/rte.extapp.mk\ndiff --git a/examples/performance-thread/pthread_shim/main.c b/examples/performance-thread/pthread_shim/main.c\nnew file mode 100644\nindex 0000000..afc12c8\n--- /dev/null\n+++ b/examples/performance-thread/pthread_shim/main.c\n@@ -0,0 +1,284 @@\n+\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#define _GNU_SOURCE\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <stdint.h>\n+#include <inttypes.h>\n+#include <sys/types.h>\n+#include <string.h>\n+#include <sys/queue.h>\n+#include <stdarg.h>\n+#include <errno.h>\n+#include <getopt.h>\n+#include <unistd.h>\n+#include <sched.h>\n+#include <pthread.h>\n+\n+#include <rte_config.h>\n+#include <rte_common.h>\n+#include <rte_lcore.h>\n+#include <rte_per_lcore.h>\n+#include <rte_timer.h>\n+\n+#include \"lthread_api.h\"\n+#include \"lthread_diag_api.h\"\n+#include \"pthread_shim.h\"\n+\n+#define DEBUG_APP 0\n+#define HELLOW_WORLD_MAX_LTHREADS 10\n+\n+__thread int print_count;\n+__thread pthread_mutex_t print_lock;\n+\n+__thread pthread_mutex_t exit_lock;\n+__thread pthread_cond_t exit_cond;\n+\n+/*\n+ * A simple thread that demonstrates use of a mutex, a condition\n+ * variable, thread local storage, explicit yield, and thread exit.\n+ *\n+ * The thread uses a mutex to protect a shared counter which is incremented\n+ * and then it waits on condition variable before exiting.\n+ *\n+ * The thread argument is stored in and retrieved from TLS, using\n+ * the pthread key create, get and set specific APIs.\n+ *\n+ * The thread yields while holding the mutex, to provide opportunity\n+ * for other threads to contend.\n+ *\n+ * All of the pthread API functions used by this thread are actually\n+ * resolved to corresponding lthread functions by the pthread shim\n+ * implemented in pthread_shim.c\n+ */\n+void *helloworld_pthread(void *arg);\n+void *helloworld_pthread(void *arg)\n+{\n+\tpthread_key_t key;\n+\n+\t/* create a key for TLS */\n+\tpthread_key_create(&key, NULL);\n+\n+\t/* store the arg in TLS */\n+\tpthread_setspecific(key, arg);\n+\n+\t/* grab lock and increment shared counter */\n+\tpthread_mutex_lock(&print_lock);\n+\tprint_count++;\n+\n+\t/* yield thread to give opportunity for lock contention */\n+\tpthread_yield();\n+\n+\t/* retrieve arg from TLS */\n+\tuint64_t thread_no = (uint64_t) pthread_getspecific(key);\n+\n+\tprintf(\"Hello - lcore = %d count = %d thread_no = %d thread_id = %p\\n\",\n+\t\t\tsched_getcpu(),\n+\t\t\tprint_count,\n+\t\t\t(int) thread_no,\n+\t\t\t(void *)pthread_self());\n+\n+\t/* release the lock */\n+\tpthread_mutex_unlock(&print_lock);\n+\n+\t/*\n+\t * wait on condition variable\n+\t * before exiting\n+\t */\n+\tpthread_mutex_lock(&exit_lock);\n+\tpthread_cond_wait(&exit_cond, &exit_lock);\n+\tpthread_mutex_unlock(&exit_lock);\n+\n+\t/* exit */\n+\tpthread_exit((void *) thread_no);\n+}\n+\n+\n+/*\n+ * This is the initial thread\n+ *\n+ * It demonstrates pthread, mutex and condition variable creation,\n+ * broadcast and pthread join APIs.\n+ *\n+ * This initial thread must always start life as an lthread.\n+ *\n+ * This thread creates many more threads then waits a short time\n+ * before signalling them to exit using a broadcast.\n+ *\n+ * All of the pthread API functions used by this thread are actually\n+ * resolved to corresponding lthread functions by the pthread shim\n+ * implemented in pthread_shim.c\n+ *\n+ * After all threads have finished the lthread scheduler is shutdown\n+ * and normal pthread operation is restored\n+ */\n+__thread pthread_t tid[HELLOW_WORLD_MAX_LTHREADS];\n+\n+static void initial_lthread(void *args);\n+static void initial_lthread(void *args __attribute__((unused)))\n+{\n+\tint lcore = (int) rte_lcore_id();\n+\t/*\n+\t *\n+\t * We can now enable pthread API override\n+\t * and start to use the pthread APIs\n+\t */\n+\tpthread_override_set(1);\n+\n+\tuint64_t i;\n+\n+\t/* initialize mutex for shared counter */\n+\tprint_count = 0;\n+\tpthread_mutex_init(&print_lock, NULL);\n+\n+\t/* initialize mutex and condition variable controlling thread exit */\n+\tpthread_mutex_init(&exit_lock, NULL);\n+\tpthread_cond_init(&exit_cond, NULL);\n+\n+\t/* spawn a number of threads */\n+\tfor (i = 0; i < HELLOW_WORLD_MAX_LTHREADS; i++) {\n+\n+\t\t/*\n+\t\t * Not strictly necessary but\n+\t\t * for the sake of this example\n+\t\t * use an attribute to pass the desired lcore\n+\t\t */\n+\t\tpthread_attr_t attr;\n+\t\tcpu_set_t cpuset;\n+\n+\t\tCPU_ZERO(&cpuset);\n+\t\tCPU_SET(lcore, &cpuset);\n+\t\tpthread_attr_init(&attr);\n+\t\tpthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset);\n+\n+\t\t/* create the thread */\n+\t\tpthread_create(&tid[i], &attr, helloworld_pthread, (void *) i);\n+\t}\n+\n+\t/* wait for 1s to allow threads\n+\t * to block on the condition variable\n+\t * N.B. nanosleep() is resolved to lthread_sleep()\n+\t * by the shim.\n+\t */\n+\tstruct timespec time;\n+\n+\ttime.tv_sec = 1;\n+\ttime.tv_nsec = 0;\n+\tnanosleep(&time, NULL);\n+\n+\t/* wake up all the threads */\n+\tpthread_cond_broadcast(&exit_cond);\n+\n+\t/* wait for them to finish */\n+\tfor (i = 0; i < HELLOW_WORLD_MAX_LTHREADS; i++) {\n+\n+\t\tuint64_t thread_no;\n+\n+\t\tpthread_join(tid[i], (void *) &thread_no);\n+\t\tif (thread_no != i)\n+\t\t\tprintf(\"error on thread exit\\n\");\n+\t}\n+\n+\t/* shutdown the lthread scheduler */\n+\tlthread_scheduler_shutdown(rte_lcore_id());\n+\tlthread_detach();\n+}\n+\n+\n+\n+/* This thread creates a single initial lthread\n+ * and then runs the scheduler\n+ * An instance of this thread is created on each thread\n+ * in the core mask\n+ */\n+static int\n+lthread_scheduler(void *args);\n+static int\n+lthread_scheduler(void *args __attribute__((unused)))\n+{\n+\t/* create initial thread  */\n+\tstruct lthread *lt;\n+\n+\tlthread_create(&lt, -1, initial_lthread, (void *) NULL);\n+\n+\t/* run the lthread scheduler */\n+\tlthread_run();\n+\n+\t/* restore genuine pthread operation */\n+\tpthread_override_set(0);\n+\treturn 0;\n+}\n+\n+int main(int argc, char **argv)\n+{\n+\tint num_sched = 0;\n+\n+\t/* basic DPDK initialization is all that is necessary to run lthreads*/\n+\tint ret = rte_eal_init(argc, argv);\n+\n+\tif (ret < 0)\n+\t\trte_exit(EXIT_FAILURE, \"Invalid EAL parameters\\n\");\n+\n+\t/* enable timer subsystem */\n+\trte_timer_subsystem_init();\n+\n+#if DEBUG_APP\n+\tlthread_diagnostic_set_mask(LT_DIAG_ALL);\n+#endif\n+\n+\t/* create a scheduler on every core in the core mask\n+\t * and launch an initial lthread that will spawn many more.\n+\t */\n+\tunsigned lcore_id;\n+\n+\tfor (lcore_id = 0; lcore_id < RTE_MAX_LCORE; lcore_id++) {\n+\t\tif (rte_lcore_is_enabled(lcore_id))\n+\t\t\tnum_sched++;\n+\t}\n+\n+\t/* set the number of schedulers, this forces all schedulers synchronize\n+\t * before entering their main loop\n+\t */\n+\tlthread_num_schedulers_set(num_sched);\n+\n+\t/* launch all threads */\n+\trte_eal_mp_remote_launch(lthread_scheduler, (void *)NULL, CALL_MASTER);\n+\n+\t/* wait for threads to stop */\n+\tRTE_LCORE_FOREACH_SLAVE(lcore_id) {\n+\t\trte_eal_wait_lcore(lcore_id);\n+\t}\n+\treturn 0;\n+}\ndiff --git a/examples/performance-thread/pthread_shim/pthread_shim.c b/examples/performance-thread/pthread_shim/pthread_shim.c\nnew file mode 100644\nindex 0000000..87026f1\n--- /dev/null\n+++ b/examples/performance-thread/pthread_shim/pthread_shim.c\n@@ -0,0 +1,714 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#include <stdio.h>\n+#include <stdlib.h>\n+#include <sys/types.h>\n+#include <errno.h>\n+#define __USE_GNU\n+#include <sched.h>\n+#include <dlfcn.h>\n+\n+#include <rte_config.h>\n+#include <rte_log.h>\n+\n+#include \"lthread_api.h\"\n+#include \"pthread_shim.h\"\n+\n+#define RTE_LOGTYPE_PTHREAD_SHIM RTE_LOGTYPE_USER3\n+\n+#define POSIX_ERRNO(x)  (x)\n+\n+/*\n+ * this flag determines at run time if we override pthread\n+ * calls and map then to equivalent lthread calls\n+ * or of we call the standard pthread function\n+ */\n+static __thread int override;\n+\n+\n+/*\n+ * this structures contains function pointers that will be\n+ * initialised to the loaded address of the real\n+ * pthread library API functions\n+ */\n+struct pthread_lib_funcs {\n+int (*f_pthread_barrier_destroy)\n+\t(pthread_barrier_t *);\n+int (*f_pthread_barrier_init)\n+\t(pthread_barrier_t *, const pthread_barrierattr_t *, unsigned);\n+int (*f_pthread_barrier_wait)\n+\t(pthread_barrier_t *);\n+int (*f_pthread_cond_broadcast)\n+\t(pthread_cond_t *);\n+int (*f_pthread_cond_destroy)\n+\t(pthread_cond_t *);\n+int (*f_pthread_cond_init)\n+\t(pthread_cond_t *, const pthread_condattr_t *);\n+int (*f_pthread_cond_signal)\n+\t(pthread_cond_t *);\n+int (*f_pthread_cond_timedwait)\n+\t(pthread_cond_t *, pthread_mutex_t *, const struct timespec *);\n+int (*f_pthread_cond_wait)\n+\t(pthread_cond_t *, pthread_mutex_t *);\n+int (*f_pthread_create)\n+\t(pthread_t *, const pthread_attr_t *, void *(*)(void *), void *);\n+int (*f_pthread_detach)\n+\t(pthread_t);\n+int (*f_pthread_equal)\n+\t(pthread_t, pthread_t);\n+void (*f_pthread_exit)\n+\t(void *);\n+void * (*f_pthread_getspecific)\n+\t(pthread_key_t);\n+int (*f_pthread_getcpuclockid)\n+\t(pthread_t, clockid_t *);\n+int (*f_pthread_join)\n+\t(pthread_t, void **);\n+int (*f_pthread_key_create)\n+\t(pthread_key_t *, void (*) (void *));\n+int (*f_pthread_key_delete)\n+\t(pthread_key_t);\n+int (*f_pthread_mutex_destroy)\n+\t(pthread_mutex_t *__mutex);\n+int (*f_pthread_mutex_init)\n+\t(pthread_mutex_t *__mutex, const pthread_mutexattr_t *);\n+int (*f_pthread_mutex_lock)\n+\t(pthread_mutex_t *__mutex);\n+int (*f_pthread_mutex_trylock)\n+\t(pthread_mutex_t *__mutex);\n+int (*f_pthread_mutex_timedlock)\n+\t(pthread_mutex_t *__mutex, const struct timespec *);\n+int (*f_pthread_mutex_unlock)\n+\t(pthread_mutex_t *__mutex);\n+int (*f_pthread_once)\n+\t(pthread_once_t *, void (*) (void));\n+int (*f_pthread_rwlock_destroy)\n+\t(pthread_rwlock_t *__rwlock);\n+int (*f_pthread_rwlock_init)\n+\t(pthread_rwlock_t *__rwlock, const pthread_rwlockattr_t *);\n+int (*f_pthread_rwlock_rdlock)\n+\t(pthread_rwlock_t *__rwlock);\n+int (*f_pthread_rwlock_timedrdlock)\n+\t(pthread_rwlock_t *__rwlock, const struct timespec *);\n+int (*f_pthread_rwlock_timedwrlock)\n+\t(pthread_rwlock_t *__rwlock, const struct timespec *);\n+int (*f_pthread_rwlock_tryrdlock)\n+\t(pthread_rwlock_t *__rwlock);\n+int (*f_pthread_rwlock_trywrlock)\n+\t(pthread_rwlock_t *__rwlock);\n+int (*f_pthread_rwlock_unlock)\n+\t(pthread_rwlock_t *__rwlock);\n+int (*f_pthread_rwlock_wrlock)\n+\t(pthread_rwlock_t *__rwlock);\n+pthread_t (*f_pthread_self)\n+\t(void);\n+int (*f_pthread_setspecific)\n+\t(pthread_key_t, const void *);\n+int (*f_pthread_spin_init)\n+\t(pthread_spinlock_t *__spin, int);\n+int (*f_pthread_spin_destroy)\n+\t(pthread_spinlock_t *__spin);\n+int (*f_pthread_spin_lock)\n+\t(pthread_spinlock_t *__spin);\n+int (*f_pthread_spin_trylock)\n+\t(pthread_spinlock_t *__spin);\n+int (*f_pthread_spin_unlock)\n+\t(pthread_spinlock_t *__spin);\n+int (*f_pthread_cancel)\n+\t(pthread_t);\n+int (*f_pthread_setcancelstate)\n+\t(int, int *);\n+int (*f_pthread_setcanceltype)\n+\t(int, int *);\n+void (*f_pthread_testcancel)\n+\t(void);\n+int (*f_pthread_getschedparam)\n+\t(pthread_t pthread, int *, struct sched_param *);\n+int (*f_pthread_setschedparam)\n+\t(pthread_t, int, const struct sched_param *);\n+int (*f_pthread_yield)\n+\t(void);\n+int (*f_pthread_setaffinity_np)\n+\t(pthread_t thread, size_t cpusetsize, const cpu_set_t *cpuset);\n+int (*f_nanosleep)\n+\t(const struct timespec *req, struct timespec *rem);\n+} _sys_pthread_funcs = {\n+\t.f_pthread_barrier_destroy = NULL,\n+};\n+\n+\n+/*\n+ * this macro obtains the loaded address of a library function\n+ * and saves it.\n+ */\n+static void *__libc_dl_handle = RTLD_NEXT;\n+\n+#define get_addr_of_loaded_symbol(name) do {\t\t\t\t\\\n+\tchar *error_str;\t\t\t\t\t\t\\\n+\t_sys_pthread_funcs.f_##name = dlsym(__libc_dl_handle, (#name));\t\\\n+\terror_str = dlerror();\t\t\t\t\t\t\\\n+\tif (error_str != NULL) {\t\t\t\t\t\\\n+\t\tfprintf(stderr, \"%s\\n\", error_str);\t\t\t\\\n+\t\t*((int *)0) = 0;                                        \\\n+\t}\t\t\t\t\t\t\t\t\\\n+} while (0)\n+\n+\n+/*\n+ * The constructor function initialises the\n+ * function pointers for pthread library functions\n+ */\n+void\n+pthread_intercept_ctor(void)__attribute__((constructor));\n+void\n+pthread_intercept_ctor(void)\n+{\n+\toverride = 0;\n+\t/*\n+\t * Get the original functions\n+\t */\n+\tget_addr_of_loaded_symbol(pthread_barrier_destroy);\n+\tget_addr_of_loaded_symbol(pthread_barrier_init);\n+\tget_addr_of_loaded_symbol(pthread_barrier_wait);\n+\tget_addr_of_loaded_symbol(pthread_cond_broadcast);\n+\tget_addr_of_loaded_symbol(pthread_cond_destroy);\n+\tget_addr_of_loaded_symbol(pthread_cond_init);\n+\tget_addr_of_loaded_symbol(pthread_cond_signal);\n+\tget_addr_of_loaded_symbol(pthread_cond_timedwait);\n+\tget_addr_of_loaded_symbol(pthread_cond_wait);\n+\tget_addr_of_loaded_symbol(pthread_create);\n+\tget_addr_of_loaded_symbol(pthread_detach);\n+\tget_addr_of_loaded_symbol(pthread_equal);\n+\tget_addr_of_loaded_symbol(pthread_exit);\n+\tget_addr_of_loaded_symbol(pthread_getspecific);\n+\tget_addr_of_loaded_symbol(pthread_getcpuclockid);\n+\tget_addr_of_loaded_symbol(pthread_join);\n+\tget_addr_of_loaded_symbol(pthread_key_create);\n+\tget_addr_of_loaded_symbol(pthread_key_delete);\n+\tget_addr_of_loaded_symbol(pthread_mutex_destroy);\n+\tget_addr_of_loaded_symbol(pthread_mutex_init);\n+\tget_addr_of_loaded_symbol(pthread_mutex_lock);\n+\tget_addr_of_loaded_symbol(pthread_mutex_trylock);\n+\tget_addr_of_loaded_symbol(pthread_mutex_timedlock);\n+\tget_addr_of_loaded_symbol(pthread_mutex_unlock);\n+\tget_addr_of_loaded_symbol(pthread_once);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_destroy);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_init);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_rdlock);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_timedrdlock);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_timedwrlock);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_tryrdlock);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_trywrlock);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_unlock);\n+\tget_addr_of_loaded_symbol(pthread_rwlock_wrlock);\n+\tget_addr_of_loaded_symbol(pthread_self);\n+\tget_addr_of_loaded_symbol(pthread_setspecific);\n+\tget_addr_of_loaded_symbol(pthread_spin_init);\n+\tget_addr_of_loaded_symbol(pthread_spin_destroy);\n+\tget_addr_of_loaded_symbol(pthread_spin_lock);\n+\tget_addr_of_loaded_symbol(pthread_spin_trylock);\n+\tget_addr_of_loaded_symbol(pthread_spin_unlock);\n+\tget_addr_of_loaded_symbol(pthread_cancel);\n+\tget_addr_of_loaded_symbol(pthread_setcancelstate);\n+\tget_addr_of_loaded_symbol(pthread_setcanceltype);\n+\tget_addr_of_loaded_symbol(pthread_testcancel);\n+\tget_addr_of_loaded_symbol(pthread_getschedparam);\n+\tget_addr_of_loaded_symbol(pthread_setschedparam);\n+\tget_addr_of_loaded_symbol(pthread_yield);\n+\tget_addr_of_loaded_symbol(pthread_setaffinity_np);\n+\tget_addr_of_loaded_symbol(nanosleep);\n+}\n+\n+\n+/*\n+ * Enable/Disable pthread override\n+ * state\n+ *  0 disable\n+ *  1 enable\n+ */\n+void pthread_override_set(int state)\n+{\n+\toverride = state;\n+}\n+\n+\n+/*\n+ * Return pthread override state\n+ * return\n+ *  0 disable\n+ *  1 enable\n+ */\n+int pthread_override_get(void)\n+{\n+\treturn override;\n+}\n+\n+/*\n+ * This macro is used to catch and log\n+ * invocation of stubs for unimplemented pthread\n+ * API functions.\n+ */\n+#define NOT_IMPLEMENTED do {\t\t\t\t\\\n+\tif (override) {\t\t\t\t\t\\\n+\t\tRTE_LOG(WARNING,\t\t\t\\\n+\t\t\tPTHREAD_SHIM,\t\t\t\\\n+\t\t\t\"WARNING %s NOT IMPLEMENTED\\n\",\t\\\n+\t\t\t__func__);\t\t\t\\\n+\t}\t\t\t\t\t\t\\\n+} while (0)\n+\n+/*\n+ * pthread API override functions follow\n+ * Note in this example code only a subset of functions are\n+ * implemented.\n+ *\n+ * The stub functions provided will issue a warning log\n+ * message if an unimplemented function is invoked\n+ *\n+ */\n+\n+int pthread_barrier_destroy(pthread_barrier_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_barrier_destroy(a);\n+}\n+\n+int\n+pthread_barrier_init(pthread_barrier_t *a,\n+\t\t     const pthread_barrierattr_t *b, unsigned c)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_barrier_init(a, b, c);\n+}\n+\n+int pthread_barrier_wait(pthread_barrier_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_barrier_wait(a);\n+}\n+\n+int pthread_cond_broadcast(pthread_cond_t *cond)\n+{\n+\tif (override) {\n+\n+\t\tlthread_cond_broadcast(*(struct lthread_cond **)cond);\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_cond_broadcast(cond);\n+}\n+\n+int pthread_cond_destroy(pthread_cond_t *cond)\n+{\n+\tif (override)\n+\t\treturn -lthread_cond_destroy(*(struct lthread_cond **)cond);\n+\treturn _sys_pthread_funcs.f_pthread_cond_destroy(cond);\n+}\n+\n+int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *attr)\n+{\n+\tif (override)\n+\t\treturn -lthread_cond_init(NULL,\n+\t\t\t\t(struct lthread_cond **)cond,\n+\t\t\t\t(const struct lthread_condattr *) attr);\n+\treturn _sys_pthread_funcs.f_pthread_cond_init(cond, attr);\n+}\n+\n+int pthread_cond_signal(pthread_cond_t *cond)\n+{\n+\tif (override) {\n+\t\tlthread_cond_signal(*(struct lthread_cond **)cond);\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_cond_signal(cond);\n+}\n+\n+int\n+pthread_cond_timedwait(pthread_cond_t *__restrict cond,\n+\t\t       pthread_mutex_t *__restrict mutex,\n+\t\t       const struct timespec *__restrict time)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_cond_timedwait(cond, mutex, time);\n+}\n+\n+int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)\n+{\n+\tif (override) {\n+\t\tpthread_mutex_unlock(mutex);\n+\t\tint rv = lthread_cond_wait(*(struct lthread_cond **)cond, 0);\n+\n+\t\tpthread_mutex_lock(mutex);\n+\t\treturn rv;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_cond_wait(cond, mutex);\n+}\n+\n+int\n+pthread_create(pthread_t *__restrict tid,\n+\t\tconst pthread_attr_t *__restrict attr,\n+\t\tvoid *(func) (void *),\n+\t       void *__restrict arg)\n+{\n+\tif (override) {\n+\t\tint lcore = -1;\n+\n+\t\tif (attr != NULL) {\n+\t\t\t/* determine CPU being requested */\n+\t\t\tcpu_set_t cpuset;\n+\n+\t\t\tCPU_ZERO(&cpuset);\n+\t\t\tpthread_attr_getaffinity_np(attr,\n+\t\t\t\t\t\tsizeof(cpu_set_t),\n+\t\t\t\t\t\t&cpuset);\n+\n+\t\t\tif (CPU_COUNT(&cpuset) != 1)\n+\t\t\t\treturn POSIX_ERRNO(EINVAL);\n+\n+\t\t\tfor (lcore = 0; lcore < LTHREAD_MAX_LCORES; lcore++) {\n+\t\t\t\tif (!CPU_ISSET(lcore, &cpuset))\n+\t\t\t\t\tcontinue;\n+\t\t\t\tbreak;\n+\t\t\t}\n+\t\t}\n+\t\treturn lthread_create((struct lthread **)tid, lcore,\n+\t\t\t\t      (void (*)(void *))func, arg);\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_create(tid, attr, func, arg);\n+}\n+\n+int pthread_detach(pthread_t tid)\n+{\n+\tif (override) {\n+\t\tstruct lthread *lt = (struct lthread *)tid;\n+\n+\t\tif (lt == lthread_current())\n+\t\t\tlthread_detach();\n+\t\t\treturn 0;\n+\t\tNOT_IMPLEMENTED;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_detach(tid);\n+}\n+\n+int pthread_equal(pthread_t a, pthread_t b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_equal(a, b);\n+}\n+\n+void pthread_exit_override(void *v)\n+{\n+\tif (override) {\n+\t\tlthread_exit(v);\n+\t\treturn;\n+\t}\n+\t_sys_pthread_funcs.f_pthread_exit(v);\n+}\n+\n+void\n+*pthread_getspecific(pthread_key_t key)\n+{\n+\tif (override)\n+\t\treturn lthread_getspecific((unsigned int) key);\n+\treturn _sys_pthread_funcs.f_pthread_getspecific(key);\n+}\n+\n+int pthread_getcpuclockid(pthread_t a, clockid_t *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_getcpuclockid(a, b);\n+}\n+\n+int pthread_join(pthread_t tid, void **val)\n+{\n+\tif (override)\n+\t\treturn lthread_join((struct lthread *)tid, val);\n+\treturn _sys_pthread_funcs.f_pthread_join(tid, val);\n+}\n+\n+int pthread_key_create(pthread_key_t *keyptr, void (*dtor) (void *))\n+{\n+\tif (override)\n+\t\treturn lthread_key_create((unsigned int *)keyptr, dtor);\n+\treturn _sys_pthread_funcs.f_pthread_key_create(keyptr, dtor);\n+}\n+\n+int pthread_key_delete(pthread_key_t key)\n+{\n+\tif (override) {\n+\t\tlthread_key_delete((unsigned int) key);\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_key_delete(key);\n+}\n+\n+\n+int\n+pthread_mutex_init(pthread_mutex_t *mutex, const pthread_mutexattr_t *attr)\n+{\n+\tif (override)\n+\t\treturn lthread_mutex_init(NULL,\n+\t\t\t\t(struct lthread_mutex **)mutex,\n+\t\t\t\t(const struct lthread_mutexattr *)attr);\n+\treturn _sys_pthread_funcs.f_pthread_mutex_init(mutex, attr);\n+}\n+\n+int pthread_mutex_lock(pthread_mutex_t *mutex)\n+{\n+\tif (override)\n+\t\treturn lthread_mutex_lock(*(struct lthread_mutex **)mutex);\n+\treturn _sys_pthread_funcs.f_pthread_mutex_lock(mutex);\n+}\n+\n+int pthread_mutex_trylock(pthread_mutex_t *mutex)\n+{\n+\tif (override)\n+\t\treturn lthread_mutex_trylock(*(struct lthread_mutex **)mutex);\n+\treturn _sys_pthread_funcs.f_pthread_mutex_trylock(mutex);\n+}\n+\n+int pthread_mutex_timedlock(pthread_mutex_t *mutex, const struct timespec *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_mutex_timedlock(mutex, b);\n+}\n+\n+int pthread_mutex_unlock(pthread_mutex_t *mutex)\n+{\n+\tif (override)\n+\t\treturn lthread_mutex_unlock(*(struct lthread_mutex **)mutex);\n+\treturn _sys_pthread_funcs.f_pthread_mutex_unlock(mutex);\n+}\n+\n+int pthread_once(pthread_once_t *a, void (b) (void))\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_once(a, b);\n+}\n+\n+int pthread_rwlock_destroy(pthread_rwlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_destroy(a);\n+}\n+\n+int pthread_rwlock_init(pthread_rwlock_t *a, const pthread_rwlockattr_t *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_init(a, b);\n+}\n+\n+int pthread_rwlock_rdlock(pthread_rwlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_rdlock(a);\n+}\n+\n+int pthread_rwlock_timedrdlock(pthread_rwlock_t *a, const struct timespec *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_timedrdlock(a, b);\n+}\n+\n+int pthread_rwlock_timedwrlock(pthread_rwlock_t *a, const struct timespec *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_timedwrlock(a, b);\n+}\n+\n+int pthread_rwlock_tryrdlock(pthread_rwlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_tryrdlock(a);\n+}\n+\n+int pthread_rwlock_trywrlock(pthread_rwlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_trywrlock(a);\n+}\n+\n+int pthread_rwlock_unlock(pthread_rwlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_unlock(a);\n+}\n+\n+int pthread_rwlock_wrlock(pthread_rwlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_rwlock_wrlock(a);\n+}\n+\n+int pthread_yield(void)\n+{\n+\tif (override) {\n+\t\tlthread_yield();\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_yield();\n+\n+}\n+\n+pthread_t pthread_self(void)\n+{\n+\tif (override)\n+\t\treturn (pthread_t) lthread_current();\n+\treturn _sys_pthread_funcs.f_pthread_self();\n+}\n+\n+int pthread_setspecific(pthread_key_t key, const void *data)\n+{\n+\tif (override) {\n+\t\tint rv =  lthread_setspecific((unsigned int)key, data);\n+\t\treturn rv;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_setspecific(key, data);\n+}\n+\n+int pthread_spin_init(pthread_spinlock_t *a, int b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_spin_init(a, b);\n+}\n+\n+int pthread_spin_destroy(pthread_spinlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_spin_destroy(a);\n+}\n+\n+int pthread_spin_lock(pthread_spinlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_spin_lock(a);\n+}\n+\n+int pthread_spin_trylock(pthread_spinlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_spin_trylock(a);\n+}\n+\n+int pthread_spin_unlock(pthread_spinlock_t *a)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_spin_unlock(a);\n+}\n+\n+int pthread_cancel(pthread_t tid)\n+{\n+\tif (override) {\n+\t\tlthread_cancel(*(struct lthread **)tid);\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_cancel(tid);\n+}\n+\n+int pthread_setcancelstate(int a, int *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_setcancelstate(a, b);\n+}\n+\n+int pthread_setcanceltype(int a, int *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_setcanceltype(a, b);\n+}\n+\n+void pthread_testcancel(void)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_testcancel();\n+}\n+\n+\n+int pthread_getschedparam(pthread_t tid, int *a, struct sched_param *b)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_getschedparam(tid, a, b);\n+}\n+\n+int pthread_setschedparam(pthread_t a, int b, const struct sched_param *c)\n+{\n+\tNOT_IMPLEMENTED;\n+\treturn _sys_pthread_funcs.f_pthread_setschedparam(a, b, c);\n+}\n+\n+\n+int nanosleep(const struct timespec *req, struct timespec *rem)\n+{\n+\tif (override) {\n+\t\tuint64_t ns = req->tv_sec * 1000000000 + req->tv_nsec;\n+\n+\t\tlthread_sleep(ns);\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_nanosleep(req, rem);\n+}\n+\n+int\n+pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,\n+\t\t       const cpu_set_t *cpuset)\n+{\n+\tif (override) {\n+\t\t/* we only allow affinity with a single CPU */\n+\t\tif (CPU_COUNT(cpuset) != 1)\n+\t\t\treturn POSIX_ERRNO(EINVAL);\n+\n+\t\t/* we only allow the current thread to sets its own affinity */\n+\t\tstruct lthread *lt = (struct lthread *)thread;\n+\n+\t\tif (lthread_current() != lt)\n+\t\t\treturn POSIX_ERRNO(EINVAL);\n+\n+\t\t/* determine the CPU being requested */\n+\t\tint i;\n+\n+\t\tfor (i = 0; i < LTHREAD_MAX_LCORES; i++) {\n+\t\t\tif (!CPU_ISSET(i, cpuset))\n+\t\t\t\tcontinue;\n+\t\t\tbreak;\n+\t\t}\n+\t\t/* check requested core is allowed */\n+\t\tif (i == LTHREAD_MAX_LCORES)\n+\t\t\treturn POSIX_ERRNO(EINVAL);\n+\n+\t\t/* finally we can set affinity to the requested lcore */\n+\t\tlthread_set_affinity(i);\n+\t\treturn 0;\n+\t}\n+\treturn _sys_pthread_funcs.f_pthread_setaffinity_np(thread, cpusetsize,\n+\t\t\t\t\t\t\t   cpuset);\n+}\ndiff --git a/examples/performance-thread/pthread_shim/pthread_shim.h b/examples/performance-thread/pthread_shim/pthread_shim.h\nnew file mode 100644\nindex 0000000..0950082\n--- /dev/null\n+++ b/examples/performance-thread/pthread_shim/pthread_shim.h\n@@ -0,0 +1,113 @@\n+/*-\n+ *   BSD LICENSE\n+ *\n+ *   Copyright(c) 2010-2014 Intel Corporation. All rights reserved.\n+ *   All rights reserved.\n+ *\n+ *   Redistribution and use in source and binary forms, with or without\n+ *   modification, are permitted provided that the following conditions\n+ *   are met:\n+ *\n+ *     * Redistributions of source code must retain the above copyright\n+ *       notice, this list of conditions and the following disclaimer.\n+ *     * Redistributions in binary form must reproduce the above copyright\n+ *       notice, this list of conditions and the following disclaimer in\n+ *       the documentation and/or other materials provided with the\n+ *       distribution.\n+ *     * Neither the name of Intel Corporation nor the names of its\n+ *       contributors may be used to endorse or promote products derived\n+ *       from this software without specific prior written permission.\n+ *\n+ *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS\n+ *   \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT\n+ *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR\n+ *   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT\n+ *   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,\n+ *   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\n+ *   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\n+ *   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\n+ *   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n+ *   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\n+ *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n+ */\n+\n+#ifndef _PTHREAD_SHIM_H_\n+#define _PTHREAD_SHIM_H_\n+#include <pthread.h>\n+\n+/*\n+ * This pthread shim is an example that demonstrates how legacy code\n+ * that makes use of POSIX pthread services can make use of lthreads\n+ * with reduced porting effort.\n+ *\n+ * N.B. The example is not a complete implementation, only a subset of\n+ * pthread APIs sufficient to demonstrate the principle of operation\n+ * are implemented.\n+ *\n+ * In general pthread attribute objects do not have equivalent functions\n+ * in lthreads, and are ignored.\n+ *\n+ * There is one exception and that is the use of attr to specify a\n+ * core affinity in calls to pthread_create.\n+ *\n+ * The shim operates as follows:-\n+ *\n+ * On initialisation a constructor function uses dlsym to obtain and\n+ * save the loaded address of the full set of pthread APIs that will\n+ * be overridden.\n+ *\n+ * For each function there is a stub provided that will invoke either\n+ * the genuine pthread library function saved saved by the constructor,\n+ * or else the corresponding equivalent lthread function.\n+ *\n+ * The stub functions are implemented in pthread_shim.c\n+ *\n+ * The stub will take care of adapting parameters, and any police\n+ * any constraints where lthread functionality differs.\n+ *\n+ * The initial thread must always be a pure lthread.\n+ *\n+ * The decision whether to invoke the real library function or the lthread\n+ * function is controlled by a per pthread flag that can be switched\n+ * on of off by the pthread_override_set() API described below. Typcially\n+ * this should be done as the first action of the initial lthread.\n+ *\n+ * N.B In general it would be poor practice to revert to invoke a real\n+ * pthread function when running as an lthread, since these may block and\n+ * effectively stall the lthread scheduler.\n+ *\n+ */\n+\n+\n+/*\n+ * An exiting lthread must not terminate the pthread it is running in\n+ * since this would mean terminating the lthread scheduler.\n+ * We override pthread_exit() with a macro because it is typically declared with\n+ * __attribute__((noreturn))\n+ */\n+void pthread_exit_override(void *v);\n+\n+#define pthread_exit(v) do { \\\n+\tpthread_exit_override((v));\t\\\n+\treturn NULL;\t\\\n+} while (0)\n+\n+/*\n+ * Enable/Disable pthread override\n+ * state\n+ * 0 disable\n+ * 1 enable\n+ */\n+void pthread_override_set(int state);\n+\n+\n+/*\n+ * Return pthread override state\n+ * return\n+ * 0 disable\n+ * 1 enable\n+ */\n+int pthread_override_get(void);\n+\n+\n+#endif /* _PTHREAD_SHIM_H_ */\n",
    "prefixes": [
        "dpdk-dev",
        "v1",
        "4/5"
    ]
}