From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: 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 ; 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 To: Anand Rawat , "dev@dpdk.org" CC: "pallavi.kadam@intel.com" , "ranjit.menon@intel.com" , "jeffrey.b.shaw@intel.com" , "bruce.richardson@intel.com" , "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: 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: 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 26 Mar 2019 16:32:22 -0000 -----Original Message----- From: dev 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 Signed-off-by: Pallavi Kadam Reviewed-by: Jeff Shaw Reviewed-by: Ranjit Menon Acked-by: Harini Ramakrishnan --- 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 +#include +#include +#include +#include +#include +#include +#include + +/* 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 +#include =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 =20 - /* Get the cpu core id value */ -unsigned int -eal_cpu_core_id(unsigned int lcore_id) +#include + +/* 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 +#include =20 -#include "rte_common.h" +#include +#include +#include +#include +#include +#include +#include =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 + /* 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 #include +#include =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: Received: from dpdk.org (dpdk.org [92.243.14.124]) by dpdk.space (Postfix) with ESMTP id 8CD7AA05D3 for ; 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 ; 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 To: Anand Rawat , "dev@dpdk.org" CC: "pallavi.kadam@intel.com" , "ranjit.menon@intel.com" , "jeffrey.b.shaw@intel.com" , "bruce.richardson@intel.com" , "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: 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: 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 List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Message-ID: <20190326163220.uHTfY5q36mcQfPVjyL7_cGB0QzVrCu4As5xNZWYKEkk@z> -----Original Message----- From: dev 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 Signed-off-by: Pallavi Kadam Reviewed-by: Jeff Shaw Reviewed-by: Ranjit Menon Acked-by: Harini Ramakrishnan --- 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 +#include +#include +#include +#include +#include +#include +#include + +/* 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 +#include =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 =20 - /* Get the cpu core id value */ -unsigned int -eal_cpu_core_id(unsigned int lcore_id) +#include + +/* 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 +#include =20 -#include "rte_common.h" +#include +#include +#include +#include +#include +#include +#include =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 + /* 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 #include +#include =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