diff mbox

linux-generic: timer: use plain buffers for timeouts

Message ID 1429884635-17042-1-git-send-email-ola.liljedahl@linaro.org
State Accepted
Commit f834609c554c933e6398252817baf59016074447
Headers show

Commit Message

Ola Liljedahl April 24, 2015, 2:10 p.m. UTC
Use plain buffers for timeouts. Store the timeout header in the buffer
data area. This simplifies re-use on other platforms where the event
header cannot be arbitrarily defined.

Signed-off-by: Ola Liljedahl <ola.liljedahl@linaro.org>
---
(This document/code contribution attached is provided under the terms of
agreement LES-LTM-21309)

 platform/linux-generic/include/odp_timer_internal.h | 15 ++++++++++++---
 platform/linux-generic/odp_pool.c                   |  7 ++++---
 platform/linux-generic/odp_timer.c                  | 15 +++++++++------
 3 files changed, 25 insertions(+), 12 deletions(-)

Comments

Maxim Uvarov May 13, 2015, 10:19 a.m. UTC | #1
Patch looks good. Validation test passed. Need one more review.

Thanks,
Maxim.

On 04/24/2015 17:10, Ola Liljedahl wrote:
> Use plain buffers for timeouts. Store the timeout header in the buffer
> data area. This simplifies re-use on other platforms where the event
> header cannot be arbitrarily defined.
>
> Signed-off-by: Ola Liljedahl <ola.liljedahl@linaro.org>
> ---
> (This document/code contribution attached is provided under the terms of
> agreement LES-LTM-21309)
>
>   platform/linux-generic/include/odp_timer_internal.h | 15 ++++++++++++---
>   platform/linux-generic/odp_pool.c                   |  7 ++++---
>   platform/linux-generic/odp_timer.c                  | 15 +++++++++------
>   3 files changed, 25 insertions(+), 12 deletions(-)
>
> diff --git a/platform/linux-generic/include/odp_timer_internal.h b/platform/linux-generic/include/odp_timer_internal.h
> index 90af62c..a631bd0 100644
> --- a/platform/linux-generic/include/odp_timer_internal.h
> +++ b/platform/linux-generic/include/odp_timer_internal.h
> @@ -16,36 +16,45 @@
>   
>   #include <odp/align.h>
>   #include <odp/debug.h>
> +#include <odp_debug_internal.h>
>   #include <odp_buffer_internal.h>
>   #include <odp_pool_internal.h>
>   #include <odp/timer.h>
>   
>   /**
>    * Internal Timeout header
> + * For compatibility with buffers, we use the buffer_hdr here and nothing else
>    */
>   typedef struct {
>   	/* common buffer header */
>   	odp_buffer_hdr_t buf_hdr;
> +} odp_timeout_fakehdr_t;
>   
> +/* The real timeout header is in a separate struct in a separate location */
> +typedef struct {
>   	/* Requested expiration time */
>   	uint64_t expiration;
>   	/* User ptr inherited from parent timer */
>   	void *user_ptr;
> +	/* Handle of buffer we are located in */
> +	odp_buffer_t buf;
>   	/* Parent timer */
>   	odp_timer_t timer;
>   } odp_timeout_hdr_t;
>   
>   typedef struct odp_timeout_hdr_stride {
> -	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_hdr_t))];
> +	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_fakehdr_t))];
>   } odp_timeout_hdr_stride;
>   
>   
>   /**
>    * Return the timeout header
>    */
> -static inline odp_timeout_hdr_t *odp_timeout_hdr(odp_buffer_t buf)
> +static inline odp_timeout_hdr_t *odp_timeout_hdr_from_buf(odp_buffer_t buf)
>   {
> -	return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
> +	/* The real timeout header is stored in the buffer data */
> +	ODP_ASSERT(odp_buffer_size(buf) == sizeof(odp_timeout_hdr_t));
> +	return (odp_timeout_hdr_t *)odp_buffer_addr(buf);
>   }
>   
>   #endif
> diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
> index bf49623..fc10aa4 100644
> --- a/platform/linux-generic/odp_pool.c
> +++ b/platform/linux-generic/odp_pool.c
> @@ -32,7 +32,7 @@
>   typedef union buffer_type_any_u {
>   	odp_buffer_hdr_t  buf;
>   	odp_packet_hdr_t  pkt;
> -	odp_timeout_hdr_t tmo;
> +	odp_timeout_fakehdr_t tmo;
>   } odp_anybuf_t;
>   
>   _ODP_STATIC_ASSERT((sizeof(union buffer_type_any_u) % 8) == 0,
> @@ -148,7 +148,8 @@ odp_pool_t odp_pool_create(const char *name,
>   
>   	/* Default size and align for timeouts */
>   	if (params->type == ODP_POOL_TIMEOUT) {
> -		params->buf.size  = 0; /* tmo.__res1 */
> +		/* The real timeout header is stored in the buffer */
> +		params->buf.size  = sizeof(odp_timeout_hdr_t); /* tmo.__res1 */
>   		params->buf.align = 0; /* tmo.__res2 */
>   	}
>   
> @@ -226,7 +227,7 @@ odp_pool_t odp_pool_create(const char *name,
>   		break;
>   
>   	case ODP_POOL_TIMEOUT:
> -		blk_size = 0;
> +		blk_size = params->buf.size;
>   		buf_num = params->tmo.num;
>   		buf_stride = sizeof(odp_timeout_hdr_stride);
>   		break;
> diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c
> index e5391dc..1922f94 100644
> --- a/platform/linux-generic/odp_timer.c
> +++ b/platform/linux-generic/odp_timer.c
> @@ -78,7 +78,7 @@ static _odp_atomic_flag_t locks[NUM_LOCKS]; /* Multiple locks per cache line! */
>   
>   static odp_timeout_hdr_t *timeout_hdr_from_buf(odp_buffer_t buf)
>   {
> -	return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
> +	return odp_timeout_hdr_from_buf(buf);
>   }
>   
>   /******************************************************************************
> @@ -820,8 +820,7 @@ odp_timeout_t odp_timeout_from_event(odp_event_t ev)
>   odp_event_t odp_timeout_to_event(odp_timeout_t tmo)
>   {
>   	odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
> -	odp_buffer_t buf = odp_hdr_to_buf(&tmo_hdr->buf_hdr);
> -	return odp_buffer_to_event(buf);
> +	return odp_buffer_to_event(tmo_hdr->buf);
>   }
>   
>   int odp_timeout_fresh(odp_timeout_t tmo)
> @@ -857,16 +856,20 @@ void *odp_timeout_user_ptr(odp_timeout_t tmo)
>   
>   odp_timeout_t odp_timeout_alloc(odp_pool_t pool)
>   {
> +	odp_timeout_hdr_t *tmo_hdr;
>   	odp_buffer_t buf = odp_buffer_alloc(pool);
>   	if (odp_unlikely(buf == ODP_BUFFER_INVALID))
>   		return ODP_TIMEOUT_INVALID;
> -	return odp_timeout_from_event(odp_buffer_to_event(buf));
> +	tmo_hdr = timeout_hdr_from_buf(buf);
> +	/* Must save buffer handle in timeout header for later use */
> +	tmo_hdr->buf = buf;
> +	return (odp_timeout_t)tmo_hdr;
>   }
>   
>   void odp_timeout_free(odp_timeout_t tmo)
>   {
> -	odp_event_t ev = odp_timeout_to_event(tmo);
> -	odp_buffer_free(odp_buffer_from_event(ev));
> +	odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
> +	odp_buffer_free(tmo_hdr->buf);
>   }
>   
>   int odp_timer_init_global(void)
Ola Liljedahl May 13, 2015, 3:31 p.m. UTC | #2
On 13 May 2015 at 12:19, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:

> Patch looks good. Validation test passed. Need one more review.
>
Thanks. I did this primarily for KS2 being able to use the linux-generic
timer implementation without any changes. I am waiting for Taras to verify
this.

-- Ola


>
> Thanks,
> Maxim.
>
>
> On 04/24/2015 17:10, Ola Liljedahl wrote:
>
>> Use plain buffers for timeouts. Store the timeout header in the buffer
>> data area. This simplifies re-use on other platforms where the event
>> header cannot be arbitrarily defined.
>>
>> Signed-off-by: Ola Liljedahl <ola.liljedahl@linaro.org>
>> ---
>> (This document/code contribution attached is provided under the terms of
>> agreement LES-LTM-21309)
>>
>>   platform/linux-generic/include/odp_timer_internal.h | 15 ++++++++++++---
>>   platform/linux-generic/odp_pool.c                   |  7 ++++---
>>   platform/linux-generic/odp_timer.c                  | 15 +++++++++------
>>   3 files changed, 25 insertions(+), 12 deletions(-)
>>
>> diff --git a/platform/linux-generic/include/odp_timer_internal.h
>> b/platform/linux-generic/include/odp_timer_internal.h
>> index 90af62c..a631bd0 100644
>> --- a/platform/linux-generic/include/odp_timer_internal.h
>> +++ b/platform/linux-generic/include/odp_timer_internal.h
>> @@ -16,36 +16,45 @@
>>     #include <odp/align.h>
>>   #include <odp/debug.h>
>> +#include <odp_debug_internal.h>
>>   #include <odp_buffer_internal.h>
>>   #include <odp_pool_internal.h>
>>   #include <odp/timer.h>
>>     /**
>>    * Internal Timeout header
>> + * For compatibility with buffers, we use the buffer_hdr here and
>> nothing else
>>    */
>>   typedef struct {
>>         /* common buffer header */
>>         odp_buffer_hdr_t buf_hdr;
>> +} odp_timeout_fakehdr_t;
>>   +/* The real timeout header is in a separate struct in a separate
>> location */
>> +typedef struct {
>>         /* Requested expiration time */
>>         uint64_t expiration;
>>         /* User ptr inherited from parent timer */
>>         void *user_ptr;
>> +       /* Handle of buffer we are located in */
>> +       odp_buffer_t buf;
>>         /* Parent timer */
>>         odp_timer_t timer;
>>   } odp_timeout_hdr_t;
>>     typedef struct odp_timeout_hdr_stride {
>> -       uint8_t
>> pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_hdr_t))];
>> +       uint8_t
>> pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_fakehdr_t))];
>>   } odp_timeout_hdr_stride;
>>       /**
>>    * Return the timeout header
>>    */
>> -static inline odp_timeout_hdr_t *odp_timeout_hdr(odp_buffer_t buf)
>> +static inline odp_timeout_hdr_t *odp_timeout_hdr_from_buf(odp_buffer_t
>> buf)
>>   {
>> -       return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
>> +       /* The real timeout header is stored in the buffer data */
>> +       ODP_ASSERT(odp_buffer_size(buf) == sizeof(odp_timeout_hdr_t));
>> +       return (odp_timeout_hdr_t *)odp_buffer_addr(buf);
>>   }
>>     #endif
>> diff --git a/platform/linux-generic/odp_pool.c
>> b/platform/linux-generic/odp_pool.c
>> index bf49623..fc10aa4 100644
>> --- a/platform/linux-generic/odp_pool.c
>> +++ b/platform/linux-generic/odp_pool.c
>> @@ -32,7 +32,7 @@
>>   typedef union buffer_type_any_u {
>>         odp_buffer_hdr_t  buf;
>>         odp_packet_hdr_t  pkt;
>> -       odp_timeout_hdr_t tmo;
>> +       odp_timeout_fakehdr_t tmo;
>>   } odp_anybuf_t;
>>     _ODP_STATIC_ASSERT((sizeof(union buffer_type_any_u) % 8) == 0,
>> @@ -148,7 +148,8 @@ odp_pool_t odp_pool_create(const char *name,
>>         /* Default size and align for timeouts */
>>         if (params->type == ODP_POOL_TIMEOUT) {
>> -               params->buf.size  = 0; /* tmo.__res1 */
>> +               /* The real timeout header is stored in the buffer */
>> +               params->buf.size  = sizeof(odp_timeout_hdr_t); /*
>> tmo.__res1 */
>>                 params->buf.align = 0; /* tmo.__res2 */
>>         }
>>   @@ -226,7 +227,7 @@ odp_pool_t odp_pool_create(const char *name,
>>                 break;
>>         case ODP_POOL_TIMEOUT:
>> -               blk_size = 0;
>> +               blk_size = params->buf.size;
>>                 buf_num = params->tmo.num;
>>                 buf_stride = sizeof(odp_timeout_hdr_stride);
>>                 break;
>> diff --git a/platform/linux-generic/odp_timer.c
>> b/platform/linux-generic/odp_timer.c
>> index e5391dc..1922f94 100644
>> --- a/platform/linux-generic/odp_timer.c
>> +++ b/platform/linux-generic/odp_timer.c
>> @@ -78,7 +78,7 @@ static _odp_atomic_flag_t locks[NUM_LOCKS]; /* Multiple
>> locks per cache line! */
>>     static odp_timeout_hdr_t *timeout_hdr_from_buf(odp_buffer_t buf)
>>   {
>> -       return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
>> +       return odp_timeout_hdr_from_buf(buf);
>>   }
>>
>> /******************************************************************************
>> @@ -820,8 +820,7 @@ odp_timeout_t odp_timeout_from_event(odp_event_t ev)
>>   odp_event_t odp_timeout_to_event(odp_timeout_t tmo)
>>   {
>>         odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
>> -       odp_buffer_t buf = odp_hdr_to_buf(&tmo_hdr->buf_hdr);
>> -       return odp_buffer_to_event(buf);
>> +       return odp_buffer_to_event(tmo_hdr->buf);
>>   }
>>     int odp_timeout_fresh(odp_timeout_t tmo)
>> @@ -857,16 +856,20 @@ void *odp_timeout_user_ptr(odp_timeout_t tmo)
>>     odp_timeout_t odp_timeout_alloc(odp_pool_t pool)
>>   {
>> +       odp_timeout_hdr_t *tmo_hdr;
>>         odp_buffer_t buf = odp_buffer_alloc(pool);
>>         if (odp_unlikely(buf == ODP_BUFFER_INVALID))
>>                 return ODP_TIMEOUT_INVALID;
>> -       return odp_timeout_from_event(odp_buffer_to_event(buf));
>> +       tmo_hdr = timeout_hdr_from_buf(buf);
>> +       /* Must save buffer handle in timeout header for later use */
>> +       tmo_hdr->buf = buf;
>> +       return (odp_timeout_t)tmo_hdr;
>>   }
>>     void odp_timeout_free(odp_timeout_t tmo)
>>   {
>> -       odp_event_t ev = odp_timeout_to_event(tmo);
>> -       odp_buffer_free(odp_buffer_from_event(ev));
>> +       odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
>> +       odp_buffer_free(tmo_hdr->buf);
>>   }
>>     int odp_timer_init_global(void)
>>
>
> _______________________________________________
> lng-odp mailing list
> lng-odp@lists.linaro.org
> https://lists.linaro.org/mailman/listinfo/lng-odp
>
Ola Liljedahl May 29, 2015, 2:26 p.m. UTC | #3
On 13 May 2015 at 17:31, Ola Liljedahl <ola.liljedahl@linaro.org> wrote:

> On 13 May 2015 at 12:19, Maxim Uvarov <maxim.uvarov@linaro.org> wrote:
>
>> Patch looks good. Validation test passed. Need one more review.
>>
> Thanks. I did this primarily for KS2 being able to use the linux-generic
> timer implementation without any changes. I am waiting for Taras to verify
> this.
>
Well it seems now that Taras is not going to verify that this patch solves
his problems on KS2. I like the patch anyway and would like to see it
merged. Any reviewers?

-- Ola


>
> -- Ola
>
>
>>
>> Thanks,
>> Maxim.
>>
>>
>> On 04/24/2015 17:10, Ola Liljedahl wrote:
>>
>>> Use plain buffers for timeouts. Store the timeout header in the buffer
>>> data area. This simplifies re-use on other platforms where the event
>>> header cannot be arbitrarily defined.
>>>
>>> Signed-off-by: Ola Liljedahl <ola.liljedahl@linaro.org>
>>> ---
>>> (This document/code contribution attached is provided under the terms of
>>> agreement LES-LTM-21309)
>>>
>>>   platform/linux-generic/include/odp_timer_internal.h | 15
>>> ++++++++++++---
>>>   platform/linux-generic/odp_pool.c                   |  7 ++++---
>>>   platform/linux-generic/odp_timer.c                  | 15
>>> +++++++++------
>>>   3 files changed, 25 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/platform/linux-generic/include/odp_timer_internal.h
>>> b/platform/linux-generic/include/odp_timer_internal.h
>>> index 90af62c..a631bd0 100644
>>> --- a/platform/linux-generic/include/odp_timer_internal.h
>>> +++ b/platform/linux-generic/include/odp_timer_internal.h
>>> @@ -16,36 +16,45 @@
>>>     #include <odp/align.h>
>>>   #include <odp/debug.h>
>>> +#include <odp_debug_internal.h>
>>>   #include <odp_buffer_internal.h>
>>>   #include <odp_pool_internal.h>
>>>   #include <odp/timer.h>
>>>     /**
>>>    * Internal Timeout header
>>> + * For compatibility with buffers, we use the buffer_hdr here and
>>> nothing else
>>>    */
>>>   typedef struct {
>>>         /* common buffer header */
>>>         odp_buffer_hdr_t buf_hdr;
>>> +} odp_timeout_fakehdr_t;
>>>   +/* The real timeout header is in a separate struct in a separate
>>> location */
>>> +typedef struct {
>>>         /* Requested expiration time */
>>>         uint64_t expiration;
>>>         /* User ptr inherited from parent timer */
>>>         void *user_ptr;
>>> +       /* Handle of buffer we are located in */
>>> +       odp_buffer_t buf;
>>>         /* Parent timer */
>>>         odp_timer_t timer;
>>>   } odp_timeout_hdr_t;
>>>     typedef struct odp_timeout_hdr_stride {
>>> -       uint8_t
>>> pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_hdr_t))];
>>> +       uint8_t
>>> pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_fakehdr_t))];
>>>   } odp_timeout_hdr_stride;
>>>       /**
>>>    * Return the timeout header
>>>    */
>>> -static inline odp_timeout_hdr_t *odp_timeout_hdr(odp_buffer_t buf)
>>> +static inline odp_timeout_hdr_t *odp_timeout_hdr_from_buf(odp_buffer_t
>>> buf)
>>>   {
>>> -       return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
>>> +       /* The real timeout header is stored in the buffer data */
>>> +       ODP_ASSERT(odp_buffer_size(buf) == sizeof(odp_timeout_hdr_t));
>>> +       return (odp_timeout_hdr_t *)odp_buffer_addr(buf);
>>>   }
>>>     #endif
>>> diff --git a/platform/linux-generic/odp_pool.c
>>> b/platform/linux-generic/odp_pool.c
>>> index bf49623..fc10aa4 100644
>>> --- a/platform/linux-generic/odp_pool.c
>>> +++ b/platform/linux-generic/odp_pool.c
>>> @@ -32,7 +32,7 @@
>>>   typedef union buffer_type_any_u {
>>>         odp_buffer_hdr_t  buf;
>>>         odp_packet_hdr_t  pkt;
>>> -       odp_timeout_hdr_t tmo;
>>> +       odp_timeout_fakehdr_t tmo;
>>>   } odp_anybuf_t;
>>>     _ODP_STATIC_ASSERT((sizeof(union buffer_type_any_u) % 8) == 0,
>>> @@ -148,7 +148,8 @@ odp_pool_t odp_pool_create(const char *name,
>>>         /* Default size and align for timeouts */
>>>         if (params->type == ODP_POOL_TIMEOUT) {
>>> -               params->buf.size  = 0; /* tmo.__res1 */
>>> +               /* The real timeout header is stored in the buffer */
>>> +               params->buf.size  = sizeof(odp_timeout_hdr_t); /*
>>> tmo.__res1 */
>>>                 params->buf.align = 0; /* tmo.__res2 */
>>>         }
>>>   @@ -226,7 +227,7 @@ odp_pool_t odp_pool_create(const char *name,
>>>                 break;
>>>         case ODP_POOL_TIMEOUT:
>>> -               blk_size = 0;
>>> +               blk_size = params->buf.size;
>>>                 buf_num = params->tmo.num;
>>>                 buf_stride = sizeof(odp_timeout_hdr_stride);
>>>                 break;
>>> diff --git a/platform/linux-generic/odp_timer.c
>>> b/platform/linux-generic/odp_timer.c
>>> index e5391dc..1922f94 100644
>>> --- a/platform/linux-generic/odp_timer.c
>>> +++ b/platform/linux-generic/odp_timer.c
>>> @@ -78,7 +78,7 @@ static _odp_atomic_flag_t locks[NUM_LOCKS]; /*
>>> Multiple locks per cache line! */
>>>     static odp_timeout_hdr_t *timeout_hdr_from_buf(odp_buffer_t buf)
>>>   {
>>> -       return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
>>> +       return odp_timeout_hdr_from_buf(buf);
>>>   }
>>>
>>> /******************************************************************************
>>> @@ -820,8 +820,7 @@ odp_timeout_t odp_timeout_from_event(odp_event_t ev)
>>>   odp_event_t odp_timeout_to_event(odp_timeout_t tmo)
>>>   {
>>>         odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
>>> -       odp_buffer_t buf = odp_hdr_to_buf(&tmo_hdr->buf_hdr);
>>> -       return odp_buffer_to_event(buf);
>>> +       return odp_buffer_to_event(tmo_hdr->buf);
>>>   }
>>>     int odp_timeout_fresh(odp_timeout_t tmo)
>>> @@ -857,16 +856,20 @@ void *odp_timeout_user_ptr(odp_timeout_t tmo)
>>>     odp_timeout_t odp_timeout_alloc(odp_pool_t pool)
>>>   {
>>> +       odp_timeout_hdr_t *tmo_hdr;
>>>         odp_buffer_t buf = odp_buffer_alloc(pool);
>>>         if (odp_unlikely(buf == ODP_BUFFER_INVALID))
>>>                 return ODP_TIMEOUT_INVALID;
>>> -       return odp_timeout_from_event(odp_buffer_to_event(buf));
>>> +       tmo_hdr = timeout_hdr_from_buf(buf);
>>> +       /* Must save buffer handle in timeout header for later use */
>>> +       tmo_hdr->buf = buf;
>>> +       return (odp_timeout_t)tmo_hdr;
>>>   }
>>>     void odp_timeout_free(odp_timeout_t tmo)
>>>   {
>>> -       odp_event_t ev = odp_timeout_to_event(tmo);
>>> -       odp_buffer_free(odp_buffer_from_event(ev));
>>> +       odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
>>> +       odp_buffer_free(tmo_hdr->buf);
>>>   }
>>>     int odp_timer_init_global(void)
>>>
>>
>> _______________________________________________
>> lng-odp mailing list
>> lng-odp@lists.linaro.org
>> https://lists.linaro.org/mailman/listinfo/lng-odp
>>
>
>
diff mbox

Patch

diff --git a/platform/linux-generic/include/odp_timer_internal.h b/platform/linux-generic/include/odp_timer_internal.h
index 90af62c..a631bd0 100644
--- a/platform/linux-generic/include/odp_timer_internal.h
+++ b/platform/linux-generic/include/odp_timer_internal.h
@@ -16,36 +16,45 @@ 
 
 #include <odp/align.h>
 #include <odp/debug.h>
+#include <odp_debug_internal.h>
 #include <odp_buffer_internal.h>
 #include <odp_pool_internal.h>
 #include <odp/timer.h>
 
 /**
  * Internal Timeout header
+ * For compatibility with buffers, we use the buffer_hdr here and nothing else
  */
 typedef struct {
 	/* common buffer header */
 	odp_buffer_hdr_t buf_hdr;
+} odp_timeout_fakehdr_t;
 
+/* The real timeout header is in a separate struct in a separate location */
+typedef struct {
 	/* Requested expiration time */
 	uint64_t expiration;
 	/* User ptr inherited from parent timer */
 	void *user_ptr;
+	/* Handle of buffer we are located in */
+	odp_buffer_t buf;
 	/* Parent timer */
 	odp_timer_t timer;
 } odp_timeout_hdr_t;
 
 typedef struct odp_timeout_hdr_stride {
-	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_hdr_t))];
+	uint8_t pad[ODP_CACHE_LINE_SIZE_ROUNDUP(sizeof(odp_timeout_fakehdr_t))];
 } odp_timeout_hdr_stride;
 
 
 /**
  * Return the timeout header
  */
-static inline odp_timeout_hdr_t *odp_timeout_hdr(odp_buffer_t buf)
+static inline odp_timeout_hdr_t *odp_timeout_hdr_from_buf(odp_buffer_t buf)
 {
-	return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
+	/* The real timeout header is stored in the buffer data */
+	ODP_ASSERT(odp_buffer_size(buf) == sizeof(odp_timeout_hdr_t));
+	return (odp_timeout_hdr_t *)odp_buffer_addr(buf);
 }
 
 #endif
diff --git a/platform/linux-generic/odp_pool.c b/platform/linux-generic/odp_pool.c
index bf49623..fc10aa4 100644
--- a/platform/linux-generic/odp_pool.c
+++ b/platform/linux-generic/odp_pool.c
@@ -32,7 +32,7 @@ 
 typedef union buffer_type_any_u {
 	odp_buffer_hdr_t  buf;
 	odp_packet_hdr_t  pkt;
-	odp_timeout_hdr_t tmo;
+	odp_timeout_fakehdr_t tmo;
 } odp_anybuf_t;
 
 _ODP_STATIC_ASSERT((sizeof(union buffer_type_any_u) % 8) == 0,
@@ -148,7 +148,8 @@  odp_pool_t odp_pool_create(const char *name,
 
 	/* Default size and align for timeouts */
 	if (params->type == ODP_POOL_TIMEOUT) {
-		params->buf.size  = 0; /* tmo.__res1 */
+		/* The real timeout header is stored in the buffer */
+		params->buf.size  = sizeof(odp_timeout_hdr_t); /* tmo.__res1 */
 		params->buf.align = 0; /* tmo.__res2 */
 	}
 
@@ -226,7 +227,7 @@  odp_pool_t odp_pool_create(const char *name,
 		break;
 
 	case ODP_POOL_TIMEOUT:
-		blk_size = 0;
+		blk_size = params->buf.size;
 		buf_num = params->tmo.num;
 		buf_stride = sizeof(odp_timeout_hdr_stride);
 		break;
diff --git a/platform/linux-generic/odp_timer.c b/platform/linux-generic/odp_timer.c
index e5391dc..1922f94 100644
--- a/platform/linux-generic/odp_timer.c
+++ b/platform/linux-generic/odp_timer.c
@@ -78,7 +78,7 @@  static _odp_atomic_flag_t locks[NUM_LOCKS]; /* Multiple locks per cache line! */
 
 static odp_timeout_hdr_t *timeout_hdr_from_buf(odp_buffer_t buf)
 {
-	return (odp_timeout_hdr_t *)odp_buf_to_hdr(buf);
+	return odp_timeout_hdr_from_buf(buf);
 }
 
 /******************************************************************************
@@ -820,8 +820,7 @@  odp_timeout_t odp_timeout_from_event(odp_event_t ev)
 odp_event_t odp_timeout_to_event(odp_timeout_t tmo)
 {
 	odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
-	odp_buffer_t buf = odp_hdr_to_buf(&tmo_hdr->buf_hdr);
-	return odp_buffer_to_event(buf);
+	return odp_buffer_to_event(tmo_hdr->buf);
 }
 
 int odp_timeout_fresh(odp_timeout_t tmo)
@@ -857,16 +856,20 @@  void *odp_timeout_user_ptr(odp_timeout_t tmo)
 
 odp_timeout_t odp_timeout_alloc(odp_pool_t pool)
 {
+	odp_timeout_hdr_t *tmo_hdr;
 	odp_buffer_t buf = odp_buffer_alloc(pool);
 	if (odp_unlikely(buf == ODP_BUFFER_INVALID))
 		return ODP_TIMEOUT_INVALID;
-	return odp_timeout_from_event(odp_buffer_to_event(buf));
+	tmo_hdr = timeout_hdr_from_buf(buf);
+	/* Must save buffer handle in timeout header for later use */
+	tmo_hdr->buf = buf;
+	return (odp_timeout_t)tmo_hdr;
 }
 
 void odp_timeout_free(odp_timeout_t tmo)
 {
-	odp_event_t ev = odp_timeout_to_event(tmo);
-	odp_buffer_free(odp_buffer_from_event(ev));
+	odp_timeout_hdr_t *tmo_hdr = (odp_timeout_hdr_t *)tmo;
+	odp_buffer_free(tmo_hdr->buf);
 }
 
 int odp_timer_init_global(void)