Message ID | A4A7819F3AE089479B8A88B97202C75D37BE86F9@ex10-mbx-9001.ant.amazon.com (mailing list archive) |
---|---|
State | Not Applicable, archived |
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]) by dpdk.org (Postfix) with ESMTP id 573C8B3B1; Thu, 25 Sep 2014 09:40:15 +0200 (CEST) Received: from smtp-fw-33001.amazon.com (smtp-fw-33001.amazon.com [207.171.189.228]) by dpdk.org (Postfix) with ESMTP id 2720CB3AD for <dev@dpdk.org>; Thu, 25 Sep 2014 09:40:12 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amazon.com; i=@amazon.com; q=dns/txt; s=amazon201209; t=1411631190; x=1443167190; h=from:to:subject:date:message-id:mime-version; bh=iVPVVzXsTWkCVe/6OPy4C/aM7tRCcuil170bnpUJlOE=; b=Anq67js8RaULZX2SvHsZcfLYCEEW8lmiPUYM5LbHH6isiIo/ObOvw8XR N1xXCiNdzU/e7/4XL2mm9Vjz4om8ZqZaMTDykiO1wS3oBwbDPKA11YBxR Si6cilS6ltgpfj4w65KT6xKoGEyJ0GpbqJovQrVPOQjg+cTfRPv3FGJ+q A=; X-IronPort-AV: E=Sophos;i="5.04,595,1406592000"; d="scan'208,217";a="106833076" Received: from email-inbound-relay-62001.pdx2.amazon.com ([10.241.21.123]) by smtp-border-fw-out-33001.sea14.amazon.com with ESMTP/TLS/DHE-RSA-AES256-SHA; 25 Sep 2014 07:46:25 +0000 Received: from ex10-hub-9004.ant.amazon.com (pdx2-ws-svc-lb17-vlan2.amazon.com [10.247.140.66]) by email-inbound-relay-62001.pdx2.amazon.com (8.14.7/8.14.7) with ESMTP id s8P7kOPX001036 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=OK) for <dev@dpdk.org>; Thu, 25 Sep 2014 07:46:24 GMT Received: from EX10-MBX-9001.ant.amazon.com ([fe80::1023:3a45:4674:52c6]) by ex10-hub-9004.ant.amazon.com ([::1]) with mapi id 14.03.0181.006; Thu, 25 Sep 2014 00:46:17 -0700 From: "Saha, Avik (AWS)" <aviksaha@amazon.com> To: "dev@dpdk.org" <dev@dpdk.org> Thread-Topic: [dpdk-dev] [PATCH] Fix for LRU corrupted returns Thread-Index: Ac/Yk7ywkHZ3u5mETg2SYiggoS84qQ== Date: Thu, 25 Sep 2014 07:46:16 +0000 Message-ID: <A4A7819F3AE089479B8A88B97202C75D37BE86F9@ex10-mbx-9001.ant.amazon.com> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-originating-ip: [10.184.49.70] MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: quoted-printable X-Content-Filtered-By: Mailman/MimeDel 2.1.15 Subject: [dpdk-dev] [PATCH] Fix for LRU corrupted returns 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>, <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>, <mailto:dev-request@dpdk.org?subject=subscribe> Errors-To: dev-bounces@dpdk.org Sender: "dev" <dev-bounces@dpdk.org> |
Commit Message
Saha, Avik (AWS)
Sept. 25, 2014, 7:46 a.m. UTC
This is a patch to a problem that I have faced (described in the thread) and this works for me.
1) Since the data_size_shl was getting its value from the key_size, the table data entries were being corrupted when the calculation to shift the number of bits was being made based on the key_size (according to the document the key_size and entry_size are independently configurable) - With this fix, we get the MSB that is set in entry_size (also removes the constraint of this having to be a power of 2 - not entirely sure if this was the reason the constraint was kept though)
2) The document does not say that the entry_size needs to be a power of 2 and this was failing silently when I was trying to bring my application up.
-----Original Message-----
From: dev [mailto:dev-bounces@dpdk.org] On Behalf Of Saha, Avik (AWS)
Sent: Wednesday, September 24, 2014 4:12 PM
To: dev@dpdk.org
Subject: [dpdk-dev] Strange behaviour with LRU table
1) All the calls to add entries succeeds
2) The key look up works as expected.
3) The value (entry_data) that is returned is incorrect for every other entry - 1st entry data on .f_action_hit is wrong, 2nd entry_data on .f_action_hit is correct and so on.
I have initialized my LRU as follows:
struct rte_pipeline_table_params table_params = {
.ops = &rte_table_hash_lru_dosig_ops,
.arg_create = &rule_tbl_params,
.f_action_hit = rw_pipeline_stage_2_cache_hit,
.f_action_miss = rw_pipeline_stage_2_cache_miss,
.arg_ah = (void *)lcore_params,
.action_data_size = 16,
};
Is there something obvious I am missing - from first look it seems to be a problem with cache lines but I really am not sure.
Avik
Comments
On Thu, Sep 25, 2014 at 07:46:16AM +0000, Saha, Avik (AWS) wrote: > This is a patch to a problem that I have faced (described in the thread) and this works for me. > > 1) Since the data_size_shl was getting its value from the key_size, the table data entries were being corrupted when the calculation to shift the number of bits was being made based on the key_size (according to the document the key_size and entry_size are independently configurable) - With this fix, we get the MSB that is set in entry_size (also removes the constraint of this having to be a power of 2 - not entirely sure if this was the reason the constraint was kept though) > 2) The document does not say that the entry_size needs to be a power of 2 and this was failing silently when I was trying to bring my application up. > > diff --git a/DPDK/lib/librte_table/rte_table_hash_lru.c b/DPDK/lib/librte_table/rte_table_hash_lru.c > index d1a4984..4ec9aa4 100644 > --- a/DPDK/lib/librte_table/rte_table_hash_lru.c > +++ b/DPDK/lib/librte_table/rte_table_hash_lru.c > @@ -153,8 +153,10 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > uint32_t i; > > /* Check input parameters */ > - if ((check_params_create(p) != 0) || > - (!rte_is_power_of_2(entry_size)) || > + // Commenting out the power of 2 check on the entry_size since the > + // Programmers Guide does not call this out and we are going to handle > + // the data_size_shl of the table later on (Line 197) Please remove the reference to Line 197 here. Thats not going to remain accurate for very long. > + if ((check_params_create(p) != 0) || > ((sizeof(struct rte_table_hash) % CACHE_LINE_SIZE) != 0) || > (sizeof(struct bucket) != (CACHE_LINE_SIZE / 2))) { > return NULL; > @@ -192,7 +194,7 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > /* Internal */ > t->bucket_mask = t->n_buckets - 1; > t->key_size_shl = __builtin_ctzl(p->key_size); > - t->data_size_shl = __builtin_ctzl(p->key_size); > + t->data_size_shl = 32 - (__builtin_clz(entry_size)); I presume the 32 value here is a cache line size? That should be replaced with CACHE_LINE_SIZE...Though looking at it, that doesn't seem sufficient. Seems like we need a eal abstraction to dynamically tell us what the cache line size is (we can read it from /proc/cpuinfo in linux, not sure about bsd). Neil
Sorry about the delay. The number 32 is not really a CACHE_LINE_SIZE but since __builtin_clz returns the number of leading 0's before the most significant set bit in a 32 bit number (entry_size is uint32_t), I subtract that number from 32 to get the number of trailing bits after the most significant set bit. This will be the separation in my data_mem regions. -----Original Message----- From: Neil Horman [mailto:nhorman@tuxdriver.com] Sent: Thursday, September 25, 2014 3:22 AM To: Saha, Avik (AWS) Cc: dev@dpdk.org Subject: Re: [dpdk-dev] [PATCH] Fix for LRU corrupted returns On Thu, Sep 25, 2014 at 07:46:16AM +0000, Saha, Avik (AWS) wrote: > This is a patch to a problem that I have faced (described in the thread) and this works for me. > > 1) Since the data_size_shl was getting its value from the key_size, the table data entries were being corrupted when the calculation to shift the number of bits was being made based on the key_size (according to the document the key_size and entry_size are independently configurable) - With this fix, we get the MSB that is set in entry_size (also removes the constraint of this having to be a power of 2 - not entirely sure if this was the reason the constraint was kept though) > 2) The document does not say that the entry_size needs to be a power of 2 and this was failing silently when I was trying to bring my application up. > > diff --git a/DPDK/lib/librte_table/rte_table_hash_lru.c > b/DPDK/lib/librte_table/rte_table_hash_lru.c > index d1a4984..4ec9aa4 100644 > --- a/DPDK/lib/librte_table/rte_table_hash_lru.c > +++ b/DPDK/lib/librte_table/rte_table_hash_lru.c > @@ -153,8 +153,10 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > uint32_t i; > > /* Check input parameters */ > - if ((check_params_create(p) != 0) || > - (!rte_is_power_of_2(entry_size)) || > + // Commenting out the power of 2 check on the entry_size since the > + // Programmers Guide does not call this out and we are going to handle > + // the data_size_shl of the table later on (Line 197) Please remove the reference to Line 197 here. Thats not going to remain accurate for very long. > + if ((check_params_create(p) != 0) || > ((sizeof(struct rte_table_hash) % CACHE_LINE_SIZE) != 0) || > (sizeof(struct bucket) != (CACHE_LINE_SIZE / 2))) { > return NULL; > @@ -192,7 +194,7 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > /* Internal */ > t->bucket_mask = t->n_buckets - 1; > t->key_size_shl = __builtin_ctzl(p->key_size); > - t->data_size_shl = __builtin_ctzl(p->key_size); > + t->data_size_shl = 32 - (__builtin_clz(entry_size)); I presume the 32 value here is a cache line size? That should be replaced with CACHE_LINE_SIZE...Though looking at it, that doesn't seem sufficient. Seems like we need a eal abstraction to dynamically tell us what the cache line size is (we can read it from /proc/cpuinfo in linux, not sure about bsd). Neil
On Tue, Sep 30, 2014 at 06:26:23AM +0000, Saha, Avik (AWS) wrote: > Sorry about the delay. The number 32 is not really a CACHE_LINE_SIZE but since __builtin_clz returns the number of leading 0's before the most significant set bit in a 32 bit number (entry_size is uint32_t), I subtract that number from 32 to get the number of trailing bits after the most significant set bit. This will be the separation in my data_mem regions. > Ah, ok, then change that 32 to sizeof(t->data_size_shl) to protect you against type changes and to avoid having magic values running around in your code. Also, you might want to do some sanity checking of entry_size as it seems like theres a soft assumption that entry size is non-zero and a power of two. while the latter is checked higher in the function, the former isn't and __builtin_clz has undefined behavior if its passed a zero value. Neil > -----Original Message----- > From: Neil Horman [mailto:nhorman@tuxdriver.com] > Sent: Thursday, September 25, 2014 3:22 AM > To: Saha, Avik (AWS) > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH] Fix for LRU corrupted returns > > On Thu, Sep 25, 2014 at 07:46:16AM +0000, Saha, Avik (AWS) wrote: > > This is a patch to a problem that I have faced (described in the thread) and this works for me. > > > > 1) Since the data_size_shl was getting its value from the key_size, the table data entries were being corrupted when the calculation to shift the number of bits was being made based on the key_size (according to the document the key_size and entry_size are independently configurable) - With this fix, we get the MSB that is set in entry_size (also removes the constraint of this having to be a power of 2 - not entirely sure if this was the reason the constraint was kept though) > > 2) The document does not say that the entry_size needs to be a power of 2 and this was failing silently when I was trying to bring my application up. > > > > diff --git a/DPDK/lib/librte_table/rte_table_hash_lru.c > > b/DPDK/lib/librte_table/rte_table_hash_lru.c > > index d1a4984..4ec9aa4 100644 > > --- a/DPDK/lib/librte_table/rte_table_hash_lru.c > > +++ b/DPDK/lib/librte_table/rte_table_hash_lru.c > > @@ -153,8 +153,10 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > > uint32_t i; > > > > /* Check input parameters */ > > - if ((check_params_create(p) != 0) || > > - (!rte_is_power_of_2(entry_size)) || > > + // Commenting out the power of 2 check on the entry_size since the > > + // Programmers Guide does not call this out and we are going to handle > > + // the data_size_shl of the table later on (Line 197) > Please remove the reference to Line 197 here. Thats not going to remain accurate for very long. > > > + if ((check_params_create(p) != 0) || > > ((sizeof(struct rte_table_hash) % CACHE_LINE_SIZE) != 0) || > > (sizeof(struct bucket) != (CACHE_LINE_SIZE / 2))) { > > return NULL; > > @@ -192,7 +194,7 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > > /* Internal */ > > t->bucket_mask = t->n_buckets - 1; > > t->key_size_shl = __builtin_ctzl(p->key_size); > > - t->data_size_shl = __builtin_ctzl(p->key_size); > > + t->data_size_shl = 32 - (__builtin_clz(entry_size)); > I presume the 32 value here is a cache line size? That should be replaced with CACHE_LINE_SIZE...Though looking at it, that doesn't seem sufficient. Seems like we need a eal abstraction to dynamically tell us what the cache line size is (we can read it from /proc/cpuinfo in linux, not sure about bsd). > > Neil > >
I have to point out that I am commenting out the the power_of_2 check on entry_size. I am not sure if this is the right way but I don't know why this soft assumption is important (since I cannot find the power of 2 constraint in the documentation). I agree with the 0 check but the only reason I did not put that in is because entry size would at least be sizeof(struct rte_pipeline_table_entry) = 8 bytes (to which the action_data_size is added) Avik -----Original Message----- From: Neil Horman [mailto:nhorman@tuxdriver.com] Sent: Tuesday, September 30, 2014 5:51 AM To: Saha, Avik (AWS) Cc: dev@dpdk.org Subject: Re: [dpdk-dev] [PATCH] Fix for LRU corrupted returns On Tue, Sep 30, 2014 at 06:26:23AM +0000, Saha, Avik (AWS) wrote: > Sorry about the delay. The number 32 is not really a CACHE_LINE_SIZE but since __builtin_clz returns the number of leading 0's before the most significant set bit in a 32 bit number (entry_size is uint32_t), I subtract that number from 32 to get the number of trailing bits after the most significant set bit. This will be the separation in my data_mem regions. > Ah, ok, then change that 32 to sizeof(t->data_size_shl) to protect you against type changes and to avoid having magic values running around in your code. Also, you might want to do some sanity checking of entry_size as it seems like theres a soft assumption that entry size is non-zero and a power of two. while the latter is checked higher in the function, the former isn't and __builtin_clz has undefined behavior if its passed a zero value. Neil > -----Original Message----- > From: Neil Horman [mailto:nhorman@tuxdriver.com] > Sent: Thursday, September 25, 2014 3:22 AM > To: Saha, Avik (AWS) > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH] Fix for LRU corrupted returns > > On Thu, Sep 25, 2014 at 07:46:16AM +0000, Saha, Avik (AWS) wrote: > > This is a patch to a problem that I have faced (described in the thread) and this works for me. > > > > 1) Since the data_size_shl was getting its value from the key_size, the table data entries were being corrupted when the calculation to shift the number of bits was being made based on the key_size (according to the document the key_size and entry_size are independently configurable) - With this fix, we get the MSB that is set in entry_size (also removes the constraint of this having to be a power of 2 - not entirely sure if this was the reason the constraint was kept though) > > 2) The document does not say that the entry_size needs to be a power of 2 and this was failing silently when I was trying to bring my application up. > > > > diff --git a/DPDK/lib/librte_table/rte_table_hash_lru.c > > b/DPDK/lib/librte_table/rte_table_hash_lru.c > > index d1a4984..4ec9aa4 100644 > > --- a/DPDK/lib/librte_table/rte_table_hash_lru.c > > +++ b/DPDK/lib/librte_table/rte_table_hash_lru.c > > @@ -153,8 +153,10 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > > uint32_t i; > > > > /* Check input parameters */ > > - if ((check_params_create(p) != 0) || > > - (!rte_is_power_of_2(entry_size)) || > > + // Commenting out the power of 2 check on the entry_size since the > > + // Programmers Guide does not call this out and we are going to handle > > + // the data_size_shl of the table later on (Line 197) > Please remove the reference to Line 197 here. Thats not going to remain accurate for very long. > > > + if ((check_params_create(p) != 0) || > > ((sizeof(struct rte_table_hash) % CACHE_LINE_SIZE) != 0) || > > (sizeof(struct bucket) != (CACHE_LINE_SIZE / 2))) { > > return NULL; > > @@ -192,7 +194,7 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > > /* Internal */ > > t->bucket_mask = t->n_buckets - 1; > > t->key_size_shl = __builtin_ctzl(p->key_size); > > - t->data_size_shl = __builtin_ctzl(p->key_size); > > + t->data_size_shl = 32 - (__builtin_clz(entry_size)); > I presume the 32 value here is a cache line size? That should be replaced with CACHE_LINE_SIZE...Though looking at it, that doesn't seem sufficient. Seems like we need a eal abstraction to dynamically tell us what the cache line size is (we can read it from /proc/cpuinfo in linux, not sure about bsd). > > Neil > >
On Tue, Sep 30, 2014 at 06:14:46PM +0000, Saha, Avik (AWS) wrote: > I have to point out that I am commenting out the the power_of_2 check on entry_size. I am not sure if this is the right way but I don't know why this soft assumption is important (since I cannot find the power of 2 constraint in the documentation). I agree with the 0 check but the only reason I did not put that in is because entry size would at least be sizeof(struct rte_pipeline_table_entry) = 8 bytes (to which the action_data_size is added) > > Avik > I would imagine the power of two check is in place sepcifically because of the zero bit searchs immediately below it. I.e. you can't really create bit masks for multi-field values, when those fields aren't contiguous. Neil > -----Original Message----- > From: Neil Horman [mailto:nhorman@tuxdriver.com] > Sent: Tuesday, September 30, 2014 5:51 AM > To: Saha, Avik (AWS) > Cc: dev@dpdk.org > Subject: Re: [dpdk-dev] [PATCH] Fix for LRU corrupted returns > > On Tue, Sep 30, 2014 at 06:26:23AM +0000, Saha, Avik (AWS) wrote: > > Sorry about the delay. The number 32 is not really a CACHE_LINE_SIZE but since __builtin_clz returns the number of leading 0's before the most significant set bit in a 32 bit number (entry_size is uint32_t), I subtract that number from 32 to get the number of trailing bits after the most significant set bit. This will be the separation in my data_mem regions. > > > Ah, ok, then change that 32 to sizeof(t->data_size_shl) to protect you against type changes and to avoid having magic values running around in your code. Also, you might want to do some sanity checking of entry_size as it seems like theres a soft assumption that entry size is non-zero and a power of two. > while the latter is checked higher in the function, the former isn't and __builtin_clz has undefined behavior if its passed a zero value. > > Neil > > > -----Original Message----- > > From: Neil Horman [mailto:nhorman@tuxdriver.com] > > Sent: Thursday, September 25, 2014 3:22 AM > > To: Saha, Avik (AWS) > > Cc: dev@dpdk.org > > Subject: Re: [dpdk-dev] [PATCH] Fix for LRU corrupted returns > > > > On Thu, Sep 25, 2014 at 07:46:16AM +0000, Saha, Avik (AWS) wrote: > > > This is a patch to a problem that I have faced (described in the thread) and this works for me. > > > > > > 1) Since the data_size_shl was getting its value from the key_size, the table data entries were being corrupted when the calculation to shift the number of bits was being made based on the key_size (according to the document the key_size and entry_size are independently configurable) - With this fix, we get the MSB that is set in entry_size (also removes the constraint of this having to be a power of 2 - not entirely sure if this was the reason the constraint was kept though) > > > 2) The document does not say that the entry_size needs to be a power of 2 and this was failing silently when I was trying to bring my application up. > > > > > > diff --git a/DPDK/lib/librte_table/rte_table_hash_lru.c > > > b/DPDK/lib/librte_table/rte_table_hash_lru.c > > > index d1a4984..4ec9aa4 100644 > > > --- a/DPDK/lib/librte_table/rte_table_hash_lru.c > > > +++ b/DPDK/lib/librte_table/rte_table_hash_lru.c > > > @@ -153,8 +153,10 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > > > uint32_t i; > > > > > > /* Check input parameters */ > > > - if ((check_params_create(p) != 0) || > > > - (!rte_is_power_of_2(entry_size)) || > > > + // Commenting out the power of 2 check on the entry_size since the > > > + // Programmers Guide does not call this out and we are going to handle > > > + // the data_size_shl of the table later on (Line 197) > > Please remove the reference to Line 197 here. Thats not going to remain accurate for very long. > > > > > + if ((check_params_create(p) != 0) || > > > ((sizeof(struct rte_table_hash) % CACHE_LINE_SIZE) != 0) || > > > (sizeof(struct bucket) != (CACHE_LINE_SIZE / 2))) { > > > return NULL; > > > @@ -192,7 +194,7 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) > > > /* Internal */ > > > t->bucket_mask = t->n_buckets - 1; > > > t->key_size_shl = __builtin_ctzl(p->key_size); > > > - t->data_size_shl = __builtin_ctzl(p->key_size); > > > + t->data_size_shl = 32 - (__builtin_clz(entry_size)); > > I presume the 32 value here is a cache line size? That should be replaced with CACHE_LINE_SIZE...Though looking at it, that doesn't seem sufficient. Seems like we need a eal abstraction to dynamically tell us what the cache line size is (we can read it from /proc/cpuinfo in linux, not sure about bsd). > > > > Neil > > > > >
diff --git a/DPDK/lib/librte_table/rte_table_hash_lru.c b/DPDK/lib/librte_table/rte_table_hash_lru.c index d1a4984..4ec9aa4 100644 --- a/DPDK/lib/librte_table/rte_table_hash_lru.c +++ b/DPDK/lib/librte_table/rte_table_hash_lru.c @@ -153,8 +153,10 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) uint32_t i; /* Check input parameters */ - if ((check_params_create(p) != 0) || - (!rte_is_power_of_2(entry_size)) || + // Commenting out the power of 2 check on the entry_size since the + // Programmers Guide does not call this out and we are going to handle + // the data_size_shl of the table later on (Line 197) + if ((check_params_create(p) != 0) || ((sizeof(struct rte_table_hash) % CACHE_LINE_SIZE) != 0) || (sizeof(struct bucket) != (CACHE_LINE_SIZE / 2))) { return NULL; @@ -192,7 +194,7 @@ rte_table_hash_lru_create(void *params, int socket_id, uint32_t entry_size) /* Internal */ t->bucket_mask = t->n_buckets - 1; t->key_size_shl = __builtin_ctzl(p->key_size); - t->data_size_shl = __builtin_ctzl(p->key_size); + t->data_size_shl = 32 - (__builtin_clz(entry_size)); /* Tables */ table_meta_offset = 0;