Changeset 1ccbd052 in rtems
- Timestamp:
- 04/15/15 08:53:29 (8 years ago)
- Branches:
- 4.11, 5, master
- Children:
- fd53d25
- Parents:
- 6d253941
- git-author:
- Sebastian Huber <sebastian.huber@…> (04/15/15 08:53:29)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (05/19/15 10:00:43)
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
cpukit/rtems/src/timercreate.c
r6d253941 r1ccbd052 30 30 { 31 31 Timer_server_Control *timer_server; 32 ISR_Level level; 33 34 /* The timer class must not change during the cancel operation */ 35 _ISR_Disable( level ); 32 36 33 37 switch ( the_timer->the_class ) { … … 47 51 break; 48 52 } 53 54 _ISR_Enable( level ); 49 55 } 50 56 -
cpukit/score/include/rtems/score/watchdogimpl.h
r6d253941 r1ccbd052 47 47 48 48 /** 49 * @brief Iterator item to synchronize concurrent insert, remove and tickle 50 * operations. 51 */ 52 typedef struct { 53 /** 54 * @brief A node for a Watchdog_Header::Iterators chain. 55 */ 56 Chain_Node Node; 57 58 /** 59 * @brief The current delta interval of the new watchdog to insert. 60 */ 61 Watchdog_Interval delta_interval; 62 63 /** 64 * @brief The current watchdog of the chain on the way to insert the new 65 * watchdog. 66 */ 67 Chain_Node *current; 68 } Watchdog_Iterator; 69 70 /** 49 71 * @brief Watchdog header. 50 72 */ … … 59 81 */ 60 82 Chain_Control Watchdogs; 83 84 /** 85 * @brief Currently active iterators. 86 * 87 * The iterators are registered in _Watchdog_Insert() and updated in case the 88 * watchdog chain changes. 89 */ 90 Chain_Control Iterators; 61 91 } Watchdog_Header; 62 63 /**64 * @brief Watchdog synchronization level.65 *66 * This used for synchronization purposes67 * during an insert on a watchdog delta chain.68 */69 SCORE_EXTERN volatile uint32_t _Watchdog_Sync_level;70 71 /**72 * @brief Watchdog synchronization count.73 *74 * This used for synchronization purposes75 * during an insert on a watchdog delta chain.76 */77 SCORE_EXTERN volatile uint32_t _Watchdog_Sync_count;78 92 79 93 /** … … 135 149 */ 136 150 Watchdog_States _Watchdog_Remove ( 151 Watchdog_Header *header, 152 Watchdog_Control *the_watchdog 153 ); 154 155 /** 156 * @brief Actually removes an WATCHDOG_ACTIVE or WATCHDOG_REMOVE_IT watchdog. 157 * 158 * @see _Watchdog_Remove() and _Watchdog_Tickle(). 159 */ 160 void _Watchdog_Remove_it( 137 161 Watchdog_Header *header, 138 162 Watchdog_Control *the_watchdog … … 438 462 ) 439 463 { 464 _ISR_lock_Initialize( &header->Lock, "Watchdog" ); 440 465 _Chain_Initialize_empty( &header->Watchdogs ); 466 _Chain_Initialize_empty( &header->Iterators ); 441 467 } 442 468 -
cpukit/score/src/watchdog.c
r6d253941 r1ccbd052 26 26 void _Watchdog_Handler_initialization( void ) 27 27 { 28 _Watchdog_Sync_count = 0;29 _Watchdog_Sync_level = 0;30 28 _Watchdog_Ticks_since_boot = 0; 31 29 -
cpukit/score/src/watchdoginsert.c
r6d253941 r1ccbd052 20 20 21 21 #include <rtems/score/watchdogimpl.h> 22 #include <rtems/score/isrlevel.h> 23 #include <rtems/score/percpu.h> 22 23 static void _Watchdog_Insert_fixup( 24 Watchdog_Header *header, 25 Watchdog_Control *next_watchdog, 26 Watchdog_Interval delta 27 ) 28 { 29 const Chain_Node *iterator_tail; 30 Chain_Node *iterator_node; 31 32 next_watchdog->delta_interval -= delta; 33 34 iterator_node = _Chain_First( &header->Iterators ); 35 iterator_tail = _Chain_Immutable_tail( &header->Iterators ); 36 37 while ( iterator_node != iterator_tail ) { 38 Watchdog_Iterator *iterator; 39 40 iterator = (Watchdog_Iterator *) iterator_node; 41 42 if ( iterator->current == &next_watchdog->Node ) { 43 iterator->delta_interval -= delta; 44 } 45 46 iterator_node = _Chain_Next( iterator_node ); 47 } 48 } 24 49 25 50 void _Watchdog_Insert( 26 Watchdog_Header 27 Watchdog_Control 51 Watchdog_Header *header, 52 Watchdog_Control *the_watchdog 28 53 ) 29 54 { 30 ISR_lock_Context lock_context; 31 Watchdog_Control *after; 32 uint32_t insert_isr_nest_level; 33 Watchdog_Interval delta_interval; 34 35 36 insert_isr_nest_level = _ISR_Nest_level; 55 ISR_lock_Context lock_context; 37 56 38 57 _Watchdog_Acquire( header, &lock_context ); 39 58 40 /* 41 * Check to see if the watchdog has just been inserted by a 42 * higher priority interrupt. If so, abandon this insert. 43 */ 59 if ( the_watchdog->state == WATCHDOG_INACTIVE ) { 60 Watchdog_Iterator iterator; 61 Chain_Node *current; 62 Chain_Node *next; 63 Watchdog_Interval delta; 44 64 45 if ( the_watchdog->state != WATCHDOG_INACTIVE ) { 46 _Watchdog_Release( header, &lock_context ); 47 return; 65 the_watchdog->state = WATCHDOG_BEING_INSERTED; 66 67 _Chain_Append_unprotected( &header->Iterators, &iterator.Node ); 68 69 delta = the_watchdog->initial; 70 current = _Chain_Head( &header->Watchdogs ); 71 72 while ( 73 ( next = _Chain_Next( current ) ) != _Chain_Tail( &header->Watchdogs ) 74 ) { 75 Watchdog_Control *next_watchdog; 76 Watchdog_Interval delta_next; 77 78 next_watchdog = (Watchdog_Control *) next; 79 delta_next = next_watchdog->delta_interval; 80 81 if ( delta < delta_next ) { 82 _Watchdog_Insert_fixup( header, next_watchdog, delta ); 83 break; 84 } 85 86 iterator.delta_interval = delta - delta_next; 87 iterator.current = next; 88 89 _Watchdog_Flash( header, &lock_context ); 90 91 if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) { 92 goto abort_insert; 93 } 94 95 delta = iterator.delta_interval; 96 current = iterator.current; 97 } 98 99 the_watchdog->delta_interval = delta; 100 the_watchdog->start_time = _Watchdog_Ticks_since_boot; 101 _Watchdog_Activate( the_watchdog ); 102 _Chain_Insert_unprotected( current, &the_watchdog->Node ); 103 104 abort_insert: 105 106 _Chain_Extract_unprotected( &iterator.Node ); 48 107 } 49 108 50 the_watchdog->state = WATCHDOG_BEING_INSERTED;51 _Watchdog_Sync_count++;52 53 restart:54 delta_interval = the_watchdog->initial;55 56 for ( after = _Watchdog_First( header ) ;57 ;58 after = _Watchdog_Next( after ) ) {59 60 if ( delta_interval == 0 || !_Watchdog_Next( after ) )61 break;62 63 if ( delta_interval < after->delta_interval ) {64 after->delta_interval -= delta_interval;65 break;66 }67 68 delta_interval -= after->delta_interval;69 70 _Watchdog_Flash( header, &lock_context );71 72 if ( the_watchdog->state != WATCHDOG_BEING_INSERTED ) {73 goto exit_insert;74 }75 76 if ( _Watchdog_Sync_level > insert_isr_nest_level ) {77 _Watchdog_Sync_level = insert_isr_nest_level;78 goto restart;79 }80 }81 82 _Watchdog_Activate( the_watchdog );83 84 the_watchdog->delta_interval = delta_interval;85 86 _Chain_Insert_unprotected( after->Node.previous, &the_watchdog->Node );87 88 the_watchdog->start_time = _Watchdog_Ticks_since_boot;89 90 exit_insert:91 _Watchdog_Sync_level = insert_isr_nest_level;92 _Watchdog_Sync_count--;93 109 _Watchdog_Release( header, &lock_context ); 94 110 } -
cpukit/score/src/watchdogremove.c
r6d253941 r1ccbd052 19 19 #endif 20 20 21 #include <rtems/system.h>22 #include <rtems/score/isr.h>23 21 #include <rtems/score/watchdogimpl.h> 22 #include <rtems/score/assert.h> 23 24 void _Watchdog_Remove_it( 25 Watchdog_Header *header, 26 Watchdog_Control *the_watchdog 27 ) 28 { 29 Chain_Node *next; 30 Watchdog_Interval delta; 31 const Chain_Node *iterator_tail; 32 Chain_Node *iterator_node; 33 34 _Assert( 35 the_watchdog->state == WATCHDOG_ACTIVE 36 || the_watchdog->state == WATCHDOG_REMOVE_IT 37 ); 38 39 the_watchdog->state = WATCHDOG_INACTIVE; 40 the_watchdog->stop_time = _Watchdog_Ticks_since_boot; 41 42 next = _Chain_Next( &the_watchdog->Node ); 43 delta = the_watchdog->delta_interval; 44 45 if ( next != _Chain_Tail( &header->Watchdogs ) ) { 46 Watchdog_Control *next_watchdog; 47 48 next_watchdog = (Watchdog_Control *) next; 49 next_watchdog->delta_interval += delta; 50 } 51 52 _Chain_Extract_unprotected( &the_watchdog->Node ); 53 54 iterator_node = _Chain_First( &header->Iterators ); 55 iterator_tail = _Chain_Immutable_tail( &header->Iterators ); 56 57 while ( iterator_node != iterator_tail ) { 58 Watchdog_Iterator *iterator; 59 60 iterator = (Watchdog_Iterator *) iterator_node; 61 62 if ( iterator->current == next ) { 63 iterator->delta_interval += delta; 64 } 65 66 if ( iterator->current == &the_watchdog->Node ) { 67 iterator->current = _Chain_Previous( &the_watchdog->Node ); 68 } 69 70 iterator_node = _Chain_Next( iterator_node ); 71 } 72 } 24 73 25 74 Watchdog_States _Watchdog_Remove( … … 30 79 ISR_lock_Context lock_context; 31 80 Watchdog_States previous_state; 32 Watchdog_ Control *next_watchdog;81 Watchdog_Interval now; 33 82 34 83 _Watchdog_Acquire( header, &lock_context ); … … 45 94 */ 46 95 the_watchdog->state = WATCHDOG_INACTIVE; 96 now = _Watchdog_Ticks_since_boot; 97 the_watchdog->start_time = now; 98 the_watchdog->stop_time = now; 47 99 break; 48 100 49 101 case WATCHDOG_ACTIVE: 50 102 case WATCHDOG_REMOVE_IT: 51 52 the_watchdog->state = WATCHDOG_INACTIVE; 53 next_watchdog = _Watchdog_Next( the_watchdog ); 54 55 if ( _Watchdog_Next(next_watchdog) ) 56 next_watchdog->delta_interval += the_watchdog->delta_interval; 57 58 if ( _Watchdog_Sync_count ) 59 _Watchdog_Sync_level = _ISR_Nest_level; 60 61 _Chain_Extract_unprotected( &the_watchdog->Node ); 103 _Watchdog_Remove_it( header, the_watchdog ); 62 104 break; 63 105 } 64 the_watchdog->stop_time = _Watchdog_Ticks_since_boot;65 106 66 107 _Watchdog_Release( header, &lock_context ); -
cpukit/score/src/watchdogtickle.c
r6d253941 r1ccbd052 20 20 21 21 #include <rtems/score/watchdogimpl.h> 22 #include <rtems/score/isrlevel.h>23 22 24 23 void _Watchdog_Tickle( … … 26 25 ) 27 26 { 28 ISR_lock_Context lock_context; 29 Watchdog_Control *the_watchdog; 30 Watchdog_States watchdog_state; 31 32 /* 33 * See the comment in watchdoginsert.c and watchdogadjust.c 34 * about why it's safe not to declare header a pointer to 35 * volatile data - till, 2003/7 36 */ 27 ISR_lock_Context lock_context; 37 28 38 29 _Watchdog_Acquire( header, &lock_context ); 39 30 40 if ( _Watchdog_Is_empty( header ) ) 41 goto leave; 31 if ( !_Watchdog_Is_empty( header ) ) { 32 Watchdog_Control *first; 33 Watchdog_Interval delta; 42 34 43 the_watchdog = _Watchdog_First( header ); 35 first = _Watchdog_First( header ); 36 delta = first->delta_interval; 44 37 45 /* 46 * For some reason, on rare occasions the_watchdog->delta_interval 47 * of the head of the watchdog chain is 0. Before this test was 48 * added, on these occasions an event (which usually was supposed 49 * to have a timeout of 1 tick would have a delta_interval of 0, which 50 * would be decremented to 0xFFFFFFFF by the unprotected 51 * "the_watchdog->delta_interval--;" operation. 52 * This would mean the event would not timeout, and also the chain would 53 * be blocked, because a timeout with a very high number would be at the 54 * head, rather than at the end. 55 * The test "if (the_watchdog->delta_interval != 0)" 56 * here prevents this from occuring. 57 * 58 * We were not able to categorically identify the situation that causes 59 * this, but proved it to be true empirically. So this check causes 60 * correct behaviour in this circumstance. 61 * 62 * The belief is that a race condition exists whereby an event at the head 63 * of the chain is removed (by a pending ISR or higher priority task) 64 * during the _ISR_Flash( level ); in _Watchdog_Insert, but the watchdog 65 * to be inserted has already had its delta_interval adjusted to 0, and 66 * so is added to the head of the chain with a delta_interval of 0. 67 * 68 * Steven Johnson - 12/2005 (gcc-3.2.3 -O3 on powerpc) 69 */ 70 if (the_watchdog->delta_interval != 0) { 71 the_watchdog->delta_interval--; 72 if ( the_watchdog->delta_interval != 0 ) 73 goto leave; 38 /* 39 * Although it is forbidden to insert watchdogs with a delta interval of 40 * zero it is possible to observe watchdogs with a delta interval of zero 41 * at this point. For example lets have a watchdog chain of one watchdog 42 * with a delta interval of one and insert a new one with an initial value 43 * of one. At the start of the insert procedure it will advance one step 44 * and reduce its delta interval by one yielding zero. Now a tick happens. 45 * This will remove the watchdog on the chain and update the insert 46 * iterator. Now the insert operation continues and will insert the new 47 * watchdog with a delta interval of zero. 48 */ 49 if ( delta > 0 ) { 50 --delta; 51 first->delta_interval = delta; 52 } 53 54 while ( delta == 0 ) { 55 bool run; 56 Watchdog_Service_routine_entry routine; 57 Objects_Id id; 58 void *user_data; 59 60 run = ( first->state == WATCHDOG_ACTIVE ); 61 62 _Watchdog_Remove_it( header, first ); 63 64 routine = first->routine; 65 id = first->id; 66 user_data = first->user_data; 67 68 _Watchdog_Release( header, &lock_context ); 69 70 if ( run ) { 71 (*routine)( id, user_data ); 72 } 73 74 _Watchdog_Acquire( header, &lock_context ); 75 76 if ( _Watchdog_Is_empty( header ) ) { 77 break; 78 } 79 80 first = _Watchdog_First( header ); 81 delta = first->delta_interval; 82 } 74 83 } 75 84 76 do { 77 watchdog_state = _Watchdog_Remove( header, the_watchdog ); 78 79 _Watchdog_Release( header, &lock_context ); 80 81 switch( watchdog_state ) { 82 case WATCHDOG_ACTIVE: 83 (*the_watchdog->routine)( 84 the_watchdog->id, 85 the_watchdog->user_data 86 ); 87 break; 88 89 case WATCHDOG_INACTIVE: 90 /* 91 * This state indicates that the watchdog is not on any chain. 92 * Thus, it is NOT on a chain being tickled. This case should 93 * never occur. 94 */ 95 break; 96 97 case WATCHDOG_BEING_INSERTED: 98 /* 99 * This state indicates that the watchdog is in the process of 100 * BEING inserted on the chain. Thus, it can NOT be on a chain 101 * being tickled. This case should never occur. 102 */ 103 break; 104 105 case WATCHDOG_REMOVE_IT: 106 break; 107 } 108 109 _Watchdog_Acquire( header, &lock_context ); 110 111 the_watchdog = _Watchdog_First( header ); 112 } while ( !_Watchdog_Is_empty( header ) && 113 (the_watchdog->delta_interval == 0) ); 114 115 leave: 116 _Watchdog_Release( header, &lock_context ); 85 _Watchdog_Release( header, &lock_context ); 117 86 } -
testsuites/sptests/spsize/size.c
r6d253941 r1ccbd052 400 400 /*userext.h*/ (sizeof _User_extensions_List) + 401 401 402 /*watchdog.h*/ (sizeof _Watchdog_Sync_level) + 403 (sizeof _Watchdog_Sync_count) + 404 (sizeof _Watchdog_Ticks_since_boot) + 402 /*watchdog.h*/ (sizeof _Watchdog_Ticks_since_boot) + 405 403 (sizeof _Watchdog_Ticks_header) + 406 404 (sizeof _Watchdog_Seconds_header) + -
testsuites/sptests/spwatchdog/init.c
r6d253941 r1ccbd052 33 33 34 34 rtems_test_assert( 0 ); 35 } 36 37 static void init_watchdogs( 38 Watchdog_Header *header, 39 Watchdog_Control watchdogs[3] 40 ) 41 { 42 Watchdog_Control *a = &watchdogs[0]; 43 Watchdog_Control *b = &watchdogs[1]; 44 Watchdog_Control *c = &watchdogs[2]; 45 Watchdog_Control *d = &watchdogs[3]; 46 47 _Watchdog_Header_initialize( header ); 48 rtems_test_assert( _Watchdog_Is_empty( header ) ); 49 rtems_test_assert( _Chain_Is_empty( &header->Iterators ) ); 50 51 _Watchdog_Initialize( c, NULL, 0, NULL ); 52 c->initial = 6; 53 _Watchdog_Insert( header, c ); 54 rtems_test_assert( c->delta_interval == 6 ); 55 56 rtems_test_assert( !_Watchdog_Is_empty( header ) ); 57 rtems_test_assert( _Chain_Is_empty( &header->Iterators ) ); 58 59 _Watchdog_Initialize( a, NULL, 0, NULL ); 60 a->initial = 2; 61 _Watchdog_Insert( header, a ); 62 rtems_test_assert( a->delta_interval == 2 ); 63 rtems_test_assert( c->delta_interval == 4 ); 64 65 _Watchdog_Initialize( b, NULL, 0, NULL ); 66 b->initial = 4; 67 _Watchdog_Insert( header, b ); 68 rtems_test_assert( a->delta_interval == 2 ); 69 rtems_test_assert( b->delta_interval == 2 ); 70 rtems_test_assert( c->delta_interval == 2 ); 71 72 _Watchdog_Initialize( d, NULL, 0, NULL ); 73 } 74 75 static void destroy_watchdogs( 76 Watchdog_Header *header 77 ) 78 { 79 _ISR_lock_Destroy( &header->Lock ); 80 } 81 82 static void add_iterator( 83 Watchdog_Header *header, 84 Watchdog_Iterator *i, 85 Watchdog_Control *w 86 ) 87 { 88 _Chain_Append_unprotected( &header->Iterators, &i->Node ); 89 i->delta_interval = 2; 90 i->current = &w->Node; 91 } 92 93 static void test_watchdog_insert_and_remove( void ) 94 { 95 Watchdog_Header header; 96 Watchdog_Control watchdogs[4]; 97 Watchdog_Control *a = &watchdogs[0]; 98 Watchdog_Control *b = &watchdogs[1]; 99 Watchdog_Control *c = &watchdogs[2]; 100 Watchdog_Control *d = &watchdogs[3]; 101 Watchdog_Iterator i; 102 103 init_watchdogs( &header, watchdogs ); 104 add_iterator( &header, &i, c ); 105 106 /* Remove next watchdog of iterator */ 107 _Watchdog_Remove( &header, c ); 108 rtems_test_assert( i.delta_interval == 2 ); 109 rtems_test_assert( i.current == &b->Node ); 110 111 /* Remove watchdog before the current watchdog of iterator */ 112 _Watchdog_Remove( &header, a ); 113 rtems_test_assert( i.delta_interval == 4 ); 114 rtems_test_assert( i.current == &b->Node ); 115 116 /* Remove current (= last) watchdog of iterator */ 117 _Watchdog_Remove( &header, b ); 118 rtems_test_assert( i.delta_interval == 4 ); 119 rtems_test_assert( i.current == _Chain_Head( &header.Watchdogs ) ); 120 121 /* Insert first watchdog */ 122 a->initial = 1; 123 _Watchdog_Insert( &header, a ); 124 rtems_test_assert( i.delta_interval == 4 ); 125 rtems_test_assert( i.current == _Chain_Head( &header.Watchdogs ) ); 126 127 destroy_watchdogs( &header ); 128 init_watchdogs( &header, watchdogs ); 129 add_iterator( &header, &i, b ); 130 131 /* Insert right before current watchdog of iterator */ 132 d->initial = 3; 133 _Watchdog_Insert( &header, d ); 134 rtems_test_assert( i.delta_interval == 1 ); 135 rtems_test_assert( i.current == &b->Node ); 136 137 destroy_watchdogs( &header ); 138 init_watchdogs( &header, watchdogs ); 139 add_iterator( &header, &i, b ); 140 141 /* Insert right after current watchdog of iterator */ 142 d->initial = 5; 143 _Watchdog_Insert( &header, d ); 144 rtems_test_assert( i.delta_interval == 2 ); 145 rtems_test_assert( i.current == &b->Node ); 146 147 destroy_watchdogs( &header ); 35 148 } 36 149 … … 71 184 72 185 test_watchdog_static_init(); 186 test_watchdog_insert_and_remove(); 73 187 74 188 build_time( &time, 12, 31, 1988, 9, 0, 0, 0 );
Note: See TracChangeset
for help on using the changeset viewer.