From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from EUR03-AM5-obe.outbound.protection.outlook.com (mail-eopbgr30041.outbound.protection.outlook.com [40.107.3.41]) by dpdk.org (Postfix) with ESMTP id 8E2921B202 for ; Thu, 11 Oct 2018 12:08:25 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nxp.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Te2ZunyHP7ikAabYnHlkQTfeit/RAon6QU8cK2NcShQ=; b=tsnJuLyTSu+2ZCJ0QITUwQGMrgaUhk6Q46vk5jq4yvXMXA5dIxN6s52D+Fj4Cg46nbIMQxvot1kdQaaLQth8S82+kaDk9/hH6KtH1ybU+Bgm+P/x13trjJr8yYtdTTFgSLlHlWKwjw5xKWUzI32ZYkKqNQtzmJAB6Pzf4guKsLk= Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=shreyansh.jain@nxp.com; Received: from [10.232.14.39] (14.142.187.166) by AM6PR04MB4679.eurprd04.prod.outlook.com (2603:10a6:20b:1c::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.1228.23; Thu, 11 Oct 2018 10:08:23 +0000 From: Shreyansh Jain To: "Burakov, Anatoly" Cc: ferruh.yigit@intel.com, dev@dpdk.org References: <20180925125423.7505-1-shreyansh.jain@nxp.com> <20180925125423.7505-4-shreyansh.jain@nxp.com> <894130a9-017c-348d-31f8-c4c23f517f25@nxp.com> <2d2e9008-fb5b-3ecd-2d2c-e86250f5d363@nxp.com> <5e153c76-6eaa-e6a5-28ed-7cec191d4581@intel.com> <2c377b57-c418-5c03-a23d-5da91ef898d0@nxp.com> Message-ID: <16940ff0-278c-2376-1a86-6beaf0770a09@nxp.com> Date: Thu, 11 Oct 2018 15:37:57 +0530 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.9.1 MIME-Version: 1.0 In-Reply-To: <2c377b57-c418-5c03-a23d-5da91ef898d0@nxp.com> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-Originating-IP: [14.142.187.166] X-ClientProxiedBy: BM1PR0101CA0028.INDPRD01.PROD.OUTLOOK.COM (2603:1096:b00:1a::14) To AM6PR04MB4679.eurprd04.prod.outlook.com (2603:10a6:20b:1c::18) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 5a8ad20f-3dfe-4f58-ab37-08d62f617b53 X-MS-Office365-Filtering-HT: Tenant X-Microsoft-Antispam: BCL:0; PCL:0; RULEID:(7020095)(4652040)(8989299)(4534185)(7168020)(4627221)(201703031133081)(201702281549075)(8990200)(5600074)(711020)(4618075)(2017052603328)(7153060)(7193020); SRVR:AM6PR04MB4679; X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 3:qYQUSzPQGNbt2Buolde9WeNHWdcv1uQk3mFVljYpI4QPhbwlafHTNtzASqF275ALpwaXRsnRlI2gCllIiqVARxy2oEBtQWhjczETOJpEvKrWOxeKtYEZ5HU3yf5ulXHEb+cAD2XC/MrMd5V18WOuTMlxhCvsG8I1rHuzl2tdYSNnBvLtV+rHcynkfqvHpdjXHVuHGBONePsmi72C82pOduZPNiX3O1nhi6PzgrvDJcWrqm3PISB6OgzQusD5ltrS; 25:AB0WI1wZV2bA0MBex3Mgxu+R3wM1xL2Fed2uiJVULX+8KfCf85mTYL9FpUt4Dowr4kDtR4cGJselhkLDETl1RaqIV6NxS6gx7IR7Yk/rB+JiCYQuzevhYft3VuZsjd1kO3Rufv4cODDk2Qgh4NUqzbUBEAp4od0QxwI+IsR/Lc0AxvsWAE+w4oV2L3VN16/40zm3C21dpzvovOrNcn6C6V2s9uhwAsgyt/T4jCOyl+vjk1prU84Wje+pDuU/TjHCxifbwKKWZA6Jny9rJP1BzCCyE2KSVOODCFxFxKDvEYGdrM9UAO7NcIWlK4/XIxQnrQ2G/uIjPoWvTqnXuX+fvV5OxYXFvMqB/0Z7ZEsIubY=; 31:kBRyKAUvIrPhGP5EctmX4OQb7ye/VefZ2PvTiiBrIP3s7+dQ0nAwkLFg+i9HcdSt6S4q9/RiGk1OspN4+Of1dktKJ51REHiwsBo2BGl5jp8qjBN+ZVlQ5gEB+In/AoHoqyrE7Nxxh/rNInxsGCT/N8ZqMIDxnqBAQiJf651pETDlx457y5nFAYiYyVLmceCj7YX8zSOYynA/mlyaDwP4KSzfioPkdn4W1Ncv6S32YU4= X-MS-TrafficTypeDiagnostic: AM6PR04MB4679: X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 20:OB9cxC9JzzvgzSlcD/ucgPwXinEIwroSWSg1cUtcfc+2qAubtxYB/b2oP7uVl2VKuMj30Ew676MUzWdSPD9pdSZOFIwGTjw1ULm2pCBR+Opq09Ibw/W8RQUJeksleeK+eZqfix/c9k1Do5/V6YrDM65xRriVhjfxfUzdEqk34WHcUC6EDLSZoNjByCHvy85qU5Mu1KAI/we1cRqEwMAwV+tYmy2YtoXXX5rwtFq7swDjk/L/5amHg0D8YphTEYh34rHtxvQJKB7nj1EuOWiM5AxHKnca6jJguoWO8LqVcqKYPH9j+OoADuukAj23dIz3bhgSx6MbLySzaJrYmOnSbvwadB7wD3rOX53VkD0567+Vy7AL1dxd3IKwaTER65bYBaoYYtiDzvE2s3xD0AKYwBfg5RIyd1130u9v8aVn6MiX9eQz8QHBU8XjqxwnYtqBIzNMjQmSRRd9IGxk+81XPCTfA4XK1SPqfT8//nyEoh/Rizlri9Te2I4/tOk1lFEH; 4:tBmMPhF2+ETmn/wN9zXNypJc9ct1zIoQaepLuaTcGKjVFwL2tOgVpOEf6rEbh5zeZi1AQ9PNgZcajrnBJs9IHk41EZGwuXUcJwZTjCuyQEt4Rkowgl2j423YaRl7KA/NpsJ3QadkoZXyUOUQyMsB9JnRpycJgENCl7iLqwQjlxXM8o/v5NdgpH3WbcsPV/nsrPRUJpdoDsp1/JNrmxCMTx1DpdKSpiebih5plhPirZyis3rjcm7srVVghJ9e7Pj334qHctdDlAeqOfBdILKPUAHbL7HRRKoPFziA+acI8kX5pydtUK6M5WS4Bi29ktum X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(163750095850); X-MS-Exchange-SenderADCheck: 1 X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(8211001083)(6040522)(2401047)(5005006)(8121501046)(93006095)(93001095)(10201501046)(3002001)(3231355)(944501410)(52105095)(6055026)(149066)(150057)(6041310)(20161123560045)(20161123558120)(20161123562045)(20161123564045)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(201708071742011)(7699051)(76991055); SRVR:AM6PR04MB4679; BCL:0; PCL:0; RULEID:; SRVR:AM6PR04MB4679; X-Forefront-PRVS: 08220FA8D6 X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6049001)(136003)(396003)(376002)(366004)(346002)(39860400002)(199004)(189003)(14444005)(106356001)(105586002)(229853002)(8676002)(3846002)(6116002)(2870700001)(44832011)(386003)(446003)(68736007)(52146003)(67846002)(5660300001)(52116002)(6916009)(53936002)(2486003)(64126003)(6666004)(76176011)(36756003)(31696002)(86362001)(65826007)(97736004)(81166006)(81156014)(58126008)(23676004)(77096007)(16576012)(16526019)(26005)(2906002)(316002)(6486002)(31686004)(186003)(7736002)(4326008)(11346002)(25786009)(2616005)(486006)(53546011)(956004)(50466002)(55236004)(476003)(305945005)(6246003)(93886005)(478600001)(8936002)(66066001)(65806001)(65956001)(1006002)(47776003)(110426005); DIR:OUT; SFP:1101; SCL:1; SRVR:AM6PR04MB4679; H:[10.232.14.39]; FPR:; SPF:None; LANG:en; PTR:InfoNoRecords; A:1; MX:1; Received-SPF: None (protection.outlook.com: nxp.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtBTTZQUjA0TUI0Njc5OzIzOnJBZFdSNlVvZ1R2a1o4YytINFo4dWlLcGhy?= =?utf-8?B?Y1NlUEdTL1k2bUNRaWhyNGc3dWZHQ3RtQTNhNjFsK0VtTmVVdHUxUmduSVBX?= =?utf-8?B?L3o1d2lOZlpFbENOK3FldE1TOGFDN1grNmo1cFRVTjArYmJ6MFpubitsMnlj?= =?utf-8?B?L01wZnQ4VTVpTzY5Y1hmU0V1cTRRNjF3ejUxYTI2RzRzU1gyMWtzQ2RKRTN2?= =?utf-8?B?NVg0QUZjZER0UnpMbGQ0MTlpNlozbi90VFpLdkUrUFhBY3FWdk1OU3NxWGNZ?= =?utf-8?B?cFhFUk0vZW01OXRJSVZTSHRWOGFTMnpXejhSa0JTMDhrMFhNaXQvSjY4ZEpR?= =?utf-8?B?dG4zS2hGQnRDbDBlRmVONHpCTlVpZWI1c3ptdFFmYjh5cnNvWVoraDRUbm03?= =?utf-8?B?TjltMjdad0NRbGtWNkJKRXZWNWVzS2FsaHdnMG1sWUFac2pkOEw1cUpJZjFz?= =?utf-8?B?ZkFFbGo2UGhTVmI2ZzBDc0RmYzUrc3BranpaQmZlejArWmVSQml4M0wxeUpi?= =?utf-8?B?ZnFyM3A5MGdVTmZTODhOWExhZ1RaS1kxT09TOHFEMTZmSHM4SWJ3dGRKN0xm?= =?utf-8?B?K0lJbWVZUlNhMVJ4MWFQemVwOUVwdFkzTWpCNEx6ZXRzNUN4cnJsV3lCdEZt?= =?utf-8?B?Si8zZ0tIL0xycS9tTGdVRDFORHhrVWJaTllQSTdqQVZrYXYySEN6R3JpSisz?= =?utf-8?B?WWQ0K3JnUHRISWpHMzd5c28welAzWWJzQ3JsbWxtUFlJaXNxUElmVnNwWkFn?= =?utf-8?B?T1ZQSFVScWFBdEhXWVVmWVc5U3hkYkR4ZFhva2FqOVEwdGhWRGZ4Q2hQdk1r?= =?utf-8?B?dlVORWovMFNFdTJrdnc4MHpqRWpGR3U4d1M4YXVjbTl4a0t0aGhLSnZxMXdZ?= =?utf-8?B?azFwNitJWU9FLy92NHhUeVlmejFja3VqOTZVWnlvWHpZM1kvaitZRFg2Z0hy?= =?utf-8?B?WDFRa1JlYWZ1SXZ6Mm9ENEpPWWlvWmRYY213N2dXckk4SzI4Snh4K1pVdVZv?= =?utf-8?B?L2hiVm1KTGN2UGlzZlRaMjBEV2M0ZHBsZTZRSk1NbFV1eVhIVmV2bjZ5VEVx?= =?utf-8?B?My9XNmx4NUIrOEdZamQ0am0vdTFFNVBBOXRYQjBSTXdYWTlrS2tCZi9LNmVo?= =?utf-8?B?VFZiQk80Ny9mY3M1MmE2RHJTUk45amd5UWpueWNZK2tQVE1xSHgwMTZRZWRB?= =?utf-8?B?VzNzSXFFOURpVkx1OGYwSTYvVExMQXlHa2JEU0wxeUlZTHdDQUxyd0IydExZ?= =?utf-8?B?aHJQRVJWNmcwYVExaEsxYUVYWWgwUm84OHpLaDVDeU1vN3hPdERjNXRQaXRS?= =?utf-8?B?ZElrbHhYcEtpVCtManBvOEh5NlBoaGpXQXRUOUZmYnJ4SFlFTUI1UkhUYVBU?= =?utf-8?B?aXkvWVdhcFg4YjBSUUNUWHRaZmh1OENaVVJiTktSWi82cXFNY081N3pSdlNx?= =?utf-8?B?c1FqWnkrVXRudytva05yalFvTXY4NmpTa0V0OWYwM0dWNUluZTVGbGF4Q1Iz?= =?utf-8?B?UEtWMkg5NmFpZWtmNWUwT0Ntb1YyOGJNVEhicEZxSUJVZDRQSmozZGhleHU1?= =?utf-8?B?MWtScG5KYy92WXZvcXZ3Znd4Q0EvTTM3blJENSs5eGZVWDNaQ2tRWUczeUZ2?= =?utf-8?B?OE5USXRaS3RUYmc3TnM2QXBVZHVGZEVJMFo3ZmFTODJMQk5UNkpySkhPa01v?= =?utf-8?B?dEp4b2hmRkFOb2xyWkt3WEU1eGRicm5LeXFBS08zcFJ3UTZlYTNFYzF6WnVQ?= =?utf-8?B?dVZvUW9xVlVzOFJlbXFGbnRTWFcwbE1mZU82WmtwUFpCd1plTG11QmFNVzgz?= =?utf-8?B?eFF4STFXNDJrOFVUYXg5Znh0bGM5d3JXdU12QjIzb1Jlb2xuRU5GdVpnK1BX?= =?utf-8?B?WnV5cU11VEk5bkFpV0pmLzV4dTAwYzRZVGsrb29OYkxFdmpLNTJ4WnoyeHNh?= =?utf-8?B?M0ZrcDRBeG9DZjgrcFVNWnh0WHdSS295Y25tNUdwZTN4WjlLaVRtb2dzUUZK?= =?utf-8?B?K3A1cjFHK05lMzhMOUwrZmVicHIzRkNCYng0V3JRZGNsYmQzNFlUak9hazJi?= =?utf-8?B?Z0Mvb0MzMlF6OGVPbEpzbmIrN2w4N0NhL1hDaVU1eTVUMS9acU5xQTJsbHVX?= =?utf-8?B?cVE9PQ==?= X-Microsoft-Antispam-Message-Info: kNeIWSWX2ergVBBwgY9Rf9Xb8Z6LdpPX+staZMEAM2yFv1m+7gqp3gfCJ6wqn3/zMZCW5QsUJ79EeRoDpzfiZscEFeRfE34IrkREgNi5m70B71HoqPbfVOOhXuPOoQ0Y7hAqx3tTVqkno9d/CSM6VWM1VgOtPFGxG2nyBcYM8a/QBuI/KeQWXroYblGvh56gER1Io8+w2rmsNhRmTl+/wv8WHz5IjQiAVF1rMGxWIzvCTBpeq3vI3C0OdZQwh+x7B5N3ri8/nataY57j5eSNu+TXi0vSQBShrCThGMP8qKNzKHuu8sd2W1DzT7jTjrs2bdKDt6EAdxISb1WFTABweuGH1GhFGLVa3B3MGT2t7LE= X-Microsoft-Exchange-Diagnostics: 1; AM6PR04MB4679; 6:g2nbXL7l/YRK3lx7n+eYe9GzBHILgQZgk9roKZFUt3XLa+Ea/5ByjvtJSO24qWVD4y9SpWF9EXA9J879vcFQnG7Lx+bKWm9B3oO6MzL+Ar1NbCBlchGy7EvVoCYJjm6krycPvvIMePtEtWfexCoBCeJpC3AZSLgFR6SVLFheWbB+iG9NCXakTBlhju6blL2YR+Nu8vnyzCgos2nyvQgX5lSpEToBXUJRTs9VCeWzMAAptcFZ/nYutrMngmDmvM89larF/bdcV07JBVJxg9R7dE+/rxPVSn1HBpGU7HShzxlquLCqBB+30E1Nhy3hskyhdNYv+aDTjzJIZSmkq/zAYonZgSPd2JlgFVzE355R2xgM2K2qAvpljG/V17nQsL9xBKfZqCA58Sf8rEQNQwiQCwb8vBqSKvkBS/WVdCu04dtZW4xEYu9U2nyhM/g9gQeNuNyBLwDF00ni8vb34UzzCw==; 5:6sn/2sQQzbMasg39fm5PYrJel+n+MwjOc93lHzWGXQjZbbH9ttRYgqo4RkFG6x2qFlgKIdF0hS9M0MJTFMUvbZR79CS1GW7nLRTRo8iXkMIDci1OckkvfP2upGzTutb8aPVS3xTB03nFx5bw4QGpouFOPBbWSHTE8aQFjTX97+A=; 7:Ke7j6ZK/2RGBjVyfCxznYGbtlNFRSIQpCTcfupSfe6DBnzl7OV2mSVaj5Xumjo/G6t1Yc3OKwdXsWlh3iCegPx4Xor6mcQeogK+uEfjyGS1QX3HHqUG8Kgbof7HyMUVAkL9iq9EFnBtUNzn5CqgekKbVu9As0MdPRZCE+bBfWTiOO/2agwmu7Ex1dtTSyMwkvb1oqVr1yBKQ9lyOfHcysiLjHp+G5CLwyGIg8xlSokRal1PtodzoNfl22sHjFN8B SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: nxp.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 11 Oct 2018 10:08:23.2386 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 5a8ad20f-3dfe-4f58-ab37-08d62f617b53 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 686ea1d3-bc2b-4c6f-a92c-d99c5c301635 X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM6PR04MB4679 Subject: Re: [dpdk-dev] [PATCH 3/5] common/dpaax: add library for PA VA translation table 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: Thu, 11 Oct 2018 10:08:25 -0000 On Thursday 11 October 2018 03:32 PM, Shreyansh Jain wrote: > On Thursday 11 October 2018 02:33 PM, Burakov, Anatoly wrote: >> On 09-Oct-18 11:45 AM, Shreyansh Jain wrote: >>> On Tuesday 25 September 2018 07:09 PM, Shreyansh Jain wrote: >>>> Hello Anatoly, >>>> >>>> On Tuesday 25 September 2018 06:58 PM, Burakov, Anatoly wrote: >>>>> On 25-Sep-18 1:54 PM, Shreyansh Jain wrote: >>>>>> A common library, valid for dpaaX drivers, which is used to maintain >>>>>> a local copy of PA->VA translations. >>>>>> >>>>>> In case of physical addressing mode (one of the option for FSLMC, and >>>>>> only option for DPAA bus), the addresses of descriptors Rx'd are >>>>>> physical. These need to be converted into equivalent VA for rte_mbuf >>>>>> and other similar calls. >>>>>> >>>>>> Using the rte_mem_virt2iova or rte_mem_virt2phy is expensive. This >>>>>> library is an attempt to reduce the overall cost associated with >>>>>> this translation. >>>>>> >>>>>> A small table is maintained, containing continuous entries >>>>>> representing a continguous physical range. Each of these entries >>>>>> stores the equivalent VA, which is fed during mempool creation, or >>>>>> memory allocation/deallocation callbacks. >>>>>> >>> >>> [...] >>> >>>> >>>>> >>>>> Also, a couple of nitpicks below. >>>>> >>>>>>   cosnfig/common_base                            |   5 + >>>>>>   config/common_linuxapp                        |   5 + >>>>>>   drivers/common/Makefile                       |   4 + >>>>>>   drivers/common/dpaax/Makefile                 |  31 ++ >>>>>>   drivers/common/dpaax/dpaax_iova_table.c       | 509 >>>>>> ++++++++++++++++++ >>>>>>   drivers/common/dpaax/dpaax_iova_table.h       | 104 ++++ >>>>>>   drivers/common/dpaax/dpaax_logs.h             |  39 ++ >>>>>>   drivers/common/dpaax/meson.build              |  12 + >>>>> >>>>> >>>>> >>>>>> +    DPAAX_DEBUG("Add: Found slot at (%"PRIu64")[(%zu)] for >>>>>> vaddr:(%p)," >>>>>> +            " phy(%"PRIu64"), len(%zu)", entry[i].start, e_offset, >>>>>> +            vaddr, paddr, length); >>>>>> +    return 0; >>>>>> +} >>>>>> + >>>>>> +int >>>>>> +dpaax_iova_table_del(phys_addr_t paddr, size_t len __rte_unused) >>>>> >>>>> len is not unused. >>>> >>>> I will fix this. >>>> Actually, this function itself is useless - more for symmetry reason. >>>> Callers would be either simply updating the table, or ignoring it >>>> completely. But, yes, this is indeed wrong that I set that unused. >>>> >>> >>> Actually, I was wrong in my first reply. In case of >>> dpaax_iova_table_del(), len is indeed redundant. This is because the >>> mapping is for a complete page (min of 2MB size), even if the request >>> is for lesser length. So, removal of a single entry (of fixed size) >>> would be done. >>> >>> In fact, while on this, I think deleting a PA->VA entry itself is >>> incorrect (not just useless). A single entry (~2MB equivalent) can >>> represent multiple users (working on a rte_malloc'd area, for >>> example). So, effectively, its always an update - not an add or del. >> >> I'm not sure what you mean here. If you got a mem event about memory >> area being freed, it's guaranteed to *not* have any users - neither >> malloc, nor any other memory. And len is always page-aligned. > > ok. Maybe I am getting this wrong, but consider this: > > 1) hugepage size=2MB > 2) a = malloc(1M) >   this will pin an entry in table for a block starting at VA=(a) and > PA=(a'). Each entry is of 2MB length - that means, even if someone were > to access a+1048577 for an equivalent PA, they would get it (though, > that is a incorrect access). > 3) b = malloc(1M) >   this *might* lead to a case where same 2MB page is used and > VA=(b==(a+1MB)). Being hugepage backed, PA=(b=PA(a)+1M). > = After b, the PA-VA table has a single entry of 2MB, representing two > mallocs. It can be used for translation for any thread requesting PAs of > a or b. > 4) Free(a) >  - this would attempt to remove one 2MB entry from PA-VA table. But, > 'b' is already valid. Access to get_pa(VA(b)) should return me the PA(b). >  - 'len' is not even used as the entry in PA-VA table is of a fixed size. Just to add to this: - if talking about the mem_event callback, it definitely won't be a case where same page is still being served under another rte_malloc - But, calls can come to delete from users of PA-VA table based on their own rte_free(). And, your comment makes me think - I should probably del entry from the table only when mem_event callback is received. > > In the above, (3) is an assumption I am making based on my understanding > how mem allocator is working. Is that wrong? > > Basically, this is a restriction of this table - it has a min chunk of > 2MB - even for 1G hugepages - and hence, it is not possible to honor > deletes. I know this is convoluted logic - but, this keeps it simple and > use-able without much performance impact. > > [...] >