summaryrefslogtreecommitdiff
path: root/cesar/mac/common
diff options
context:
space:
mode:
authorCyril Jourdan2011-07-06 11:55:21 +0200
committerCyril Jourdan2011-07-20 14:45:33 +0200
commit839e26e4706c719ec2732032f7bb5dd9e2015001 (patch)
tree7fe13348faedac4fb4e5063d6515aa8ea85cef52 /cesar/mac/common
parent27a45dbed41b85129c760e8ea67977a8371db8b3 (diff)
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.
Diffstat (limited to 'cesar/mac/common')
-rw-r--r--cesar/mac/common/src/tonemap.c42
-rw-r--r--cesar/mac/common/test/fcall/src/set_tonemap.c5
-rw-r--r--cesar/mac/common/test/tonemap/src/test_tonemap.c39
-rw-r--r--cesar/mac/common/tonemap.h43
4 files changed, 111 insertions, 18 deletions
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
@@ -700,6 +700,38 @@ tonemap_increase_test (test_t t)
}
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)
{
tonemaps_t *tms = tonemaps_alloc ();
@@ -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.