diff mbox

[API-NEXT,PATCHv4] linux-generic: pool: defer ring allocation until pool creation

Message ID 20170110155940.7780-1-bill.fischofer@linaro.org
State Accepted
Commit fda9a9e4887eff3f0526c7bcef5e29ff511cd4d8
Headers show

Commit Message

Bill Fischofer Jan. 10, 2017, 3:59 p.m. UTC
To avoid excessive memory overhead for pools, defer the allocation of
the pool ring until odp_pool_create() is called. This keeps pool memory
overhead proportional to the number of pools actually in use rather
than the architected maximum number of pools.

This patch addresses Bug https://bugs.linaro.org/show_bug.cgi?id=2765

Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>

---
Changes for v4:
- Change ring name per Maxim's suggestion
- Add lock/unlock calls around setting pool->reserved back to 0 per Petri

Changes for v3:
- Do not reference pool ring on buffer alloc/free if cache can satisfy request

Changes for v2:
- Reset reserved to 0 if ring allocation fails to recover properly

 platform/linux-generic/include/odp_pool_internal.h |  3 +-
 platform/linux-generic/odp_pool.c                  | 33 +++++++++++++++++-----
 2 files changed, 28 insertions(+), 8 deletions(-)

-- 
2.9.3

Comments

Savolainen, Petri (Nokia - FI/Espoo) Jan. 11, 2017, 1:50 p.m. UTC | #1
Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com>



> -----Original Message-----

> From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of Bill

> Fischofer

> Sent: Tuesday, January 10, 2017 6:00 PM

> To: lng-odp@lists.linaro.org

> Subject: [lng-odp] [API-NEXT PATCHv4] linux-generic: pool: defer ring

> allocation until pool creation

> 

> To avoid excessive memory overhead for pools, defer the allocation of

> the pool ring until odp_pool_create() is called. This keeps pool memory

> overhead proportional to the number of pools actually in use rather

> than the architected maximum number of pools.

> 

> This patch addresses Bug https://bugs.linaro.org/show_bug.cgi?id=2765

> 

> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>

> ---

> Changes for v4:

> - Change ring name per Maxim's suggestion

> - Add lock/unlock calls around setting pool->reserved back to 0 per Petri

> 

> Changes for v3:

> - Do not reference pool ring on buffer alloc/free if cache can satisfy

> request

> 

> Changes for v2:

> - Reset reserved to 0 if ring allocation fails to recover properly

> 

>  platform/linux-generic/include/odp_pool_internal.h |  3 +-

>  platform/linux-generic/odp_pool.c                  | 33

> +++++++++++++++++-----

>  2 files changed, 28 insertions(+), 8 deletions(-)

> 

> diff --git a/platform/linux-generic/include/odp_pool_internal.h

> b/platform/linux-generic/include/odp_pool_internal.h

> index 5d7b817..4915bda 100644

> --- a/platform/linux-generic/include/odp_pool_internal.h

> +++ b/platform/linux-generic/include/odp_pool_internal.h

> @@ -69,7 +69,8 @@ typedef struct pool_t {

> 

>  	pool_cache_t     local_cache[ODP_THREAD_COUNT_MAX];

> 

> -	pool_ring_t      ring;

> +	odp_shm_t        ring_shm;

> +	pool_ring_t     *ring;

> 

>  } pool_t;

> 

> diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-

> generic/odp_pool.c

> index cae2759..932efe3 100644

> --- a/platform/linux-generic/odp_pool.c

> +++ b/platform/linux-generic/odp_pool.c

> @@ -143,7 +143,7 @@ static void flush_cache(pool_cache_t *cache, pool_t

> *pool)

>  	uint32_t mask;

>  	uint32_t cache_num, i, data;

> 

> -	ring = &pool->ring.hdr;

> +	ring = &pool->ring->hdr;

>  	mask = pool->ring_mask;

>  	cache_num = cache->num;

> 

> @@ -172,6 +172,7 @@ static pool_t *reserve_pool(void)

>  {

>  	int i;

>  	pool_t *pool;

> +	char ring_name[ODP_POOL_NAME_LEN];

> 

>  	for (i = 0; i < ODP_CONFIG_POOLS; i++) {

>  		pool = pool_entry(i);

> @@ -180,6 +181,19 @@ static pool_t *reserve_pool(void)

>  		if (pool->reserved == 0) {

>  			pool->reserved = 1;

>  			UNLOCK(&pool->lock);

> +			sprintf(ring_name, "pool_ring_%d", i);

> +			pool->ring_shm =

> +				odp_shm_reserve(ring_name,

> +						sizeof(pool_ring_t),

> +						ODP_CACHE_LINE_SIZE, 0);

> +			if (odp_unlikely(pool->ring_shm == ODP_SHM_INVALID)) {

> +				ODP_ERR("Unable to alloc pool ring %d\n", i);

> +				LOCK(&pool->lock);

> +				pool->reserved = 0;

> +				UNLOCK(&pool->lock);

> +				break;

> +			}

> +			pool->ring = odp_shm_addr(pool->ring_shm);

>  			return pool;

>  		}

>  		UNLOCK(&pool->lock);

> @@ -214,7 +228,7 @@ static void init_buffers(pool_t *pool)

>  	int type;

>  	uint32_t seg_size;

> 

> -	ring = &pool->ring.hdr;

> +	ring = &pool->ring->hdr;

>  	mask = pool->ring_mask;

>  	type = pool->params.type;

> 

> @@ -411,7 +425,7 @@ static odp_pool_t pool_create(const char *name,

> odp_pool_param_t *params,

>  		pool->uarea_base_addr = odp_shm_addr(pool->uarea_shm);

>  	}

> 

> -	ring_init(&pool->ring.hdr);

> +	ring_init(&pool->ring->hdr);

>  	init_buffers(pool);

> 

>  	return pool->pool_hdl;

> @@ -536,6 +550,8 @@ int odp_pool_destroy(odp_pool_t pool_hdl)

>  		odp_shm_free(pool->uarea_shm);

> 

>  	pool->reserved = 0;

> +	odp_shm_free(pool->ring_shm);

> +	pool->ring = NULL;

>  	UNLOCK(&pool->lock);

> 

>  	return 0;

> @@ -592,8 +608,6 @@ int buffer_alloc_multi(pool_t *pool, odp_buffer_t

> buf[],

>  	pool_cache_t *cache;

>  	uint32_t cache_num, num_ch, num_deq, burst;

> 

> -	ring  = &pool->ring.hdr;

> -	mask  = pool->ring_mask;

>  	cache = local.cache[pool->pool_idx];

> 

>  	cache_num = cache->num;

> @@ -620,6 +634,8 @@ int buffer_alloc_multi(pool_t *pool, odp_buffer_t

> buf[],

>  		 * and not uint32_t. */

>  		uint32_t data[burst];

> 

> +		ring      = &pool->ring->hdr;

> +		mask      = pool->ring_mask;

>  		burst     = ring_deq_multi(ring, mask, data, burst);

>  		cache_num = burst - num_deq;

> 

> @@ -671,12 +687,12 @@ static inline void buffer_free_to_pool(uint32_t

> pool_id,

> 

>  	cache = local.cache[pool_id];

>  	pool  = pool_entry(pool_id);

> -	ring  = &pool->ring.hdr;

> -	mask  = pool->ring_mask;

> 

>  	/* Special case of a very large free. Move directly to

>  	 * the global pool. */

>  	if (odp_unlikely(num > CONFIG_POOL_CACHE_SIZE)) {

> +		ring  = &pool->ring->hdr;

> +		mask  = pool->ring_mask;

>  		for (i = 0; i < num; i++)

>  			ring_enq(ring, mask, (uint32_t)(uintptr_t)buf[i]);

> 

> @@ -691,6 +707,9 @@ static inline void buffer_free_to_pool(uint32_t

> pool_id,

>  		uint32_t index;

>  		int burst = CACHE_BURST;

> 

> +		ring  = &pool->ring->hdr;

> +		mask  = pool->ring_mask;

> +

>  		if (odp_unlikely(num > CACHE_BURST))

>  			burst = num;

> 

> --

> 2.9.3
Maxim Uvarov Jan. 11, 2017, 2:18 p.m. UTC | #2
Merged,
Maxim.

On 01/11/17 16:50, Savolainen, Petri (Nokia - FI/Espoo) wrote:
> Reviewed-by: Petri Savolainen <petri.savolainen@nokia.com>

> 

> 

>> -----Original Message-----

>> From: lng-odp [mailto:lng-odp-bounces@lists.linaro.org] On Behalf Of Bill

>> Fischofer

>> Sent: Tuesday, January 10, 2017 6:00 PM

>> To: lng-odp@lists.linaro.org

>> Subject: [lng-odp] [API-NEXT PATCHv4] linux-generic: pool: defer ring

>> allocation until pool creation

>>

>> To avoid excessive memory overhead for pools, defer the allocation of

>> the pool ring until odp_pool_create() is called. This keeps pool memory

>> overhead proportional to the number of pools actually in use rather

>> than the architected maximum number of pools.

>>

>> This patch addresses Bug https://bugs.linaro.org/show_bug.cgi?id=2765

>>

>> Signed-off-by: Bill Fischofer <bill.fischofer@linaro.org>

>> ---

>> Changes for v4:

>> - Change ring name per Maxim's suggestion

>> - Add lock/unlock calls around setting pool->reserved back to 0 per Petri

>>

>> Changes for v3:

>> - Do not reference pool ring on buffer alloc/free if cache can satisfy

>> request

>>

>> Changes for v2:

>> - Reset reserved to 0 if ring allocation fails to recover properly

>>

>>  platform/linux-generic/include/odp_pool_internal.h |  3 +-

>>  platform/linux-generic/odp_pool.c                  | 33

>> +++++++++++++++++-----

>>  2 files changed, 28 insertions(+), 8 deletions(-)

>>

>> diff --git a/platform/linux-generic/include/odp_pool_internal.h

>> b/platform/linux-generic/include/odp_pool_internal.h

>> index 5d7b817..4915bda 100644

>> --- a/platform/linux-generic/include/odp_pool_internal.h

>> +++ b/platform/linux-generic/include/odp_pool_internal.h

>> @@ -69,7 +69,8 @@ typedef struct pool_t {

>>

>>  	pool_cache_t     local_cache[ODP_THREAD_COUNT_MAX];

>>

>> -	pool_ring_t      ring;

>> +	odp_shm_t        ring_shm;

>> +	pool_ring_t     *ring;

>>

>>  } pool_t;

>>

>> diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-

>> generic/odp_pool.c

>> index cae2759..932efe3 100644

>> --- a/platform/linux-generic/odp_pool.c

>> +++ b/platform/linux-generic/odp_pool.c

>> @@ -143,7 +143,7 @@ static void flush_cache(pool_cache_t *cache, pool_t

>> *pool)

>>  	uint32_t mask;

>>  	uint32_t cache_num, i, data;

>>

>> -	ring = &pool->ring.hdr;

>> +	ring = &pool->ring->hdr;

>>  	mask = pool->ring_mask;

>>  	cache_num = cache->num;

>>

>> @@ -172,6 +172,7 @@ static pool_t *reserve_pool(void)

>>  {

>>  	int i;

>>  	pool_t *pool;

>> +	char ring_name[ODP_POOL_NAME_LEN];

>>

>>  	for (i = 0; i < ODP_CONFIG_POOLS; i++) {

>>  		pool = pool_entry(i);

>> @@ -180,6 +181,19 @@ static pool_t *reserve_pool(void)

>>  		if (pool->reserved == 0) {

>>  			pool->reserved = 1;

>>  			UNLOCK(&pool->lock);

>> +			sprintf(ring_name, "pool_ring_%d", i);

>> +			pool->ring_shm =

>> +				odp_shm_reserve(ring_name,

>> +						sizeof(pool_ring_t),

>> +						ODP_CACHE_LINE_SIZE, 0);

>> +			if (odp_unlikely(pool->ring_shm == ODP_SHM_INVALID)) {

>> +				ODP_ERR("Unable to alloc pool ring %d\n", i);

>> +				LOCK(&pool->lock);

>> +				pool->reserved = 0;

>> +				UNLOCK(&pool->lock);

>> +				break;

>> +			}

>> +			pool->ring = odp_shm_addr(pool->ring_shm);

>>  			return pool;

>>  		}

>>  		UNLOCK(&pool->lock);

>> @@ -214,7 +228,7 @@ static void init_buffers(pool_t *pool)

>>  	int type;

>>  	uint32_t seg_size;

>>

>> -	ring = &pool->ring.hdr;

>> +	ring = &pool->ring->hdr;

>>  	mask = pool->ring_mask;

>>  	type = pool->params.type;

>>

>> @@ -411,7 +425,7 @@ static odp_pool_t pool_create(const char *name,

>> odp_pool_param_t *params,

>>  		pool->uarea_base_addr = odp_shm_addr(pool->uarea_shm);

>>  	}

>>

>> -	ring_init(&pool->ring.hdr);

>> +	ring_init(&pool->ring->hdr);

>>  	init_buffers(pool);

>>

>>  	return pool->pool_hdl;

>> @@ -536,6 +550,8 @@ int odp_pool_destroy(odp_pool_t pool_hdl)

>>  		odp_shm_free(pool->uarea_shm);

>>

>>  	pool->reserved = 0;

>> +	odp_shm_free(pool->ring_shm);

>> +	pool->ring = NULL;

>>  	UNLOCK(&pool->lock);

>>

>>  	return 0;

>> @@ -592,8 +608,6 @@ int buffer_alloc_multi(pool_t *pool, odp_buffer_t

>> buf[],

>>  	pool_cache_t *cache;

>>  	uint32_t cache_num, num_ch, num_deq, burst;

>>

>> -	ring  = &pool->ring.hdr;

>> -	mask  = pool->ring_mask;

>>  	cache = local.cache[pool->pool_idx];

>>

>>  	cache_num = cache->num;

>> @@ -620,6 +634,8 @@ int buffer_alloc_multi(pool_t *pool, odp_buffer_t

>> buf[],

>>  		 * and not uint32_t. */

>>  		uint32_t data[burst];

>>

>> +		ring      = &pool->ring->hdr;

>> +		mask      = pool->ring_mask;

>>  		burst     = ring_deq_multi(ring, mask, data, burst);

>>  		cache_num = burst - num_deq;

>>

>> @@ -671,12 +687,12 @@ static inline void buffer_free_to_pool(uint32_t

>> pool_id,

>>

>>  	cache = local.cache[pool_id];

>>  	pool  = pool_entry(pool_id);

>> -	ring  = &pool->ring.hdr;

>> -	mask  = pool->ring_mask;

>>

>>  	/* Special case of a very large free. Move directly to

>>  	 * the global pool. */

>>  	if (odp_unlikely(num > CONFIG_POOL_CACHE_SIZE)) {

>> +		ring  = &pool->ring->hdr;

>> +		mask  = pool->ring_mask;

>>  		for (i = 0; i < num; i++)

>>  			ring_enq(ring, mask, (uint32_t)(uintptr_t)buf[i]);

>>

>> @@ -691,6 +707,9 @@ static inline void buffer_free_to_pool(uint32_t

>> pool_id,

>>  		uint32_t index;

>>  		int burst = CACHE_BURST;

>>

>> +		ring  = &pool->ring->hdr;

>> +		mask  = pool->ring_mask;

>> +

>>  		if (odp_unlikely(num > CACHE_BURST))

>>  			burst = num;

>>

>> --

>> 2.9.3

>
diff mbox

Patch

diff --git a/platform/linux-generic/include/odp_pool_internal.h b/platform/linux-generic/include/odp_pool_internal.h
index 5d7b817..4915bda 100644
--- a/platform/linux-generic/include/odp_pool_internal.h
+++ b/platform/linux-generic/include/odp_pool_internal.h
@@ -69,7 +69,8 @@  typedef struct pool_t {
 
 	pool_cache_t     local_cache[ODP_THREAD_COUNT_MAX];
 
-	pool_ring_t      ring;
+	odp_shm_t        ring_shm;
+	pool_ring_t     *ring;
 
 } pool_t;
 
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index cae2759..932efe3 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -143,7 +143,7 @@  static void flush_cache(pool_cache_t *cache, pool_t *pool)
 	uint32_t mask;
 	uint32_t cache_num, i, data;
 
-	ring = &pool->ring.hdr;
+	ring = &pool->ring->hdr;
 	mask = pool->ring_mask;
 	cache_num = cache->num;
 
@@ -172,6 +172,7 @@  static pool_t *reserve_pool(void)
 {
 	int i;
 	pool_t *pool;
+	char ring_name[ODP_POOL_NAME_LEN];
 
 	for (i = 0; i < ODP_CONFIG_POOLS; i++) {
 		pool = pool_entry(i);
@@ -180,6 +181,19 @@  static pool_t *reserve_pool(void)
 		if (pool->reserved == 0) {
 			pool->reserved = 1;
 			UNLOCK(&pool->lock);
+			sprintf(ring_name, "pool_ring_%d", i);
+			pool->ring_shm =
+				odp_shm_reserve(ring_name,
+						sizeof(pool_ring_t),
+						ODP_CACHE_LINE_SIZE, 0);
+			if (odp_unlikely(pool->ring_shm == ODP_SHM_INVALID)) {
+				ODP_ERR("Unable to alloc pool ring %d\n", i);
+				LOCK(&pool->lock);
+				pool->reserved = 0;
+				UNLOCK(&pool->lock);
+				break;
+			}
+			pool->ring = odp_shm_addr(pool->ring_shm);
 			return pool;
 		}
 		UNLOCK(&pool->lock);
@@ -214,7 +228,7 @@  static void init_buffers(pool_t *pool)
 	int type;
 	uint32_t seg_size;
 
-	ring = &pool->ring.hdr;
+	ring = &pool->ring->hdr;
 	mask = pool->ring_mask;
 	type = pool->params.type;
 
@@ -411,7 +425,7 @@  static odp_pool_t pool_create(const char *name, odp_pool_param_t *params,
 		pool->uarea_base_addr = odp_shm_addr(pool->uarea_shm);
 	}
 
-	ring_init(&pool->ring.hdr);
+	ring_init(&pool->ring->hdr);
 	init_buffers(pool);
 
 	return pool->pool_hdl;
@@ -536,6 +550,8 @@  int odp_pool_destroy(odp_pool_t pool_hdl)
 		odp_shm_free(pool->uarea_shm);
 
 	pool->reserved = 0;
+	odp_shm_free(pool->ring_shm);
+	pool->ring = NULL;
 	UNLOCK(&pool->lock);
 
 	return 0;
@@ -592,8 +608,6 @@  int buffer_alloc_multi(pool_t *pool, odp_buffer_t buf[],
 	pool_cache_t *cache;
 	uint32_t cache_num, num_ch, num_deq, burst;
 
-	ring  = &pool->ring.hdr;
-	mask  = pool->ring_mask;
 	cache = local.cache[pool->pool_idx];
 
 	cache_num = cache->num;
@@ -620,6 +634,8 @@  int buffer_alloc_multi(pool_t *pool, odp_buffer_t buf[],
 		 * and not uint32_t. */
 		uint32_t data[burst];
 
+		ring      = &pool->ring->hdr;
+		mask      = pool->ring_mask;
 		burst     = ring_deq_multi(ring, mask, data, burst);
 		cache_num = burst - num_deq;
 
@@ -671,12 +687,12 @@  static inline void buffer_free_to_pool(uint32_t pool_id,
 
 	cache = local.cache[pool_id];
 	pool  = pool_entry(pool_id);
-	ring  = &pool->ring.hdr;
-	mask  = pool->ring_mask;
 
 	/* Special case of a very large free. Move directly to
 	 * the global pool. */
 	if (odp_unlikely(num > CONFIG_POOL_CACHE_SIZE)) {
+		ring  = &pool->ring->hdr;
+		mask  = pool->ring_mask;
 		for (i = 0; i < num; i++)
 			ring_enq(ring, mask, (uint32_t)(uintptr_t)buf[i]);
 
@@ -691,6 +707,9 @@  static inline void buffer_free_to_pool(uint32_t pool_id,
 		uint32_t index;
 		int burst = CACHE_BURST;
 
+		ring  = &pool->ring->hdr;
+		mask  = pool->ring_mask;
+
 		if (odp_unlikely(num > CACHE_BURST))
 			burst = num;