This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
Kernel clock scan fix
- From: Nick Garnett <nickg at calivar dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: 13 Oct 2003 18:21:29 +0100
- Subject: Kernel clock scan fix
Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/ChangeLog,v
retrieving revision 1.111
diff -u -5 -r1.111 ChangeLog
--- ChangeLog 26 Sep 2003 17:41:30 -0000 1.111
+++ ChangeLog 13 Oct 2003 17:19:39 -0000
@@ -1,5 +1,13 @@
+2003-10-13 Nick Garnett <nickg@balti.calivar.com>
+
+ * src/common/clock.cxx (Cyg_Counter::tick): Changed code to deal
+ with manipulation of unsorted lists (see ChangeLogs passim). There
+ are several corner cases where the current code does not
+ work. Replaced with a more straightforward, but slightly more
+ expensive, implementation.
+
2003-09-22 Reinhard Jessich <Reinhard.Jessich@frequentis.com>
* src/common/clock.cxx: Removed label/goto
add_alarm_unlock_return to get rid of compiler error when
CYGIMP_KERNEL_COUNTERS_SORT_LIST is enabled.
Index: src/common/clock.cxx
===================================================================
RCS file: /cvs/ecos/ecos/packages/kernel/current/src/common/clock.cxx,v
retrieving revision 1.19
diff -u -5 -r1.19 clock.cxx
--- src/common/clock.cxx 26 Sep 2003 17:41:31 -0000 1.19
+++ src/common/clock.cxx 13 Oct 2003 17:19:50 -0000
@@ -214,76 +214,62 @@
// With unsorted lists we must scan the whole list for
// candidates. However, we must be careful here since it is
// possible for the function of one alarm to add or remove
// other alarms to/from this list. Having the list shift under
// our feet in this way could be disasterous. We solve this by
- // detecting when the list has changed and restarting the scan
- // from the beginning.
-
- Cyg_DNode_T<Cyg_Alarm> *node = alarm_list_ptr->get_head();
+ // restarting the scan from the beginning whenever we call an
+ // alarm function.
- while( node != NULL )
+ cyg_bool rescan = true;
+
+ while( rescan )
{
- Cyg_Alarm *alarm = CYG_CLASSFROMBASE( Cyg_Alarm, Cyg_DNode, node );
- Cyg_DNode_T<Cyg_Alarm> *next = alarm->get_next();
+ Cyg_DNode_T<Cyg_Alarm> *node = alarm_list_ptr->get_head();
- CYG_ASSERTCLASS(alarm, "Bad alarm in counter list" );
+ rescan = false;
- if( alarm->trigger <= counter )
+ while( node != NULL )
{
- Cyg_DNode *next_next, *next_prev;
- Cyg_Alarm *head;
-
- alarm_list_ptr->remove(alarm);
+ Cyg_Alarm *alarm = CYG_CLASSFROMBASE( Cyg_Alarm, Cyg_DNode, node );
+ Cyg_DNode_T<Cyg_Alarm> *next = alarm->get_next();
- // Save some details of the list state so we can
- // detect if it has changed.
- next_next = next->get_next();
- next_prev = next->get_prev();
- head = alarm_list_ptr->get_head();
-
- if( alarm->interval != 0 )
+ CYG_ASSERTCLASS(alarm, "Bad alarm in counter list" );
+
+ if( alarm->trigger <= counter )
{
- // The alarm has a retrigger interval.
- // Reset the trigger time and requeue
- // the alarm.
- alarm->trigger += alarm->interval;
- add_alarm( alarm );
- }
- else alarm->enabled = false;
+ alarm_list_ptr->remove(alarm);
- CYG_INSTRUMENT_ALARM( CALL, this, alarm );
-
- // Call alarm function
- alarm->alarm(alarm, alarm->data);
+ if( alarm->interval != 0 )
+ {
+ // The alarm has a retrigger interval.
+ // Reset the trigger time and requeue
+ // the alarm.
+ alarm->trigger += alarm->interval;
+ add_alarm( alarm );
+ }
+ else alarm->enabled = false;
- // If that alarm function has added or removed an
- // alarm on this list that might affect this scan,
- // then start again from beginning. The main test here
- // is whether the link fields of the next node have
- // changed, implying that it may have been moved. The
- // test against the list head detects the case where
- // the next node was the only node in the list, when
- // moving is would have left the links unchanged.
+ CYG_INSTRUMENT_ALARM( CALL, this, alarm );
- if( next_next != next->get_next() ||
- next_prev != next->get_prev() ||
- head != alarm_list_ptr->get_head() )
- {
- node = alarm_list_ptr->get_head();
- continue;
+ // Call alarm function
+ alarm->alarm(alarm, alarm->data);
+
+ rescan = true;
+
+ break;
}
+
+ // If the next node is the head of the list, then we have
+ // looped all the way around. The node == next test
+ // catches the case where we only had one element to start
+ // with.
+ if( next == alarm_list_ptr->get_head() || node == next )
+ node = NULL;
+ else
+ node = next;
}
- // If the next node is the head of the list, then we have
- // looped all the way around. The node == next test
- // catches the case where we only had one element to start
- // with.
- if( next == alarm_list_ptr->get_head() || node == next )
- node = NULL;
- else
- node = next;
}
#endif
Cyg_Scheduler::unlock();
--
Nick Garnett eCos Kernel Architect
http://www.ecoscentric.com The eCos and RedBoot experts