From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <Harini.Ramakrishnan@microsoft.com>
Received: from NAM01-SN1-obe.outbound.protection.outlook.com
 (mail-eopbgr820122.outbound.protection.outlook.com [40.107.82.122])
 by dpdk.org (Postfix) with ESMTP id 505311B39F
 for <dev@dpdk.org>; Tue, 26 Mar 2019 17:32:22 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=selector1;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=teHnvQNq+AHFsuoYvj48peOYFp043dLAmcBUM9/RMmc=;
 b=JfoM1/xClHbP2jBIJElktDVlHRgOgzYL9dgHQhO1CbaoKGc3E9VFzg4fZqRHZoBykZEG97qDIabpy4L/r4nN0kQukVVOj8GM+ecaWWbUXECPoQVsGkGUflTpPj6SWoCt8Rbx/cPONCKIONVs1V54VT6XWsieyNvOOp2kfcwmk50=
Received: from MWHPR21MB0638.namprd21.prod.outlook.com (10.175.141.139) by
 MWHPR21MB0176.namprd21.prod.outlook.com (10.173.52.22) with Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.1771.3; Tue, 26 Mar 2019 16:32:20 +0000
Received: from MWHPR21MB0638.namprd21.prod.outlook.com
 ([fe80::c4e7:ece1:887e:b983]) by MWHPR21MB0638.namprd21.prod.outlook.com
 ([fe80::c4e7:ece1:887e:b983%3]) with mapi id 15.20.1771.002; Tue, 26 Mar 2019
 16:32:20 +0000
From: Harini Ramakrishnan <Harini.Ramakrishnan@microsoft.com>
To: Anand Rawat <anand.rawat@intel.com>, "dev@dpdk.org" <dev@dpdk.org>
CC: "pallavi.kadam@intel.com" <pallavi.kadam@intel.com>,
 "ranjit.menon@intel.com" <ranjit.menon@intel.com>, "jeffrey.b.shaw@intel.com"
 <jeffrey.b.shaw@intel.com>, "bruce.richardson@intel.com"
 <bruce.richardson@intel.com>, "thomas@monjalon.net" <thomas@monjalon.net>
Thread-Topic: [dpdk-dev] [PATCH v5 6/8] eal: add minimum viable code for eal
 on	windows
Thread-Index: AQHU45mmoeLI8Z8PX0S50C5i/hUkqKYeG5hQ
Date: Tue, 26 Mar 2019 16:32:20 +0000
Message-ID: <MWHPR21MB06382E26D467C9AA068118ACEF5F0@MWHPR21MB0638.namprd21.prod.outlook.com>
References: <20190306041634.12976-1-anand.rawat@intel.com>
 <20190326060238.9884-1-anand.rawat@intel.com>
 <20190326060238.9884-7-anand.rawat@intel.com>
In-Reply-To: <20190326060238.9884-7-anand.rawat@intel.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
msip_labels: MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Enabled=True;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SiteId=72f988bf-86f1-41af-91ab-2d7cd011db47;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Owner=haramakr@microsoft.com; 
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SetDate=2019-03-26T16:32:15.0948816Z;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Name=General;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Application=Microsoft Azure
 Information Protection;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_ActionId=677433eb-d16b-4094-84f7-7ff37b75995f;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Extended_MSFT_Method=Automatic
x-originating-ip: [131.107.147.44]
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: a11c0fb1-0021-4c3c-d75f-08d6b2089e72
x-ms-office365-filtering-ht: Tenant
x-microsoft-antispam: BCL:0; PCL:0;
 RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(4618075)(2017052603328)(7193020);
 SRVR:MWHPR21MB0176; 
x-ms-traffictypediagnostic: MWHPR21MB0176:
authentication-results: spf=none (sender IP is )
 smtp.mailfrom=Harini.Ramakrishnan@microsoft.com; 
x-microsoft-antispam-prvs: <MWHPR21MB017651C67F4E067EBEDD398DEF5F0@MWHPR21MB0176.namprd21.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:242;
x-forefront-prvs: 09888BC01D
x-forefront-antispam-report: SFV:NSPM;
 SFS:(10019020)(39860400002)(396003)(346002)(376002)(366004)(136003)(13464003)(189003)(199004)(14444005)(72206003)(102836004)(316002)(8936002)(256004)(478600001)(3846002)(105586002)(76176011)(7696005)(6436002)(74316002)(106356001)(22452003)(7736002)(81166006)(10090500001)(5660300002)(25786009)(4326008)(81156014)(30864003)(305945005)(2501003)(2906002)(229853002)(8990500004)(6116002)(53936002)(55016002)(6246003)(71190400001)(71200400001)(14454004)(9686003)(68736007)(52536014)(86612001)(446003)(10290500003)(11346002)(86362001)(476003)(26005)(186003)(99286004)(54906003)(110136005)(97736004)(6506007)(66066001)(53546011)(33656002)(486006);
 DIR:OUT; SFP:1102; SCL:1; SRVR:MWHPR21MB0176;
 H:MWHPR21MB0638.namprd21.prod.outlook.com; FPR:; SPF:None; LANG:en;
 PTR:InfoNoRecords; MX:1; A:1; 
received-spf: None (protection.outlook.com: microsoft.com does not designate
 permitted sender hosts)
x-ms-exchange-senderadcheck: 1
x-microsoft-antispam-message-info: 2iplRtJR9uJUwtlVgIFOfPTK+2T34kCrDjffRhp2td3UMnETQVXr/8trZayY4uXgCHUYRNssGwhNZIBW8MA3YuS0FbRnNVIFPUcOQkbHpIDgzm1j5IOCMDH+8lud/Eh85UMy9Cn14MVeEL6XUkq+MqavhcrI76nLCIgMfcD6kdha64lIdZpCiuLg7gsYgRj/UmUHpZrtEsyaSKBjiMgSHFKsOAtzykV+BwNnOrNHTmfuLJdiIkVKLW3Y0udoZ1cZ9gu3zZrdeTqvAwyXJ1ljaHsQBloHGGLFoFNdHiQExYDBvL2BxOAV32PtgZ5GO+JXIOXVPis7DzyjLsID7aUT6pY26Vjp/8EdBm3K0/WerequEipIqexHpEikngeTZ01gduhUMD7pvNt4tSwbyB9Kgt9WPlqrdbLuJdZS3YsNF94=
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-OriginatorOrg: microsoft.com
X-MS-Exchange-CrossTenant-Network-Message-Id: a11c0fb1-0021-4c3c-d75f-08d6b2089e72
X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Mar 2019 16:32:20.6021 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47
X-MS-Exchange-CrossTenant-mailboxtype: HOSTED
X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR21MB0176
Subject: Re: [dpdk-dev] [PATCH v5 6/8] eal: add minimum viable code for eal
	on	windows
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>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
X-List-Received-Date: Tue, 26 Mar 2019 16:32:22 -0000



-----Original Message-----
From: dev <dev-bounces@dpdk.org> On Behalf Of Anand Rawat
Sent: Monday, March 25, 2019 11:03 PM
To: dev@dpdk.org
Cc: anand.rawat@intel.com; pallavi.kadam@intel.com; ranjit.menon@intel.com;=
 jeffrey.b.shaw@intel.com; bruce.richardson@intel.com; thomas@monjalon.net
Subject: [dpdk-dev] [PATCH v5 6/8] eal: add minimum viable code for eal on =
windows

Add windows specific logic for eal.c, eal_lcore.c, eal_debug.c and eal_thre=
ad.c. Updated header files to contain suitable function declaractions.

Signed-off-by: Anand Rawat <anand.rawat@intel.com>
Signed-off-by: Pallavi Kadam <pallavi.kadam@intel.com>
Reviewed-by: Jeff Shaw <jeffrey.b.shaw@intel.com>
Reviewed-by: Ranjit Menon <ranjit.menon@intel.com>
Acked-by: Harini Ramakrishnan <harini.ramakrishnan@microsoft.com>
---
 lib/librte_eal/windows/eal/eal.c              |  76 ++++++++-
 lib/librte_eal/windows/eal/eal_debug.c        |  14 +-
 lib/librte_eal/windows/eal/eal_lcore.c        | 104 ++++++++++---
 lib/librte_eal/windows/eal/eal_thread.c       | 147 +++++++++++++++++-
 lib/librte_eal/windows/eal/include/regex.h    |   2 +
 .../windows/eal/include/rte_windows.h         |  20 +++
 6 files changed, 331 insertions(+), 32 deletions(-)

diff --git a/lib/librte_eal/windows/eal/eal.c b/lib/librte_eal/windows/eal/=
eal.c
index 13e41ea30..ce460481f 100644
--- a/lib/librte_eal/windows/eal/eal.c
+++ b/lib/librte_eal/windows/eal/eal.c
@@ -2,13 +2,83 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include "rte_common.h"
+#include <io.h>
+#include <fcntl.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <eal_thread.h>
+#include <eal_private.h>
+
+/* Address of global and public configuration */ static struct=20
+rte_config rte_config;
+
+/* internal configuration (per-core) */ struct lcore_config=20
+lcore_config[RTE_MAX_LCORE];
+
+/* Return a pointer to the configuration structure */ struct rte_config=20
+*
+rte_eal_get_configuration(void)
+{
+	return &rte_config;
+}
+
+static int
+sync_func(void *arg __rte_unused)
+{
+	return 0;
+}
+
+static void
+rte_eal_init_alert(const char *msg)
+{
+	fprintf(stderr, "EAL: FATAL: %s\n", msg);
+	RTE_LOG(ERR, EAL, "%s\n", msg);
+}
=20
  /* Launch threads, called at application init(). */  int  rte_eal_init(in=
t argc __rte_unused, char **argv __rte_unused)  {
-	/* TODO */
-	/* This is a stub, not the expected result */
+	int i;
+
+	/* create a map of all processors in the system */
+	eal_create_cpu_map();
+
+	if (rte_eal_cpu_init() < 0) {
+		rte_eal_init_alert("Cannot detect lcores.");
+		rte_errno =3D ENOTSUP;
+		return -1;
+	}
+
+	eal_thread_init_master(rte_config.master_lcore);
+
+	RTE_LCORE_FOREACH_SLAVE(i) {
+
+		/*
+		 * create communication pipes between master thread
+		 * and children
+		 */
+		if (_pipe(lcore_config[i].pipe_master2slave,
+			sizeof(char), _O_BINARY) < 0)
+			rte_panic("Cannot create pipe\n");
+		if (_pipe(lcore_config[i].pipe_slave2master,
+			sizeof(char), _O_BINARY) < 0)
+			rte_panic("Cannot create pipe\n");
+
+		lcore_config[i].state =3D WAIT;
+
+		/* create a thread for each lcore */
+		if (eal_thread_create(&lcore_config[i].thread_id) !=3D 0)
+			rte_panic("Cannot create thread\n");
+	}
+
+	/*
+	 * Launch a dummy function on all slave lcores, so that master lcore
+	 * knows they are all ready when this function returns.
+	 */
+	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
+	rte_eal_mp_wait_lcore();
 	return 0;
 }
diff --git a/lib/librte_eal/windows/eal/eal_debug.c b/lib/librte_eal/window=
s/eal/eal_debug.c
index 6e07fe10c..edcf257cc 100644
--- a/lib/librte_eal/windows/eal/eal_debug.c
+++ b/lib/librte_eal/windows/eal/eal_debug.c
@@ -2,14 +2,18 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include "rte_common.h"
+#include <stdarg.h>
+#include <rte_log.h>
=20
  /* call abort(), it will generate a coredump if enabled */  void -__rte_p=
anic(const char *funcname __rte_unused,
-		const char *format __rte_unused, ...)
+__rte_panic(const char *funcname, const char *format, ...)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
+	va_list ap;
+
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n", funcname);
+	va_start(ap, format);
+	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	va_end(ap);
 	abort();
 }
diff --git a/lib/librte_eal/windows/eal/eal_lcore.c b/lib/librte_eal/window=
s/eal/eal_lcore.c
index 4ddf51aa8..d39f348a3 100644
--- a/lib/librte_eal/windows/eal/eal_lcore.c
+++ b/lib/librte_eal/windows/eal/eal_lcore.c
@@ -2,31 +2,99 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include "rte_common.h"
+#include <stdint.h>
=20
- /* Get the cpu core id value */
-unsigned int
-eal_cpu_core_id(unsigned int lcore_id)
+#include <rte_common.h>
+
+/* global data structure that contains the CPU map */ static struct=20
+_wcpu_map {
+	unsigned int total_procs;
+	unsigned int proc_sockets;
+	unsigned int proc_cores;
+	unsigned int reserved;
+	struct _win_lcore_map {
+		uint8_t socket_id;
+		uint8_t core_id;
+	} wlcore_map[RTE_MAX_LCORE];
+} wcpu_map =3D { 0 };
+
+/*
+ * Create a map of all processors and associated cores on the system =20
+*/ void
+eal_create_cpu_map()
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
-	return lcore_id;
+	wcpu_map.total_procs =3D
+		GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
+
+	LOGICAL_PROCESSOR_RELATIONSHIP lprocRel;
+	DWORD lprocInfoSize =3D 0;
+	BOOL ht_enabled =3D FALSE;
+
+	/* First get the processor package information */
+	lprocRel =3D RelationProcessorPackage;
+	/* Determine the size of buffer we need (pass NULL) */
+	GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize);
+	wcpu_map.proc_sockets =3D lprocInfoSize / 48;
+
+	lprocInfoSize =3D 0;
+	/* Next get the processor core information */
+	lprocRel =3D RelationProcessorCore;
+	GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize);
+	wcpu_map.proc_cores =3D lprocInfoSize / 48;
+
+	if (wcpu_map.total_procs > wcpu_map.proc_cores)
+		ht_enabled =3D TRUE;
+
+	/* Distribute the socket and core ids appropriately
+	 * across the logical cores. For now, split the cores
+	 * equally across the sockets.
+	 */
+	unsigned int lcore =3D 0;
+	for (unsigned int socket =3D 0; socket <
+			wcpu_map.proc_sockets; ++socket) {
+		for (unsigned int core =3D 0;
+			core < (wcpu_map.proc_cores / wcpu_map.proc_sockets);
+			++core) {
+			wcpu_map.wlcore_map[lcore]
+					.socket_id =3D socket;
+			wcpu_map.wlcore_map[lcore]
+					.core_id =3D core;
+			lcore++;
+			if (ht_enabled) {
+				wcpu_map.wlcore_map[lcore]
+					.socket_id =3D socket;
+				wcpu_map.wlcore_map[lcore]
+					.core_id =3D core;
+				lcore++;
+			}
+		}
+	}
 }
=20
-/* Check if a cpu is present by the presence of the cpu information for it=
 */
+/*
+ * Check if a cpu is present by the presence of the cpu information for=20
+it  */
 int
-eal_cpu_detected(unsigned int lcore_id __rte_unused)
+eal_cpu_detected(unsigned int lcore_id) {
+	return (lcore_id < wcpu_map.total_procs); }
+
+/*
+ * Get CPU socket id for a logical core  */ unsigned=20
+eal_cpu_socket_id(unsigned int lcore_id)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
-	return 1;
+	return wcpu_map.wlcore_map[lcore_id].socket_id;
 }
=20
-/* Get CPU socket id (NUMA node) for a logical core */ -unsigned int -eal_=
cpu_socket_id(unsigned int cpu_id __rte_unused)
+/*
+ * Get CPU socket id (NUMA node) for a logical core  */ unsigned=20
+eal_cpu_core_id(unsigned int lcore_id)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
-	return 0;
+	return wcpu_map.wlcore_map[lcore_id].core_id;
 }
diff --git a/lib/librte_eal/windows/eal/eal_thread.c b/lib/librte_eal/windo=
ws/eal/eal_thread.c
index e74f8893b..906502f90 100644
--- a/lib/librte_eal/windows/eal/eal_thread.c
+++ b/lib/librte_eal/windows/eal/eal_thread.c
@@ -2,17 +2,152 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include <windows.h>
+#include <io.h>
=20
-#include "rte_common.h"
+#include <rte_atomic.h>
+#include <rte_debug.h>
+#include <rte_launch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_common.h>
+#include <eal_thread.h>
=20
-typedef uintptr_t eal_thread_t;
+
+RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) =3D LCORE_ID_ANY;
+
+/*
+ * Send a message to a slave lcore identified by slave_id to call a
+ * function f with argument arg. Once the execution is done, the
+ * remote lcore switch in FINISHED state.
+ */
+int
+rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int=20
+slave_id) {
+	int n;
+	char c =3D 0;
+	int m2s =3D lcore_config[slave_id].pipe_master2slave[1];
+	int s2m =3D lcore_config[slave_id].pipe_slave2master[0];
+
+	if (lcore_config[slave_id].state !=3D WAIT)
+		return -EBUSY;
+
+	lcore_config[slave_id].f =3D f;
+	lcore_config[slave_id].arg =3D arg;
+
+	/* send message */
+	n =3D 0;
+	while (n =3D=3D 0 || (n < 0 && errno =3D=3D EINTR))
+		n =3D _write(m2s, &c, 1);
+	if (n < 0)
+		rte_panic("cannot write on configuration pipe\n");
+
+	/* wait ack */
+	do {
+		n =3D _read(s2m, &c, 1);
+	} while (n < 0 && errno =3D=3D EINTR);
+
+	if (n <=3D 0)
+		rte_panic("cannot read on configuration pipe\n");
+
+	return 0;
+}
+
+void
+eal_thread_init_master(unsigned int lcore_id) {
+	/* set the lcore ID in per-lcore memory area */
+	RTE_PER_LCORE(_lcore_id) =3D lcore_id;
+}
+
+static inline pthread_t
+eal_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+/* main loop of threads */
+void *
+eal_thread_loop(void *arg __rte_unused) {
+	char c;
+	int n, ret;
+	unsigned int lcore_id;
+	pthread_t thread_id;
+	int m2s, s2m;
+	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
+
+	thread_id =3D eal_thread_self();
+
+	/* retrieve our lcore_id from the configuration structure */
+	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+		if (thread_id =3D=3D lcore_config[lcore_id].thread_id)
+			break;
+	}
+	if (lcore_id =3D=3D RTE_MAX_LCORE)
+		rte_panic("cannot retrieve lcore id\n");
+
+	m2s =3D lcore_config[lcore_id].pipe_master2slave[0];
+	s2m =3D lcore_config[lcore_id].pipe_slave2master[1];
+
+	/* set the lcore ID in per-lcore memory area */
+	RTE_PER_LCORE(_lcore_id) =3D lcore_id;
+
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=3D%zx;cpuset=3D[%s])\n",
+		lcore_id, (uintptr_t)thread_id, cpuset);
+
+	/* read on our pipe to get commands */
+	while (1) {
+		void *fct_arg;
+
+		/* wait command */
+		do {
+			n =3D _read(m2s, &c, 1);
+		} while (n < 0 && errno =3D=3D EINTR);
+
+		if (n <=3D 0)
+			rte_panic("cannot read on configuration pipe\n");
+
+		lcore_config[lcore_id].state =3D RUNNING;
+
+		/* send ack */
+		n =3D 0;
+		while (n =3D=3D 0 || (n < 0 && errno =3D=3D EINTR))
+			n =3D _write(s2m, &c, 1);
+		if (n < 0)
+			rte_panic("cannot write on configuration pipe\n");
+
+		if (lcore_config[lcore_id].f =3D=3D NULL)
+			rte_panic("NULL function pointer\n");
+
+		/* call the function and store the return value */
+		fct_arg =3D lcore_config[lcore_id].arg;
+		ret =3D lcore_config[lcore_id].f(fct_arg);
+		lcore_config[lcore_id].ret =3D ret;
+		rte_wmb();
+
+		/* when a service core returns, it should go directly to WAIT
+		 * state, because the application will not lcore_wait() for it.
+		 */
+		if (lcore_config[lcore_id].core_role =3D=3D ROLE_SERVICE)
+			lcore_config[lcore_id].state =3D WAIT;
+		else
+			lcore_config[lcore_id].state =3D FINISHED;
+	}
+}
=20
 /* function to create threads */
 int
-eal_thread_create(eal_thread_t *thread __rte_unused)
+eal_thread_create(pthread_t *thread)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
+	HANDLE th;
+
+	th =3D CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)eal_thread_loop,
+						NULL, 0, (LPDWORD)thread);
+	if (!th)
+		return -1;
+
+	SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
+	SetThreadPriority(th, THREAD_PRIORITY_TIME_CRITICAL);
+
 	return 0;
 }
diff --git a/lib/librte_eal/windows/eal/include/regex.h b/lib/librte_eal/wi=
ndows/eal/include/regex.h
index daa102f74..412b4edc5 100644
--- a/lib/librte_eal/windows/eal/include/regex.h
+++ b/lib/librte_eal/windows/eal/include/regex.h
@@ -12,6 +12,8 @@ extern "C" {
 #define REG_NOMATCH 1
 #define REG_ESPACE 12
=20
+#include <rte_common.h>
+
 /* defining regex_t for windows */
 typedef void *regex_t;
 /* defining regmatch_t for windows */
diff --git a/lib/librte_eal/windows/eal/include/rte_windows.h b/lib/librte_=
eal/windows/eal/include/rte_windows.h
index af24ef39f..46146e59b 100644
--- a/lib/librte_eal/windows/eal/include/rte_windows.h
+++ b/lib/librte_eal/windows/eal/include/rte_windows.h
@@ -9,7 +9,9 @@
 extern "C" {
 #endif
=20
+#include <Windows.h>
 #include <BaseTsd.h>
+#include <pthread.h>
=20
 /* macro substitution for windows supported strerror_r */  #define strerro=
r_r(a, b, c) strerror_s(b, c, a) @@ -23,6 +25,24 @@ typedef SSIZE_T ssize_t=
;
 /* macro substitution for windows supported strtok_r */  #define strtok_r(=
str, delim, saveptr) strtok_s(str, delim, saveptr)
=20
+/**
+ * Create a thread.
+ * This function is private to EAL.
+ *
+ * @param thread
+ *   The location to store the thread id if successful.
+ * @return
+ *   0 for success, -1 if the thread is not created.
+ */
+int eal_thread_create(pthread_t *thread);
+
+/**
+ * Create a map of processors and cores on the system.
+ * This function is private to EAL.
+ *
+ */
+void eal_create_cpu_map(void);
+
 #ifdef __cplusplus
 }
 #endif
--
2.17.1.windows.2

From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from dpdk.org (dpdk.org [92.243.14.124])
	by dpdk.space (Postfix) with ESMTP id 8CD7AA05D3
	for <public@inbox.dpdk.org>; Tue, 26 Mar 2019 17:32:24 +0100 (CET)
Received: from [92.243.14.124] (localhost [127.0.0.1])
	by dpdk.org (Postfix) with ESMTP id 456881B3C0;
	Tue, 26 Mar 2019 17:32:24 +0100 (CET)
Received: from NAM01-SN1-obe.outbound.protection.outlook.com
 (mail-eopbgr820122.outbound.protection.outlook.com [40.107.82.122])
 by dpdk.org (Postfix) with ESMTP id 505311B39F
 for <dev@dpdk.org>; Tue, 26 Mar 2019 17:32:22 +0100 (CET)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com;
 s=selector1;
 h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck;
 bh=teHnvQNq+AHFsuoYvj48peOYFp043dLAmcBUM9/RMmc=;
 b=JfoM1/xClHbP2jBIJElktDVlHRgOgzYL9dgHQhO1CbaoKGc3E9VFzg4fZqRHZoBykZEG97qDIabpy4L/r4nN0kQukVVOj8GM+ecaWWbUXECPoQVsGkGUflTpPj6SWoCt8Rbx/cPONCKIONVs1V54VT6XWsieyNvOOp2kfcwmk50=
Received: from MWHPR21MB0638.namprd21.prod.outlook.com (10.175.141.139) by
 MWHPR21MB0176.namprd21.prod.outlook.com (10.173.52.22) with Microsoft SMTP
 Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id
 15.20.1771.3; Tue, 26 Mar 2019 16:32:20 +0000
Received: from MWHPR21MB0638.namprd21.prod.outlook.com
 ([fe80::c4e7:ece1:887e:b983]) by MWHPR21MB0638.namprd21.prod.outlook.com
 ([fe80::c4e7:ece1:887e:b983%3]) with mapi id 15.20.1771.002; Tue, 26 Mar 2019
 16:32:20 +0000
From: Harini Ramakrishnan <Harini.Ramakrishnan@microsoft.com>
To: Anand Rawat <anand.rawat@intel.com>, "dev@dpdk.org" <dev@dpdk.org>
CC: "pallavi.kadam@intel.com" <pallavi.kadam@intel.com>,
 "ranjit.menon@intel.com" <ranjit.menon@intel.com>, "jeffrey.b.shaw@intel.com"
 <jeffrey.b.shaw@intel.com>, "bruce.richardson@intel.com"
 <bruce.richardson@intel.com>, "thomas@monjalon.net" <thomas@monjalon.net>
Thread-Topic: [dpdk-dev] [PATCH v5 6/8] eal: add minimum viable code for eal
 on	windows
Thread-Index: AQHU45mmoeLI8Z8PX0S50C5i/hUkqKYeG5hQ
Date: Tue, 26 Mar 2019 16:32:20 +0000
Message-ID:
 <MWHPR21MB06382E26D467C9AA068118ACEF5F0@MWHPR21MB0638.namprd21.prod.outlook.com>
References: <20190306041634.12976-1-anand.rawat@intel.com>
 <20190326060238.9884-1-anand.rawat@intel.com>
 <20190326060238.9884-7-anand.rawat@intel.com>
In-Reply-To: <20190326060238.9884-7-anand.rawat@intel.com>
Accept-Language: en-US
Content-Language: en-US
X-MS-Has-Attach: 
X-MS-TNEF-Correlator: 
msip_labels: MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Enabled=True;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SiteId=72f988bf-86f1-41af-91ab-2d7cd011db47;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Owner=haramakr@microsoft.com; 
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_SetDate=2019-03-26T16:32:15.0948816Z;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Name=General;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Application=Microsoft Azure
 Information Protection;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_ActionId=677433eb-d16b-4094-84f7-7ff37b75995f;
 MSIP_Label_f42aa342-8706-4288-bd11-ebb85995028c_Extended_MSFT_Method=Automatic
x-originating-ip: [131.107.147.44]
x-ms-publictraffictype: Email
x-ms-office365-filtering-correlation-id: a11c0fb1-0021-4c3c-d75f-08d6b2089e72
x-ms-office365-filtering-ht: Tenant
x-microsoft-antispam: BCL:0; PCL:0;
 RULEID:(2390118)(7020095)(4652040)(8989299)(4534185)(4627221)(201703031133081)(201702281549075)(8990200)(5600127)(711020)(4605104)(4618075)(2017052603328)(7193020);
 SRVR:MWHPR21MB0176; 
x-ms-traffictypediagnostic: MWHPR21MB0176:
authentication-results: spf=none (sender IP is )
 smtp.mailfrom=Harini.Ramakrishnan@microsoft.com; 
x-microsoft-antispam-prvs: <MWHPR21MB017651C67F4E067EBEDD398DEF5F0@MWHPR21MB0176.namprd21.prod.outlook.com>
x-ms-oob-tlc-oobclassifiers: OLM:242;
x-forefront-prvs: 09888BC01D
x-forefront-antispam-report: SFV:NSPM;
 SFS:(10019020)(39860400002)(396003)(346002)(376002)(366004)(136003)(13464003)(189003)(199004)(14444005)(72206003)(102836004)(316002)(8936002)(256004)(478600001)(3846002)(105586002)(76176011)(7696005)(6436002)(74316002)(106356001)(22452003)(7736002)(81166006)(10090500001)(5660300002)(25786009)(4326008)(81156014)(30864003)(305945005)(2501003)(2906002)(229853002)(8990500004)(6116002)(53936002)(55016002)(6246003)(71190400001)(71200400001)(14454004)(9686003)(68736007)(52536014)(86612001)(446003)(10290500003)(11346002)(86362001)(476003)(26005)(186003)(99286004)(54906003)(110136005)(97736004)(6506007)(66066001)(53546011)(33656002)(486006);
 DIR:OUT; SFP:1102; SCL:1; SRVR:MWHPR21MB0176;
 H:MWHPR21MB0638.namprd21.prod.outlook.com; FPR:; SPF:None; LANG:en;
 PTR:InfoNoRecords; MX:1; A:1; 
received-spf: None (protection.outlook.com: microsoft.com does not designate
 permitted sender hosts)
x-ms-exchange-senderadcheck: 1
x-microsoft-antispam-message-info: 2iplRtJR9uJUwtlVgIFOfPTK+2T34kCrDjffRhp2td3UMnETQVXr/8trZayY4uXgCHUYRNssGwhNZIBW8MA3YuS0FbRnNVIFPUcOQkbHpIDgzm1j5IOCMDH+8lud/Eh85UMy9Cn14MVeEL6XUkq+MqavhcrI76nLCIgMfcD6kdha64lIdZpCiuLg7gsYgRj/UmUHpZrtEsyaSKBjiMgSHFKsOAtzykV+BwNnOrNHTmfuLJdiIkVKLW3Y0udoZ1cZ9gu3zZrdeTqvAwyXJ1ljaHsQBloHGGLFoFNdHiQExYDBvL2BxOAV32PtgZ5GO+JXIOXVPis7DzyjLsID7aUT6pY26Vjp/8EdBm3K0/WerequEipIqexHpEikngeTZ01gduhUMD7pvNt4tSwbyB9Kgt9WPlqrdbLuJdZS3YsNF94=
Content-Type: text/plain; charset="UTF-8"
Content-Transfer-Encoding: quoted-printable
MIME-Version: 1.0
X-OriginatorOrg: microsoft.com
X-MS-Exchange-CrossTenant-Network-Message-Id: a11c0fb1-0021-4c3c-d75f-08d6b2089e72
X-MS-Exchange-CrossTenant-originalarrivaltime: 26 Mar 2019 16:32:20.6021 (UTC)
X-MS-Exchange-CrossTenant-fromentityheader: Hosted
X-MS-Exchange-CrossTenant-id: 72f988bf-86f1-41af-91ab-2d7cd011db47
X-MS-Exchange-CrossTenant-mailboxtype: HOSTED
X-MS-Exchange-Transport-CrossTenantHeadersStamped: MWHPR21MB0176
Subject: Re: [dpdk-dev] [PATCH v5 6/8] eal: add minimum viable code for eal
	on	windows
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>,
 <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>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org
Sender: "dev" <dev-bounces@dpdk.org>
Message-ID: <20190326163220.uHTfY5q36mcQfPVjyL7_cGB0QzVrCu4As5xNZWYKEkk@z>



-----Original Message-----
From: dev <dev-bounces@dpdk.org> On Behalf Of Anand Rawat
Sent: Monday, March 25, 2019 11:03 PM
To: dev@dpdk.org
Cc: anand.rawat@intel.com; pallavi.kadam@intel.com; ranjit.menon@intel.com;=
 jeffrey.b.shaw@intel.com; bruce.richardson@intel.com; thomas@monjalon.net
Subject: [dpdk-dev] [PATCH v5 6/8] eal: add minimum viable code for eal on =
windows

Add windows specific logic for eal.c, eal_lcore.c, eal_debug.c and eal_thre=
ad.c. Updated header files to contain suitable function declaractions.

Signed-off-by: Anand Rawat <anand.rawat@intel.com>
Signed-off-by: Pallavi Kadam <pallavi.kadam@intel.com>
Reviewed-by: Jeff Shaw <jeffrey.b.shaw@intel.com>
Reviewed-by: Ranjit Menon <ranjit.menon@intel.com>
Acked-by: Harini Ramakrishnan <harini.ramakrishnan@microsoft.com>
---
 lib/librte_eal/windows/eal/eal.c              |  76 ++++++++-
 lib/librte_eal/windows/eal/eal_debug.c        |  14 +-
 lib/librte_eal/windows/eal/eal_lcore.c        | 104 ++++++++++---
 lib/librte_eal/windows/eal/eal_thread.c       | 147 +++++++++++++++++-
 lib/librte_eal/windows/eal/include/regex.h    |   2 +
 .../windows/eal/include/rte_windows.h         |  20 +++
 6 files changed, 331 insertions(+), 32 deletions(-)

diff --git a/lib/librte_eal/windows/eal/eal.c b/lib/librte_eal/windows/eal/=
eal.c
index 13e41ea30..ce460481f 100644
--- a/lib/librte_eal/windows/eal/eal.c
+++ b/lib/librte_eal/windows/eal/eal.c
@@ -2,13 +2,83 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include "rte_common.h"
+#include <io.h>
+#include <fcntl.h>
+#include <rte_debug.h>
+#include <rte_eal.h>
+#include <rte_errno.h>
+#include <rte_lcore.h>
+#include <eal_thread.h>
+#include <eal_private.h>
+
+/* Address of global and public configuration */ static struct=20
+rte_config rte_config;
+
+/* internal configuration (per-core) */ struct lcore_config=20
+lcore_config[RTE_MAX_LCORE];
+
+/* Return a pointer to the configuration structure */ struct rte_config=20
+*
+rte_eal_get_configuration(void)
+{
+	return &rte_config;
+}
+
+static int
+sync_func(void *arg __rte_unused)
+{
+	return 0;
+}
+
+static void
+rte_eal_init_alert(const char *msg)
+{
+	fprintf(stderr, "EAL: FATAL: %s\n", msg);
+	RTE_LOG(ERR, EAL, "%s\n", msg);
+}
=20
  /* Launch threads, called at application init(). */  int  rte_eal_init(in=
t argc __rte_unused, char **argv __rte_unused)  {
-	/* TODO */
-	/* This is a stub, not the expected result */
+	int i;
+
+	/* create a map of all processors in the system */
+	eal_create_cpu_map();
+
+	if (rte_eal_cpu_init() < 0) {
+		rte_eal_init_alert("Cannot detect lcores.");
+		rte_errno =3D ENOTSUP;
+		return -1;
+	}
+
+	eal_thread_init_master(rte_config.master_lcore);
+
+	RTE_LCORE_FOREACH_SLAVE(i) {
+
+		/*
+		 * create communication pipes between master thread
+		 * and children
+		 */
+		if (_pipe(lcore_config[i].pipe_master2slave,
+			sizeof(char), _O_BINARY) < 0)
+			rte_panic("Cannot create pipe\n");
+		if (_pipe(lcore_config[i].pipe_slave2master,
+			sizeof(char), _O_BINARY) < 0)
+			rte_panic("Cannot create pipe\n");
+
+		lcore_config[i].state =3D WAIT;
+
+		/* create a thread for each lcore */
+		if (eal_thread_create(&lcore_config[i].thread_id) !=3D 0)
+			rte_panic("Cannot create thread\n");
+	}
+
+	/*
+	 * Launch a dummy function on all slave lcores, so that master lcore
+	 * knows they are all ready when this function returns.
+	 */
+	rte_eal_mp_remote_launch(sync_func, NULL, SKIP_MASTER);
+	rte_eal_mp_wait_lcore();
 	return 0;
 }
diff --git a/lib/librte_eal/windows/eal/eal_debug.c b/lib/librte_eal/window=
s/eal/eal_debug.c
index 6e07fe10c..edcf257cc 100644
--- a/lib/librte_eal/windows/eal/eal_debug.c
+++ b/lib/librte_eal/windows/eal/eal_debug.c
@@ -2,14 +2,18 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include "rte_common.h"
+#include <stdarg.h>
+#include <rte_log.h>
=20
  /* call abort(), it will generate a coredump if enabled */  void -__rte_p=
anic(const char *funcname __rte_unused,
-		const char *format __rte_unused, ...)
+__rte_panic(const char *funcname, const char *format, ...)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
+	va_list ap;
+
+	rte_log(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, "PANIC in %s():\n", funcname);
+	va_start(ap, format);
+	rte_vlog(RTE_LOG_CRIT, RTE_LOGTYPE_EAL, format, ap);
+	va_end(ap);
 	abort();
 }
diff --git a/lib/librte_eal/windows/eal/eal_lcore.c b/lib/librte_eal/window=
s/eal/eal_lcore.c
index 4ddf51aa8..d39f348a3 100644
--- a/lib/librte_eal/windows/eal/eal_lcore.c
+++ b/lib/librte_eal/windows/eal/eal_lcore.c
@@ -2,31 +2,99 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include "rte_common.h"
+#include <stdint.h>
=20
- /* Get the cpu core id value */
-unsigned int
-eal_cpu_core_id(unsigned int lcore_id)
+#include <rte_common.h>
+
+/* global data structure that contains the CPU map */ static struct=20
+_wcpu_map {
+	unsigned int total_procs;
+	unsigned int proc_sockets;
+	unsigned int proc_cores;
+	unsigned int reserved;
+	struct _win_lcore_map {
+		uint8_t socket_id;
+		uint8_t core_id;
+	} wlcore_map[RTE_MAX_LCORE];
+} wcpu_map =3D { 0 };
+
+/*
+ * Create a map of all processors and associated cores on the system =20
+*/ void
+eal_create_cpu_map()
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
-	return lcore_id;
+	wcpu_map.total_procs =3D
+		GetActiveProcessorCount(ALL_PROCESSOR_GROUPS);
+
+	LOGICAL_PROCESSOR_RELATIONSHIP lprocRel;
+	DWORD lprocInfoSize =3D 0;
+	BOOL ht_enabled =3D FALSE;
+
+	/* First get the processor package information */
+	lprocRel =3D RelationProcessorPackage;
+	/* Determine the size of buffer we need (pass NULL) */
+	GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize);
+	wcpu_map.proc_sockets =3D lprocInfoSize / 48;
+
+	lprocInfoSize =3D 0;
+	/* Next get the processor core information */
+	lprocRel =3D RelationProcessorCore;
+	GetLogicalProcessorInformationEx(lprocRel, NULL, &lprocInfoSize);
+	wcpu_map.proc_cores =3D lprocInfoSize / 48;
+
+	if (wcpu_map.total_procs > wcpu_map.proc_cores)
+		ht_enabled =3D TRUE;
+
+	/* Distribute the socket and core ids appropriately
+	 * across the logical cores. For now, split the cores
+	 * equally across the sockets.
+	 */
+	unsigned int lcore =3D 0;
+	for (unsigned int socket =3D 0; socket <
+			wcpu_map.proc_sockets; ++socket) {
+		for (unsigned int core =3D 0;
+			core < (wcpu_map.proc_cores / wcpu_map.proc_sockets);
+			++core) {
+			wcpu_map.wlcore_map[lcore]
+					.socket_id =3D socket;
+			wcpu_map.wlcore_map[lcore]
+					.core_id =3D core;
+			lcore++;
+			if (ht_enabled) {
+				wcpu_map.wlcore_map[lcore]
+					.socket_id =3D socket;
+				wcpu_map.wlcore_map[lcore]
+					.core_id =3D core;
+				lcore++;
+			}
+		}
+	}
 }
=20
-/* Check if a cpu is present by the presence of the cpu information for it=
 */
+/*
+ * Check if a cpu is present by the presence of the cpu information for=20
+it  */
 int
-eal_cpu_detected(unsigned int lcore_id __rte_unused)
+eal_cpu_detected(unsigned int lcore_id) {
+	return (lcore_id < wcpu_map.total_procs); }
+
+/*
+ * Get CPU socket id for a logical core  */ unsigned=20
+eal_cpu_socket_id(unsigned int lcore_id)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
-	return 1;
+	return wcpu_map.wlcore_map[lcore_id].socket_id;
 }
=20
-/* Get CPU socket id (NUMA node) for a logical core */ -unsigned int -eal_=
cpu_socket_id(unsigned int cpu_id __rte_unused)
+/*
+ * Get CPU socket id (NUMA node) for a logical core  */ unsigned=20
+eal_cpu_core_id(unsigned int lcore_id)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
-	return 0;
+	return wcpu_map.wlcore_map[lcore_id].core_id;
 }
diff --git a/lib/librte_eal/windows/eal/eal_thread.c b/lib/librte_eal/windo=
ws/eal/eal_thread.c
index e74f8893b..906502f90 100644
--- a/lib/librte_eal/windows/eal/eal_thread.c
+++ b/lib/librte_eal/windows/eal/eal_thread.c
@@ -2,17 +2,152 @@
  * Copyright(c) 2019 Intel Corporation
  */
=20
-#include <windows.h>
+#include <io.h>
=20
-#include "rte_common.h"
+#include <rte_atomic.h>
+#include <rte_debug.h>
+#include <rte_launch.h>
+#include <rte_lcore.h>
+#include <rte_per_lcore.h>
+#include <rte_common.h>
+#include <eal_thread.h>
=20
-typedef uintptr_t eal_thread_t;
+
+RTE_DEFINE_PER_LCORE(unsigned int, _lcore_id) =3D LCORE_ID_ANY;
+
+/*
+ * Send a message to a slave lcore identified by slave_id to call a
+ * function f with argument arg. Once the execution is done, the
+ * remote lcore switch in FINISHED state.
+ */
+int
+rte_eal_remote_launch(lcore_function_t *f, void *arg, unsigned int=20
+slave_id) {
+	int n;
+	char c =3D 0;
+	int m2s =3D lcore_config[slave_id].pipe_master2slave[1];
+	int s2m =3D lcore_config[slave_id].pipe_slave2master[0];
+
+	if (lcore_config[slave_id].state !=3D WAIT)
+		return -EBUSY;
+
+	lcore_config[slave_id].f =3D f;
+	lcore_config[slave_id].arg =3D arg;
+
+	/* send message */
+	n =3D 0;
+	while (n =3D=3D 0 || (n < 0 && errno =3D=3D EINTR))
+		n =3D _write(m2s, &c, 1);
+	if (n < 0)
+		rte_panic("cannot write on configuration pipe\n");
+
+	/* wait ack */
+	do {
+		n =3D _read(s2m, &c, 1);
+	} while (n < 0 && errno =3D=3D EINTR);
+
+	if (n <=3D 0)
+		rte_panic("cannot read on configuration pipe\n");
+
+	return 0;
+}
+
+void
+eal_thread_init_master(unsigned int lcore_id) {
+	/* set the lcore ID in per-lcore memory area */
+	RTE_PER_LCORE(_lcore_id) =3D lcore_id;
+}
+
+static inline pthread_t
+eal_thread_self(void)
+{
+	return GetCurrentThreadId();
+}
+
+/* main loop of threads */
+void *
+eal_thread_loop(void *arg __rte_unused) {
+	char c;
+	int n, ret;
+	unsigned int lcore_id;
+	pthread_t thread_id;
+	int m2s, s2m;
+	char cpuset[RTE_CPU_AFFINITY_STR_LEN];
+
+	thread_id =3D eal_thread_self();
+
+	/* retrieve our lcore_id from the configuration structure */
+	RTE_LCORE_FOREACH_SLAVE(lcore_id) {
+		if (thread_id =3D=3D lcore_config[lcore_id].thread_id)
+			break;
+	}
+	if (lcore_id =3D=3D RTE_MAX_LCORE)
+		rte_panic("cannot retrieve lcore id\n");
+
+	m2s =3D lcore_config[lcore_id].pipe_master2slave[0];
+	s2m =3D lcore_config[lcore_id].pipe_slave2master[1];
+
+	/* set the lcore ID in per-lcore memory area */
+	RTE_PER_LCORE(_lcore_id) =3D lcore_id;
+
+	RTE_LOG(DEBUG, EAL, "lcore %u is ready (tid=3D%zx;cpuset=3D[%s])\n",
+		lcore_id, (uintptr_t)thread_id, cpuset);
+
+	/* read on our pipe to get commands */
+	while (1) {
+		void *fct_arg;
+
+		/* wait command */
+		do {
+			n =3D _read(m2s, &c, 1);
+		} while (n < 0 && errno =3D=3D EINTR);
+
+		if (n <=3D 0)
+			rte_panic("cannot read on configuration pipe\n");
+
+		lcore_config[lcore_id].state =3D RUNNING;
+
+		/* send ack */
+		n =3D 0;
+		while (n =3D=3D 0 || (n < 0 && errno =3D=3D EINTR))
+			n =3D _write(s2m, &c, 1);
+		if (n < 0)
+			rte_panic("cannot write on configuration pipe\n");
+
+		if (lcore_config[lcore_id].f =3D=3D NULL)
+			rte_panic("NULL function pointer\n");
+
+		/* call the function and store the return value */
+		fct_arg =3D lcore_config[lcore_id].arg;
+		ret =3D lcore_config[lcore_id].f(fct_arg);
+		lcore_config[lcore_id].ret =3D ret;
+		rte_wmb();
+
+		/* when a service core returns, it should go directly to WAIT
+		 * state, because the application will not lcore_wait() for it.
+		 */
+		if (lcore_config[lcore_id].core_role =3D=3D ROLE_SERVICE)
+			lcore_config[lcore_id].state =3D WAIT;
+		else
+			lcore_config[lcore_id].state =3D FINISHED;
+	}
+}
=20
 /* function to create threads */
 int
-eal_thread_create(eal_thread_t *thread __rte_unused)
+eal_thread_create(pthread_t *thread)
 {
-	/* TODO */
-	/* This is a stub, not the expected result */
+	HANDLE th;
+
+	th =3D CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)eal_thread_loop,
+						NULL, 0, (LPDWORD)thread);
+	if (!th)
+		return -1;
+
+	SetPriorityClass(GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
+	SetThreadPriority(th, THREAD_PRIORITY_TIME_CRITICAL);
+
 	return 0;
 }
diff --git a/lib/librte_eal/windows/eal/include/regex.h b/lib/librte_eal/wi=
ndows/eal/include/regex.h
index daa102f74..412b4edc5 100644
--- a/lib/librte_eal/windows/eal/include/regex.h
+++ b/lib/librte_eal/windows/eal/include/regex.h
@@ -12,6 +12,8 @@ extern "C" {
 #define REG_NOMATCH 1
 #define REG_ESPACE 12
=20
+#include <rte_common.h>
+
 /* defining regex_t for windows */
 typedef void *regex_t;
 /* defining regmatch_t for windows */
diff --git a/lib/librte_eal/windows/eal/include/rte_windows.h b/lib/librte_=
eal/windows/eal/include/rte_windows.h
index af24ef39f..46146e59b 100644
--- a/lib/librte_eal/windows/eal/include/rte_windows.h
+++ b/lib/librte_eal/windows/eal/include/rte_windows.h
@@ -9,7 +9,9 @@
 extern "C" {
 #endif
=20
+#include <Windows.h>
 #include <BaseTsd.h>
+#include <pthread.h>
=20
 /* macro substitution for windows supported strerror_r */  #define strerro=
r_r(a, b, c) strerror_s(b, c, a) @@ -23,6 +25,24 @@ typedef SSIZE_T ssize_t=
;
 /* macro substitution for windows supported strtok_r */  #define strtok_r(=
str, delim, saveptr) strtok_s(str, delim, saveptr)
=20
+/**
+ * Create a thread.
+ * This function is private to EAL.
+ *
+ * @param thread
+ *   The location to store the thread id if successful.
+ * @return
+ *   0 for success, -1 if the thread is not created.
+ */
+int eal_thread_create(pthread_t *thread);
+
+/**
+ * Create a map of processors and cores on the system.
+ * This function is private to EAL.
+ *
+ */
+void eal_create_cpu_map(void);
+
 #ifdef __cplusplus
 }
 #endif
--
2.17.1.windows.2