Mercurial > flash_v2
comparison packages/net/tcpip/current/src/ecos/timeout.c @ 115:6ed91473a1cd ecos-sw-2000-08-21
Merge from eCos master repository on 2000-08-21-22:40:54-BST
| author | jlarmour |
|---|---|
| date | Fri, 25 Aug 2000 17:32:38 +0000 |
| parents | 02ea4320376c |
| children | 6bd9d475ed4b |
comparison
equal
deleted
inserted
replaced
| 114:5ad2b71d525e | 115:6ed91473a1cd |
|---|---|
| 39 // | 39 // |
| 40 //####BSDCOPYRIGHTEND#### | 40 //####BSDCOPYRIGHTEND#### |
| 41 //========================================================================== | 41 //========================================================================== |
| 42 //#####DESCRIPTIONBEGIN#### | 42 //#####DESCRIPTIONBEGIN#### |
| 43 // | 43 // |
| 44 // Author(s): gthomas | 44 // Author(s): gthomas, hmt |
| 45 // Contributors: gthomas | 45 // Contributors: gthomas, hmt |
| 46 // Date: 1999-02-05 | 46 // Date: 1999-02-05 |
| 47 // Description: Simple timeout functions | 47 // Description: Simple timeout functions |
| 48 //####DESCRIPTIONEND#### | 48 //####DESCRIPTIONEND#### |
| 49 | 49 |
| 50 #include <sys/param.h> | 50 #include <sys/param.h> |
| 51 #include <pkgconf/net.h> | 51 #include <pkgconf/net.h> |
| 52 #include <cyg/kernel/kapi.h> | 52 #include <cyg/kernel/kapi.h> |
| 53 #include <cyg/infra/cyg_ass.h> | |
| 53 | 54 |
| 54 // Timeout support | 55 // Timeout support |
| 55 | 56 |
| 56 #ifndef NTIMEOUTS | 57 #ifndef NTIMEOUTS |
| 57 #define NTIMEOUTS 8 | 58 #define NTIMEOUTS 8 |
| 63 } timeout_entry; | 64 } timeout_entry; |
| 64 static timeout_entry timeouts[NTIMEOUTS]; | 65 static timeout_entry timeouts[NTIMEOUTS]; |
| 65 static cyg_handle_t timeout_alarm_handle; | 66 static cyg_handle_t timeout_alarm_handle; |
| 66 static cyg_alarm timeout_alarm; | 67 static cyg_alarm timeout_alarm; |
| 67 static cyg_int32 last_delta; | 68 static cyg_int32 last_delta; |
| 69 static cyg_tick_count_t last_set_time; | |
| 70 | |
| 71 extern cyg_uint32 cyg_in_softnet( void ); | |
| 68 | 72 |
| 69 static void | 73 static void |
| 70 do_timeout(cyg_handle_t alarm, cyg_addrword_t data) | 74 do_timeout(cyg_handle_t alarm, cyg_addrword_t data) |
| 71 { | 75 { |
| 72 int i; | 76 int i; |
| 73 cyg_int32 min_delta; | 77 cyg_int32 min_delta; |
| 74 timeout_entry *e = timeouts; | 78 timeout_entry *e; |
| 79 | |
| 80 CYG_ASSERT( 0 < last_delta, "last_delta underflow" ); | |
| 81 | |
| 82 min_delta = last_delta; // local copy | |
| 83 last_delta = -1; // flag recursive call underway | |
| 84 | |
| 85 for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { | |
| 86 if (e->delta) { | |
| 87 CYG_ASSERT( e->delta >= min_delta, "e->delta underflow" ); | |
| 88 e->delta -= min_delta; | |
| 89 if (e->delta <= 0) { // Defensive | |
| 90 // Time for this item to 'fire' | |
| 91 timeout_fun *fun = e->fun; | |
| 92 void *arg = e->arg; | |
| 93 // Call it *after* cleansing the record | |
| 94 e->fun = 0; | |
| 95 e->delta = 0; | |
| 96 (*fun)(arg); | |
| 97 } | |
| 98 } | |
| 99 } | |
| 100 | |
| 101 // Now scan for a new timeout *after* running all the callbacks | |
| 102 // (because they can add timeouts themselves) | |
| 75 min_delta = 0x7FFFFFFF; // Maxint | 103 min_delta = 0x7FFFFFFF; // Maxint |
| 76 for (i = 0; i < NTIMEOUTS; i++, e++) { | 104 for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) |
| 77 if (e->delta) { | 105 if (e->delta) |
| 78 e->delta -= last_delta; | 106 if (e->delta < min_delta) |
| 79 if (e->delta == 0) { | 107 min_delta = e->delta; |
| 80 // Time for this item to 'fire' | 108 |
| 81 (e->fun)(e->arg); | 109 CYG_ASSERT( 0 < min_delta, "min_delta underflow" ); |
| 82 e->fun = 0; | 110 |
| 83 } else { | |
| 84 if (e->delta < min_delta) min_delta = e->delta; | |
| 85 } | |
| 86 } | |
| 87 } | |
| 88 if (min_delta != 0x7FFFFFFF) { | 111 if (min_delta != 0x7FFFFFFF) { |
| 89 // Still something to do, schedule it | 112 // Still something to do, schedule it |
| 90 cyg_alarm_initialize(timeout_alarm_handle, cyg_current_time()+min_delta, 0); | 113 last_set_time = cyg_current_time(); |
| 114 cyg_alarm_initialize(timeout_alarm_handle, last_set_time+min_delta, 0); | |
| 91 last_delta = min_delta; | 115 last_delta = min_delta; |
| 116 } else { | |
| 117 last_delta = 0; // flag no activity | |
| 92 } | 118 } |
| 93 } | 119 } |
| 94 | 120 |
| 95 cyg_uint32 | 121 cyg_uint32 |
| 96 timeout(timeout_fun *fun, void *arg, cyg_int32 delta) | 122 timeout(timeout_fun *fun, void *arg, cyg_int32 delta) |
| 97 { | 123 { |
| 98 int i; | 124 int i; |
| 99 cyg_int32 min_delta; | |
| 100 static bool init = false; | 125 static bool init = false; |
| 101 timeout_entry *e = timeouts; | 126 timeout_entry *e; |
| 102 cyg_uint32 stamp; | 127 cyg_uint32 stamp; |
| 128 | |
| 129 CYG_ASSERT( 0 < delta, "delta is right now, or even sooner!" ); | |
| 130 | |
| 131 // this needs to be atomic wrt threads and DSRs | |
| 132 cyg_scheduler_lock(); | |
| 133 | |
| 103 if (!init) { | 134 if (!init) { |
| 104 cyg_handle_t h; | 135 cyg_handle_t h; |
| 105 cyg_clock_to_counter(cyg_real_time_clock(), &h); | 136 cyg_clock_to_counter(cyg_real_time_clock(), &h); |
| 106 cyg_alarm_create(h, do_timeout, 0, &timeout_alarm_handle, &timeout_alarm); | 137 cyg_alarm_create(h, do_timeout, 0, &timeout_alarm_handle, &timeout_alarm); |
| 107 init = true; | 138 init = true; |
| 108 } | 139 } |
| 140 | |
| 141 // Renormalize delta wrt the existing set alarm, if there is one | |
| 142 if ( last_delta > 0 ) | |
| 143 delta += (cyg_int32)(cyg_current_time() - last_set_time); | |
| 144 // So recorded_delta is set to either: | |
| 145 // alarm is active: delta + NOW - THEN | |
| 146 // alarm is inactive: delta | |
| 147 | |
| 109 stamp = 0; // Assume no slots available | 148 stamp = 0; // Assume no slots available |
| 110 for (i = 0; i < NTIMEOUTS; i++, e++) { | 149 for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { |
| 111 if ((e->delta == 0) && (e->fun == 0)) { | 150 if ((e->delta == 0) && (e->fun == 0)) { |
| 112 // Free entry | 151 // Free entry |
| 113 e->delta = delta; | 152 e->delta = delta; |
| 114 e->fun = fun; | 153 e->fun = fun; |
| 115 e->arg = arg; | 154 e->arg = arg; |
| 116 stamp = (cyg_uint32)e; | 155 stamp = (cyg_uint32)e; |
| 117 break; | 156 break; |
| 118 } | 157 } |
| 119 } | 158 } |
| 120 e = timeouts; | 159 |
| 121 min_delta = 0x7FFFFFFF; | 160 if ( stamp && // we did add a record AND |
| 122 for (i = 0; i < NTIMEOUTS; i++, e++) { | 161 (0 == last_delta || // alarm was inactive OR |
| 123 if (e->delta && (e->delta < min_delta)) min_delta = e->delta; | 162 delta < last_delta) ) { // alarm was active but later than we need |
| 124 } | 163 |
| 125 if (min_delta != 0x7FFFFFFF) { | 164 // (if last_delta is -1, this call is recursive from the handler so |
| 126 // Still something to do, schedule it | 165 // also do nothing in that case) |
| 127 cyg_alarm_initialize(timeout_alarm_handle, cyg_current_time()+min_delta, 0); | 166 |
| 128 last_delta = min_delta; | 167 // Here, we know the new item added is sooner than that which was |
| 129 } | 168 // most recently set, if any, so we can just go and set it up. |
| 169 if ( 0 == last_delta ) | |
| 170 last_set_time = cyg_current_time(); | |
| 171 | |
| 172 // So we use, to set the alarm either: | |
| 173 // alarm is active: (delta + NOW - THEN) + THEN | |
| 174 // alarm is inactive: delta + NOW | |
| 175 // and in either case it is true that | |
| 176 // (recorded_delta + last_set_time) == (delta + NOW) | |
| 177 cyg_alarm_initialize(timeout_alarm_handle, last_set_time+delta, 0); | |
| 178 last_delta = delta; | |
| 179 } | |
| 180 // Otherwise, the alarm is active, AND it is set to fire sooner than we | |
| 181 // require, so when it does, that will sort out calling the item we | |
| 182 // just added. Or we didn't actually add a record, so nothing has | |
| 183 // changed. | |
| 184 | |
| 185 #ifdef CYGPKG_INFRA_DEBUG | |
| 186 // Do some more checking akin to that in the alarm handler: | |
| 187 if ( last_delta != -1 ) { // not a recursive call | |
| 188 CYG_ASSERT( last_delta >= 0, "Bad last delta" ); | |
| 189 delta = 0x7fffffff; | |
| 190 for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { | |
| 191 if (e->delta) { | |
| 192 CYG_ASSERT( e->delta >= last_delta, "e->delta underflow" ); | |
| 193 CYG_ASSERT( last_set_time + e->delta > cyg_current_time(), | |
| 194 "Recorded alarm not in the future!" ); | |
| 195 if ( e->delta < delta ) | |
| 196 delta = e->delta; | |
| 197 } else { | |
| 198 CYG_ASSERT( 0 == e->fun, "Function recorded for 0 delta" ); | |
| 199 } | |
| 200 } | |
| 201 CYG_ASSERT( delta == last_delta, "We didn't pick the smallest delta!" ); | |
| 202 } | |
| 203 #endif | |
| 204 | |
| 205 cyg_scheduler_unlock(); | |
| 206 | |
| 130 return stamp; | 207 return stamp; |
| 131 } | 208 } |
| 132 | 209 |
| 133 void | 210 void |
| 134 untimeout(timeout_fun *fun, void * arg) | 211 untimeout(timeout_fun *fun, void * arg) |
| 135 { | 212 { |
| 136 int i; | 213 int i; |
| 137 timeout_entry *e = timeouts; | 214 timeout_entry *e; |
| 138 | 215 cyg_scheduler_lock(); |
| 139 for (i = 0; i < NTIMEOUTS; i++, e++) { | 216 for (e = timeouts, i = 0; i < NTIMEOUTS; i++, e++) { |
| 140 if (e->delta && (e->fun == fun) && (e->arg == arg)) { | 217 if (e->delta && (e->fun == fun) && (e->arg == arg)) { |
| 141 e->delta = 0; | 218 e->delta = 0; |
| 142 e->fun = 0; | 219 e->fun = 0; |
| 143 return; | 220 break; |
| 144 } | 221 } |
| 145 } | 222 } |
| 223 cyg_scheduler_unlock(); | |
| 146 } | 224 } |
| 147 | 225 |
| 226 // EOF timeout.c |
