From 839e26e4706c719ec2732032f7bb5dd9e2015001 Mon Sep 17 00:00:00 2001 From: Cyril Jourdan Date: Wed, 6 Jul 2011 11:55:21 +0200 Subject: cesar/mac/common: use a list to postpone tonemap release, closes #1547 This little delay allows PBProc to keep a reference to a tonemap about to be released. --- cesar/mac/common/src/tonemap.c | 42 +++++++++++++++++++---- cesar/mac/common/test/fcall/src/set_tonemap.c | 5 ++- cesar/mac/common/test/tonemap/src/test_tonemap.c | 39 ++++++++++++++++++++- cesar/mac/common/tonemap.h | 43 +++++++++++++++++++----- 4 files changed, 111 insertions(+), 18 deletions(-) (limited to 'cesar/mac/common') diff --git a/cesar/mac/common/src/tonemap.c b/cesar/mac/common/src/tonemap.c index 84efbaf02e..0cde1fdbd3 100644 --- a/cesar/mac/common/src/tonemap.c +++ b/cesar/mac/common/src/tonemap.c @@ -104,6 +104,8 @@ tonemap_alloc () tm_entry->tmdma_desc_head = first; /* Tone map in use. */ tm_entry->released = TONEMAP_IN_USE; + /* Initialize release_link. */ + list_init_node (&tm_entry->release_link); /* Return allocated tone map. */ return tm_entry; } @@ -132,17 +134,43 @@ tonemap_disable (tonemaps_t *tms, u8 tmi) } void -tonemap_release_forced (tonemaps_t *tms, u8 tmi) +tonemap_release (tonemaps_t *tms, u8 tmi, + tonemap_release_list_t *tm_release_list) { /* Check parameters. */ dbg_assert (tms); dbg_assert ((TONEMAP_INDEX_IS_NEGOTIATED (tmi))); - dbg_assert (tms->tm[tmi]); - - /* Atomic deletion. */ tonemap_t *tm = tms->tm[tmi]; + dbg_assert (tm); + dbg_assert (tm_release_list); + + /* Put the tonemap in the release list and get it out of the + * station set. */ + list_push (tm_release_list, &tm->release_link); + tm->released = TONEMAP_RELEASE_TIMER_S; tms->tm[tmi] = NULL; - tonemap_free (tm); +} + +bool +tonemap_release_list_clean (tonemap_release_list_t *tm_release_list) +{ + /* Check parameter. */ + dbg_assert (tm_release_list); + + /* Parse the release list to free the expired tonemaps. */ + list_node_t *i, *i_next; + for (i = list_begin (tm_release_list); i != list_end (tm_release_list); + i = i_next) + { + i_next = list_next (i); + tonemap_t *tm = PARENT_OF (tonemap_t, release_link, i); + if (!--tm->released) + { + list_remove (tm_release_list, i); + tonemap_free (tm); + } + } + return list_empty (tm_release_list); } void @@ -488,7 +516,7 @@ tonemaps_disabled_clean (tonemaps_t *tms) } void -tonemaps_reset (tonemaps_t *tms) +tonemaps_reset (tonemaps_t *tms, tonemap_release_list_t *tm_release_list) { /* Check parameter. */ dbg_assert (tms); @@ -504,7 +532,7 @@ tonemaps_reset (tonemaps_t *tms) { /* Release if in use. */ if (tms->tm[i]) - tonemap_release_forced (tms, i); + tonemap_release (tms, i, tm_release_list); } /* Reset to default value. */ tonemaps_init (tms); diff --git a/cesar/mac/common/test/fcall/src/set_tonemap.c b/cesar/mac/common/test/fcall/src/set_tonemap.c index aca051da2f..de1beeabd4 100644 --- a/cesar/mac/common/test/fcall/src/set_tonemap.c +++ b/cesar/mac/common/test/fcall/src/set_tonemap.c @@ -49,7 +49,10 @@ mac_test_fcall_set_tonemap (mac_test_fcall_set_tonemap_t *ctx, tonemaps_t *tms = tx ? sta->tx_tonemaps : sta->rx_tonemaps; /* Release any older tonemap. */ if (tms->tm[tmi]) - tonemap_release_forced (tms, tmi); + { + tonemap_free (tms->tm[tmi]); + tms->tm[tmi] = NULL; + } /* Create the new tonemap. */ if (tmi >= PHY_MOD_ROBO_NB) { diff --git a/cesar/mac/common/test/tonemap/src/test_tonemap.c b/cesar/mac/common/test/tonemap/src/test_tonemap.c index ae2439818f..b85652fba9 100644 --- a/cesar/mac/common/test/tonemap/src/test_tonemap.c +++ b/cesar/mac/common/test/tonemap/src/test_tonemap.c @@ -699,6 +699,38 @@ tonemap_increase_test (test_t t) tonemap_free (tm); } +void +tonemap_release_test (test_t t) +{ + tonemap_release_list_t tm_release_list; + tonemap_release_list_init (&tm_release_list); + bool empty; + test_case_begin (t, "tone maps release"); + test_begin (t, "empty list cleanup") + { + empty = tonemap_release_list_clean (&tm_release_list); + test_fail_unless (empty == true); + } test_end; + test_begin (t, "release several tone maps") + { + tonemaps_t *tms = tonemaps_alloc (); + /* Create two tone maps. */ + uint tmi1 = tonemaps_set_first_free_tmi (tms, tonemap_alloc ()); + uint tmi2 = tonemaps_set_first_free_tmi (tms, tonemap_alloc ()); + /* Release them one by one. */ + tonemap_release (tms, tmi1, &tm_release_list); + empty = tonemap_release_list_clean (&tm_release_list); + test_fail_unless (empty == false); + tonemap_release (tms, tmi2, &tm_release_list); + empty = tonemap_release_list_clean (&tm_release_list); + test_fail_unless (empty == false); + empty = tonemap_release_list_clean (&tm_release_list); + test_fail_unless (empty == true); + /* Clean. */ + tonemaps_release (tms); + } test_end; +} + void tonemaps_access_test (test_t t) { @@ -768,6 +800,8 @@ tonemaps_reset_test (test_t t) test_begin (t, "release of allocated tone maps and reset to sane values") { tonemaps_t *tms = tonemaps_alloc (); + tonemap_release_list_t tm_release_list; + tonemap_release_list_init (&tm_release_list); const uint tm_count = 3; uint i; for (i = 0; i < tm_count; i++) @@ -776,7 +810,7 @@ tonemaps_reset_test (test_t t) = tonemaps_set_first_free_tmi (tms, tonemap_alloc ()); } test_fail_if (tms->default_tmi == 0); - tonemaps_reset (tms); + tonemaps_reset (tms, &tm_release_list); test_fail_if (tms->default_tmi != TONEMAP_INDEX_INITIAL_START); for (i = TONEMAP_INDEX_NEGOTIATED_FIRST; i < TONEMAP_INDEX_NB; i++) { @@ -784,6 +818,8 @@ tonemaps_reset_test (test_t t) } /* Clean. */ tonemaps_release (tms); + while (!tonemap_release_list_clean (&tm_release_list)) + ; } test_end; } @@ -798,6 +834,7 @@ tonemap_test_suite (test_t t) tonemap_copy_test (t); tonemap_decrease_test (t); tonemap_increase_test (t); + tonemap_release_test (t); tonemaps_access_test (t); tonemaps_reset_test (t); diff --git a/cesar/mac/common/tonemap.h b/cesar/mac/common/tonemap.h index a068144f64..270f7096e4 100644 --- a/cesar/mac/common/tonemap.h +++ b/cesar/mac/common/tonemap.h @@ -17,6 +17,7 @@ */ #include "hal/phy/defs.h" #include "lib/blk.h" +#include "lib/list.h" /** * Tone map indexes (TMI). @@ -204,6 +205,10 @@ struct tonemap_t * measures if memory is too low). */ u32 nb_pb; + /** + * Node to link the tonemaps in the release list. + */ + list_node_t release_link; }; typedef struct tonemap_t tonemap_t; @@ -275,6 +280,9 @@ struct tonemaps_t }; typedef struct tonemaps_t tonemaps_t; +/** Context of the tonemaps to be released. */ +typedef list_t tonemap_release_list_t; + BEGIN_DECLS /** @@ -305,16 +313,32 @@ void tonemap_disable (tonemaps_t *tms, u8 tmi); /** - * Force to release a tone map (without waiting). - * \param tms set of tone maps. - * \param tmi tone map index to release. - * This function can be dangerous because it's really deleted the tone map - * from the memory, even if it is still in use by the PBProc. You should use - * this function only in CE/TX or in the PBProc context. CE/RX should use the - * tonemap_disable function. + * Remove tone map from station set and add it to release list. + * \param tms set of tone maps + * \param tmi tone map index to remove + * \param tm_release_list where to add the removed tone map */ void -tonemap_release_forced (tonemaps_t *tms, u8 tmi); +tonemap_release (tonemaps_t *tms, u8 tmi, + tonemap_release_list_t *tm_release_list); + +/** + * Initialize a release list. + * \param tm_release_list the list to initialize + */ +extern inline void +tonemap_release_list_init (tonemap_release_list_t *tm_release_list) +{ + list_init (tm_release_list); +} + +/** + * Parse the release list to free the expired tonemaps. + * \param tm_release_list release list to clean + * \return true if list is now empty + */ +bool +tonemap_release_list_clean (tonemap_release_list_t *tm_release_list); /** * Copy one tone map to another. @@ -775,13 +799,14 @@ tonemaps_disabled_clean (tonemaps_t *tms); /** * Release all tone maps and reset default TMI to default value. * \param tms the set of tone maps to reset + * \param tm_release_list given to tonemap_release * * The purpose of this function is to reset the tone maps structure to sane * values to restart using them without deleting and re-allocating the pointer * (preventing some concurrency bugs). */ void -tonemaps_reset (tonemaps_t *tms); +tonemaps_reset (tonemaps_t *tms, tonemap_release_list_t *tm_release_list); /** * Get the list of tone maps enabled. -- cgit v1.2.3